*/
public void execute() throws HgMissingConfigElementException, HgIOException, HgException {
try {
ConfigFile cfgRead = new ConfigFile(sessionCtx);
cfgRead.addLocation(configFile);
ConfigFileParser cfgWrite = new ConfigFileParser();
FileInputStream fis = new FileInputStream(configFile);
cfgWrite.parse(fis);
fis.close();
for (Operation op : changes) {
if (!ignoreMissingKeys && !cfgRead.hasSection(op.section)) {
throw new HgMissingConfigElementException("Bad section name", op.section, op.key);
}
Map<String, String> sect = cfgRead.getSection(op.section);
if (!ignoreMissingKeys && !sect.containsKey(op.key)) {
throw new HgMissingConfigElementException("Bad key name", op.section, op.key);
}
String oldValue = sect.get(op.key);
if (oldValue == null) {
oldValue = "";
}
switch (op.kind) {
case AddValue: {
String separator = ", "; // XXX shall parse and find out separator kind in use
String newValue = oldValue + separator + op.value;
if (sect.containsKey(op.key)) {
cfgWrite.change(op.section, op.key, newValue);
} else {
cfgWrite.add(op.section, op.key, newValue);
}
break;
}
case DelValue: {
if (!ignoreMissingKeys && (oldValue.length() == 0 || !oldValue.contains(op.value))) {
throw new HgMissingConfigElementException(String.format("Bad value '%s' to delete from '%s'", op.value, oldValue), op.section, op.key);
}
int start = oldValue.indexOf(op.value);
if (start == -1) {
// nothing to change
break;
}
int commaPos = -1;
for (int i = start-1; i >=0; i--) {
if (oldValue.charAt(i) == ',') {
commaPos = i;
break;
}
}
for (int i = start + op.value.length(); commaPos == -1 && i < oldValue.length(); i++) {
if (oldValue.charAt(i) == ',') {
commaPos = i;
break;
}
}
String newValue;
if (commaPos >= 0) {
if (commaPos < start) {
// from preceding comma up to end of value
newValue = oldValue.substring(0, commaPos) + oldValue.substring(start + op.value.length());
} else {
// from value start up to and including subsequent comma
newValue = oldValue.substring(0, start) + oldValue.substring(commaPos+1);
}
} else {
// found no separator, just remove the value
// extra whitespaces (if space, not a comma is a separator) won't hurt
newValue = oldValue.substring(0, start) + oldValue.substring(start + op.value.length());
}
cfgWrite.change(op.section, op.key, newValue);
break;
}
case SetValue: {
if (sect.containsKey(op.key)) {
cfgWrite.change(op.section, op.key, op.value);
} else {
cfgWrite.add(op.section, op.key, op.value);
}
break;
}
case DelEntry: {
cfgWrite.delete(op.section, op.key);
break;
}
default: throw new HgInvalidStateException(String.format("Unknown change %s", op.kind));
}
}
FileOutputStream fos = new FileOutputStream(configFile);
cfgWrite.update(fos);
fos.close();
} catch (IOException ex) {
String m = String.format("Failed to update configuration file %s", configFile);
throw new HgBadArgumentException(m, ex); // TODO [post-1.0] better exception, it's not bad argument case
}