From 9908c203a5fc8bb59e6b539d94c558a516247161 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 1 Mar 2012 17:37:41 -0800 Subject: [PATCH] Support insteadOf and pushInsteadOf URL replacement Bug: 346873 Change-Id: I4116328f93f411da56a633bc32fd064b2ac083f2 Signed-off-by: Chris Aniszczyk --- .../jgit/transport/RemoteConfigTest.java | 63 +++++++++++++++++++ .../eclipse/jgit/transport/RemoteConfig.java | 43 ++++++++++++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java index 03a6c019e..0cada5c7e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java @@ -50,6 +50,7 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.util.Arrays; import java.util.List; import org.eclipse.jgit.errors.ConfigInvalidException; @@ -455,4 +456,66 @@ public void testSaveTimeout() throws Exception { + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + "\ttimeout = 60\n"); } + + @Test + public void noInsteadOf() throws Exception { + config.setString("remote", "origin", "url", "short:project.git"); + config.setString("url", "https://server/repos/", "name", "short:"); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getURIs().isEmpty()); + assertEquals("short:project.git", rc.getURIs().get(0).toASCIIString()); + } + + @Test + public void singleInsteadOf() throws Exception { + config.setString("remote", "origin", "url", "short:project.git"); + config.setString("url", "https://server/repos/", "insteadOf", "short:"); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getURIs().isEmpty()); + assertEquals("https://server/repos/project.git", rc.getURIs().get(0) + .toASCIIString()); + } + + @Test + public void multipleInsteadOf() throws Exception { + config.setString("remote", "origin", "url", "prefixproject.git"); + config.setStringList("url", "https://server/repos/", "insteadOf", + Arrays.asList("pre", "prefix", "pref", "perf")); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getURIs().isEmpty()); + assertEquals("https://server/repos/project.git", rc.getURIs().get(0) + .toASCIIString()); + } + + @Test + public void noPushInsteadOf() throws Exception { + config.setString("remote", "origin", "pushurl", "short:project.git"); + config.setString("url", "https://server/repos/", "name", "short:"); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getPushURIs().isEmpty()); + assertEquals("short:project.git", rc.getPushURIs().get(0) + .toASCIIString()); + } + + @Test + public void singlePushInsteadOf() throws Exception { + config.setString("remote", "origin", "pushurl", "short:project.git"); + config.setString("url", "https://server/repos/", "pushInsteadOf", + "short:"); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getPushURIs().isEmpty()); + assertEquals("https://server/repos/project.git", rc.getPushURIs() + .get(0).toASCIIString()); + } + + @Test + public void multiplePushInsteadOf() throws Exception { + config.setString("remote", "origin", "pushurl", "prefixproject.git"); + config.setStringList("url", "https://server/repos/", "pushInsteadOf", + Arrays.asList("pre", "prefix", "pref", "perf")); + RemoteConfig rc = new RemoteConfig(config, "origin"); + assertFalse(rc.getPushURIs().isEmpty()); + assertEquals("https://server/repos/project.git", rc.getPushURIs() + .get(0).toASCIIString()); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteConfig.java index 3df56c696..f75ac703a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteConfig.java @@ -49,7 +49,10 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import org.eclipse.jgit.lib.Config; @@ -84,6 +87,10 @@ public class RemoteConfig implements Serializable { private static final String KEY_TIMEOUT = "timeout"; + private static final String KEY_INSTEADOF = "insteadof"; + + private static final String KEY_PUSHINSTEADOF = "pushinsteadof"; + private static final boolean DEFAULT_MIRROR = false; /** Default value for {@link #getUploadPack()} if not specified. */ @@ -161,14 +168,17 @@ public RemoteConfig(final Config rc, final String remoteName) String val; vlst = rc.getStringList(SECTION, name, KEY_URL); + Map insteadOf = getReplacements(rc, KEY_INSTEADOF); uris = new ArrayList(vlst.length); for (final String s : vlst) - uris.add(new URIish(s)); + uris.add(new URIish(replaceUri(s, insteadOf))); + Map pushInsteadOf = getReplacements(rc, + KEY_PUSHINSTEADOF); vlst = rc.getStringList(SECTION, name, KEY_PUSHURL); pushURIs = new ArrayList(vlst.length); for (final String s : vlst) - pushURIs.add(new URIish(s)); + pushURIs.add(new URIish(replaceUri(s, pushInsteadOf))); vlst = rc.getStringList(SECTION, name, KEY_FETCH); fetch = new ArrayList(vlst.length); @@ -260,6 +270,35 @@ private void unset(final Config rc, final String key) { rc.unset(SECTION, getName(), key); } + private Map getReplacements(final Config config, + final String keyName) { + final Map replacements = new HashMap(); + for (String url : config.getSubsections(KEY_URL)) + for (String insteadOf : config.getStringList(KEY_URL, url, keyName)) + replacements.put(insteadOf, url); + return replacements; + } + + private String replaceUri(final String uri, + final Map replacements) { + if (replacements.isEmpty()) + return uri; + Entry match = null; + for (Entry replacement : replacements.entrySet()) { + // Ignore current entry if not longer than previous match + if (match != null + && match.getKey().length() > replacement.getKey().length()) + continue; + if (!uri.startsWith(replacement.getKey())) + continue; + match = replacement; + } + if (match != null) + return match.getValue() + uri.substring(match.getKey().length()); + else + return uri; + } + /** * Get the local name this remote configuration is recognized as. *