From 48e9a010ae9cfee5cc2daae2bf20d510ab9c108f Mon Sep 17 00:00:00 2001
From: "Shawn O. Pearce" <spearce@spearce.org>
Date: Thu, 28 Jan 2010 11:10:52 -0800
Subject: [PATCH] Add unsetSection to Config to remove an entire block

The unsetSection method can be used to delete an entire configuration
block, such as a [branch ""] or [remote ""] section in a file.

Change-Id: I93390c9b2187eb1b0d51353518feaed83bed2aad
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../jgit/lib/RepositoryConfigTest.java        | 41 ++++++++++++++++++
 .../src/org/eclipse/jgit/lib/Config.java      | 42 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java
index 203b7c825..41c4971a0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java
@@ -271,6 +271,47 @@ public void testEmptyString() throws ConfigInvalidException {
 		assertEquals("[my]\n\tempty =\n", c.toText());
 	}
 
+	public void testUnsetBranchSection() throws ConfigInvalidException {
+		Config c = parse("" //
+				+ "[branch \"keep\"]\n"
+				+ "  merge = master.branch.to.keep.in.the.file\n"
+				+ "\n"
+				+ "[branch \"remove\"]\n"
+				+ "  merge = this.will.get.deleted\n"
+				+ "  remote = origin-for-some-long-gone-place\n"
+				+ "\n"
+				+ "[core-section-not-to-remove-in-test]\n"
+				+ "  packedGitLimit = 14\n");
+		c.unsetSection("branch", "does.not.exist");
+		c.unsetSection("branch", "remove");
+		assertEquals("" //
+				+ "[branch \"keep\"]\n"
+				+ "  merge = master.branch.to.keep.in.the.file\n"
+				+ "\n"
+				+ "[core-section-not-to-remove-in-test]\n"
+				+ "  packedGitLimit = 14\n", c.toText());
+	}
+
+	public void testUnsetSingleSection() throws ConfigInvalidException {
+		Config c = parse("" //
+				+ "[branch \"keep\"]\n"
+				+ "  merge = master.branch.to.keep.in.the.file\n"
+				+ "\n"
+				+ "[single]\n"
+				+ "  merge = this.will.get.deleted\n"
+				+ "  remote = origin-for-some-long-gone-place\n"
+				+ "\n"
+				+ "[core-section-not-to-remove-in-test]\n"
+				+ "  packedGitLimit = 14\n");
+		c.unsetSection("single", null);
+		assertEquals("" //
+				+ "[branch \"keep\"]\n"
+				+ "  merge = master.branch.to.keep.in.the.file\n"
+				+ "\n"
+				+ "[core-section-not-to-remove-in-test]\n"
+				+ "  packedGitLimit = 14\n", c.toText());
+	}
+
 	private void assertReadLong(long exp) throws ConfigInvalidException {
 		assertReadLong(exp, String.valueOf(exp));
 	}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
index d66aa74c8..0d0c377f8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -576,6 +576,43 @@ public void unset(final String section, final String subsection,
 				.<String> emptyList());
 	}
 
+	/**
+	 * Remove all configuration values under a single section.
+	 *
+	 * @param section
+	 *            section name, e.g "branch"
+	 * @param subsection
+	 *            optional subsection value, e.g. a branch name
+	 */
+	public void unsetSection(String section, String subsection) {
+		State src, res;
+		do {
+			src = state.get();
+			res = unsetSection(src, section, subsection);
+		} while (!state.compareAndSet(src, res));
+	}
+
+	private State unsetSection(final State srcState, final String section,
+			final String subsection) {
+		final int max = srcState.entryList.size();
+		final ArrayList<Entry> r = new ArrayList<Entry>(max);
+
+		boolean lastWasMatch = false;
+		for (Entry e : srcState.entryList) {
+			if (e.match(section, subsection)) {
+				// Skip this record, it's for the section we are removing.
+				lastWasMatch = true;
+				continue;
+			}
+
+			if (lastWasMatch && e.section == null && e.subsection == null)
+				continue; // skip this padding line in the section.
+			r.add(e);
+		}
+
+		return newState(r);
+	}
+
 	/**
 	 * Set a configuration value.
 	 *
@@ -1104,6 +1141,11 @@ && eqSameCase(subsection, aSubsection)
 					&& eqIgnoreCase(name, aKey);
 		}
 
+		boolean match(final String aSection, final String aSubsection) {
+			return eqIgnoreCase(section, aSection)
+					&& eqSameCase(subsection, aSubsection);
+		}
+
 		private static boolean eqIgnoreCase(final String a, final String b) {
 			if (a == null && b == null)
 				return true;
-- 
GitLab