summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorKevin Sawicki <kevin@github.com>2012-01-17 09:35:29 -0800
committerKevin Sawicki <kevin@github.com>2012-01-17 09:35:29 -0800
commitb57845c0cc7d4d9428f26701b1c21e03982639c8 (patch)
tree95a0eedbfbca671e174d18e773c7d50f7cb28df9 /org.eclipse.jgit
parenta9892fba462e03cec1bfa4fee9525fc9de108a2f (diff)
downloadjgit-b57845c0cc7d4d9428f26701b1c21e03982639c8.tar.gz
jgit-b57845c0cc7d4d9428f26701b1c21e03982639c8.zip
Support relative submodule URLs on init/add/sync
Interpret submodule URLs that start with './' or '../' as relative to either the configured remote for the HEAD branch, or 'origin', or the parent repository working directory if no remote URL is configured Bug: 368536 Change-Id: Id4985824023b75cd45cd64a4dd9d421166391e10
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java94
6 files changed, 106 insertions, 4 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index a80e6bcae5..5b22801342 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -423,6 +423,7 @@ staleRevFlagsOn=Stale RevFlags on {0}
startingReadStageWithoutWrittenRequestDataPendingIsNotSupported=Starting read stage without written request data pending is not supported
statelessRPCRequiresOptionToBeEnabled=stateless RPC requires {0} to be enabled
submoduleExists=Submodule ''{0}'' already exists in the index
+submoduleParentRemoteUrlInvalid=Cannot remove segment from remote url ''{0}''
submodulesNotSupported=Submodules are not supported
symlinkCannotBeWrittenAsTheLinkTarget=Symlink "{0}" cannot be written as the link target cannot be read from within Java.
systemConfigFileInvalid=Systen wide config file {0} is invalid {1}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index f4de487558..dbc3bcae62 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -484,6 +484,7 @@ public class JGitText extends TranslationBundle {
/***/ public String statelessRPCRequiresOptionToBeEnabled;
/***/ public String submoduleExists;
/***/ public String submodulesNotSupported;
+ /***/ public String submoduleParentRemoteUrlInvalid;
/***/ public String symlinkCannotBeWrittenAsTheLinkTarget;
/***/ public String systemConfigFileInvalid;
/***/ public String tagNameInvalid;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index ac81ccb457..e1b293c43d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -148,12 +148,18 @@ public class SubmoduleAddCommand extends
throw new JGitInternalException(e.getMessage(), e);
}
+ final String resolvedUri;
+ try {
+ resolvedUri = SubmoduleWalk.getSubmoduleRemoteUrl(repo, uri);
+ } catch (IOException e) {
+ throw new JGitInternalException(e.getMessage(), e);
+ }
// Clone submodule repository
File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path);
CloneCommand clone = Git.cloneRepository();
configure(clone);
clone.setDirectory(moduleDirectory);
- clone.setURI(uri);
+ clone.setURI(resolvedUri);
if (monitor != null)
clone.setProgressMonitor(monitor);
Repository subRepo = clone.call().getRepository();
@@ -161,7 +167,7 @@ public class SubmoduleAddCommand extends
// Save submodule URL to parent repository's config
StoredConfig config = repo.getConfig();
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_URL, uri);
+ ConfigConstants.CONFIG_KEY_URL, resolvedUri);
try {
config.save();
} catch (IOException e) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
index ad8f02e47f..fef13704ef 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
@@ -106,7 +106,7 @@ public class SubmoduleInitCommand extends GitCommand<Collection<String>> {
String path = generator.getPath();
// Copy 'url' and 'update' fields from .gitmodules to config
// file
- String url = generator.getModulesUrl();
+ String url = generator.getRemoteUrl();
String update = generator.getModulesUpdate();
if (url != null)
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
index 43647a0c69..fd8ddc941d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
@@ -116,7 +116,7 @@ public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> {
Map<String, String> synced = new HashMap<String, String>();
StoredConfig config = repo.getConfig();
while (generator.next()) {
- String remoteUrl = generator.getModulesUrl();
+ String remoteUrl = generator.getRemoteUrl();
if (remoteUrl == null)
continue;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
index ebe994826e..78896f8a54 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
@@ -44,7 +44,9 @@ package org.eclipse.jgit.submodule;
import java.io.File;
import java.io.IOException;
+import java.text.MessageFormat;
+import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.CorruptObjectException;
@@ -176,6 +178,83 @@ public class SubmoduleWalk {
return new File(getSubmoduleDirectory(parent, path), Constants.DOT_GIT);
}
+ /**
+ * Resolve submodule repository URL.
+ * <p>
+ * This handles relative URLs that are typically specified in the
+ * '.gitmodules' file by resolving them against the remote URL of the parent
+ * repository.
+ * <p>
+ * Relative URLs will be resolved against the parent repository's working
+ * directory if the parent repository has no configured remote URL.
+ *
+ * @param parent
+ * parent repository
+ * @param url
+ * absolute or relative URL of the submodule repository
+ * @return resolved URL
+ * @throws IOException
+ */
+ public static String getSubmoduleRemoteUrl(final Repository parent,
+ final String url) throws IOException {
+ if (!url.startsWith("./") && !url.startsWith("../"))
+ return url;
+
+ String remoteName = null;
+ // Look up remote URL associated wit HEAD ref
+ Ref ref = parent.getRef(Constants.HEAD);
+ if (ref != null) {
+ if (ref.isSymbolic())
+ ref = ref.getLeaf();
+ remoteName = parent.getConfig().getString(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ Repository.shortenRefName(ref.getName()),
+ ConfigConstants.CONFIG_KEY_REMOTE);
+ }
+
+ // Fall back to 'origin' if current HEAD ref has no remote URL
+ if (remoteName == null)
+ remoteName = Constants.DEFAULT_REMOTE_NAME;
+
+ String remoteUrl = parent.getConfig().getString(
+ ConfigConstants.CONFIG_REMOTE_SECTION, remoteName,
+ ConfigConstants.CONFIG_KEY_URL);
+
+ // Fall back to parent repository's working directory if no remote URL
+ if (remoteUrl == null) {
+ remoteUrl = parent.getWorkTree().getAbsolutePath();
+ // Normalize slashes to '/'
+ if ('\\' == File.separatorChar)
+ remoteUrl = remoteUrl.replace('\\', '/');
+ }
+
+ // Remove trailing '/'
+ if (remoteUrl.charAt(remoteUrl.length() - 1) == '/')
+ remoteUrl = remoteUrl.substring(0, remoteUrl.length() - 1);
+
+ char separator = '/';
+ String submoduleUrl = url;
+ while (submoduleUrl.length() > 0) {
+ if (submoduleUrl.startsWith("./"))
+ submoduleUrl = submoduleUrl.substring(2);
+ else if (submoduleUrl.startsWith("../")) {
+ int lastSeparator = remoteUrl.lastIndexOf('/');
+ if (lastSeparator < 1) {
+ lastSeparator = remoteUrl.lastIndexOf(':');
+ separator = ':';
+ }
+ if (lastSeparator < 1)
+ throw new IOException(MessageFormat.format(
+ JGitText.get().submoduleParentRemoteUrlInvalid,
+ remoteUrl));
+ remoteUrl = remoteUrl.substring(0, lastSeparator);
+ submoduleUrl = submoduleUrl.substring(3);
+ } else
+ break;
+ }
+ return remoteUrl + separator + submoduleUrl;
+ }
+
private final Repository repository;
private final TreeWalk walk;
@@ -432,4 +511,19 @@ public class SubmoduleWalk {
Ref head = subRepo.getRef(Constants.HEAD);
return head != null ? head.getLeaf().getName() : null;
}
+
+ /**
+ * Get the resolved remote URL for the current submodule.
+ * <p>
+ * This method resolves the value of {@link #getModulesUrl()} to an absolute
+ * URL
+ *
+ * @return resolved remote URL
+ * @throws IOException
+ * @throws ConfigInvalidException
+ */
+ public String getRemoteUrl() throws IOException, ConfigInvalidException {
+ String url = getModulesUrl();
+ return url != null ? getSubmoduleRemoteUrl(repository, url) : null;
+ }
}