diff src/org/tmatesoft/hg/internal/ConfigFile.java @ 378:9fb990c8a724

Investigate approaches to alter Mercurial configuration files
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 09 Feb 2012 04:15:17 +0100
parents a37ce7145c3f
children e31e85cf4d4c
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/ConfigFile.java	Thu Feb 02 16:16:19 2012 +0100
+++ b/src/org/tmatesoft/hg/internal/ConfigFile.java	Thu Feb 09 04:15:17 2012 +0100
@@ -17,11 +17,18 @@
 package org.tmatesoft.hg.internal;
 
 import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -52,7 +59,7 @@
 	}
 
 	public Map<String,String> getSection(String sectionName) {
-		if (sections ==  null) {
+		if (sections == null) {
 			return Collections.emptyMap();
 		}
 		int x = sections.indexOf(sectionName);
@@ -79,7 +86,31 @@
 		String value = getSection(sectionName).get(key);
 		return value == null ? defaultValue : value;
 	}
-
+	
+	public void putString(String sectionName, String key, String newValue) {
+		Map<String, String> section = null;
+		if (sections == null) {
+			// init, in case we didn't read any file with prev config
+			sections = new ArrayList<String>();
+			content = new ArrayList<Map<String,String>>();
+		}
+		int x = sections.indexOf(sectionName);
+		if (x == -1) {
+			if (newValue == null) {
+				return;
+			}
+			sections.add(sectionName);
+			content.add(section = new LinkedHashMap<String, String>());
+		} else {
+			section = content.get(x);
+		}
+		if (newValue == null) {
+			section.remove(key);
+		} else {
+			section.put(key, newValue);
+		}
+	}
+	
 	// TODO handle %include and %unset directives
 	// TODO "" and lists
 	// XXX perhaps, single string to keep whole section with substrings for keys/values to minimize number of arrays (String.value)
@@ -141,4 +172,42 @@
 		}
 		assert sections.size() == content.size();
 	}
+
+	public void writeTo(File f) throws IOException {
+		byte[] data = compose();
+		if (!f.exists()) {
+			f.createNewFile();
+		}
+		FileChannel fc = new FileOutputStream(f).getChannel();
+		FileLock fl = fc.lock();
+		try {
+			fc.write(ByteBuffer.wrap(data));
+		} finally {
+			fl.release();
+			fc.close();
+		}
+	}
+	
+	private byte[] compose() {
+		ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
+		PrintStream ps = new PrintStream(bos);
+		Iterator<String> sectionNames = sections.iterator();
+		for (Map<String,String> s : content) {
+			final String name = sectionNames.next(); // iterate through names despite section may be empty
+			if (s.isEmpty()) {
+				continue; // do not write an empty section
+			}
+			ps.print('[');
+			ps.print(name);
+			ps.println(']');
+			for (Map.Entry<String, String> e : s.entrySet()) {
+				ps.print(e.getKey());
+				ps.print('=');
+				ps.println(e.getValue());
+			}
+			ps.println();
+		}
+		ps.flush();
+		return bos.toByteArray();
+	}
 }