Browse Source

Merge "Support relative submodule URLs on init/add/sync"

stable-1.3
Matthias Sohn 13 years ago committed by Code Review
parent
commit
ea56a1ddb2
  1. 43
      org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java
  2. 232
      org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleInitTest.java
  3. 69
      org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java
  4. 1
      org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
  5. 1
      org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
  6. 10
      org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
  7. 2
      org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
  8. 2
      org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
  9. 94
      org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java

43
org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java

@ -47,6 +47,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.File;
import java.text.MessageFormat; import java.text.MessageFormat;
import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
@ -58,6 +59,7 @@ import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEditor; import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
@ -169,4 +171,45 @@ public class SubmoduleAddTest extends RepositoryTestCase {
e.getMessage()); e.getMessage());
} }
} }
@Test
public void addSubmoduleWithRelativeUri() throws Exception {
Git git = new Git(db);
writeTrashFile("file.txt", "content");
git.add().addFilepattern("file.txt").call();
RevCommit commit = git.commit().setMessage("create file").call();
SubmoduleAddCommand command = new SubmoduleAddCommand(db);
String path = "sub";
String uri = "./.git";
command.setPath(path);
command.setURI(uri);
Repository repo = command.call();
assertNotNull(repo);
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals(path, generator.getPath());
assertEquals(commit, generator.getObjectId());
assertEquals(uri, generator.getModulesUrl());
assertEquals(path, generator.getModulesPath());
String fullUri = db.getDirectory().getAbsolutePath();
if (File.separatorChar == '\\')
fullUri = fullUri.replace('\\', '/');
assertEquals(fullUri, generator.getConfigUrl());
assertNotNull(generator.getRepository());
assertEquals(
fullUri,
generator
.getRepository()
.getConfig()
.getString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME,
ConfigConstants.CONFIG_KEY_URL));
assertEquals(commit, repo.resolve(Constants.HEAD));
Status status = Git.wrap(db).status().call();
assertTrue(status.getAdded().contains(Constants.DOT_GIT_MODULES));
assertTrue(status.getAdded().contains(path));
}
} }

232
org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleInitTest.java

@ -46,12 +46,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import org.eclipse.jgit.api.SubmoduleInitCommand; import org.eclipse.jgit.api.SubmoduleInitCommand;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEditor; import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
@ -81,19 +83,7 @@ public class SubmoduleInitTest extends RepositoryTestCase {
@Test @Test
public void repositoryWithUninitializedModule() throws IOException, public void repositoryWithUninitializedModule() throws IOException,
ConfigInvalidException { ConfigInvalidException {
final ObjectId id = ObjectId final String path = addSubmoduleToIndex();
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
final String path = "sub";
DirCache cache = db.lockDirCache();
DirCacheEditor editor = cache.editor();
editor.add(new PathEdit(path) {
public void apply(DirCacheEntry ent) {
ent.setFileMode(FileMode.GITLINK);
ent.setObjectId(id);
}
});
editor.commit();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db); SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next()); assertTrue(generator.next());
@ -123,4 +113,220 @@ public class SubmoduleInitTest extends RepositoryTestCase {
assertEquals(url, generator.getConfigUrl()); assertEquals(url, generator.getConfigUrl());
assertEquals(update, generator.getConfigUpdate()); assertEquals(update, generator.getConfigUpdate());
} }
@Test
public void resolveSameLevelRelativeUrl() throws Exception {
final String path = addSubmoduleToIndex();
String base = "git://server/repo.git";
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
base);
config.save();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertNull(generator.getConfigUpdate());
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "./sub.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
String update = "rebase";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_UPDATE, update);
modulesConfig.save();
SubmoduleInitCommand command = new SubmoduleInitCommand(db);
Collection<String> modules = command.call();
assertNotNull(modules);
assertEquals(1, modules.size());
assertEquals(path, modules.iterator().next());
generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals("git://server/repo.git/sub.git", generator.getConfigUrl());
assertEquals(update, generator.getConfigUpdate());
}
@Test
public void resolveOneLevelHigherRelativeUrl() throws IOException,
ConfigInvalidException {
final String path = addSubmoduleToIndex();
String base = "git://server/repo.git";
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
base);
config.save();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertNull(generator.getConfigUpdate());
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "../sub.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
String update = "rebase";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_UPDATE, update);
modulesConfig.save();
SubmoduleInitCommand command = new SubmoduleInitCommand(db);
Collection<String> modules = command.call();
assertNotNull(modules);
assertEquals(1, modules.size());
assertEquals(path, modules.iterator().next());
generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals("git://server/sub.git", generator.getConfigUrl());
assertEquals(update, generator.getConfigUpdate());
}
@Test
public void resolveTwoLevelHigherRelativeUrl() throws IOException,
ConfigInvalidException {
final String path = addSubmoduleToIndex();
String base = "git://server/repo.git";
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
base);
config.save();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertNull(generator.getConfigUpdate());
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "../../server2/sub.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
String update = "rebase";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_UPDATE, update);
modulesConfig.save();
SubmoduleInitCommand command = new SubmoduleInitCommand(db);
Collection<String> modules = command.call();
assertNotNull(modules);
assertEquals(1, modules.size());
assertEquals(path, modules.iterator().next());
generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals("git://server2/sub.git", generator.getConfigUrl());
assertEquals(update, generator.getConfigUpdate());
}
@Test
public void resolveWorkingDirectoryRelativeUrl() throws IOException,
ConfigInvalidException {
final String path = addSubmoduleToIndex();
String base = db.getWorkTree().getAbsolutePath();
if (File.separatorChar == '\\')
base = base.replace('\\', '/');
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
null);
config.save();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertNull(generator.getConfigUpdate());
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "./sub.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
String update = "rebase";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_UPDATE, update);
modulesConfig.save();
SubmoduleInitCommand command = new SubmoduleInitCommand(db);
Collection<String> modules = command.call();
assertNotNull(modules);
assertEquals(1, modules.size());
assertEquals(path, modules.iterator().next());
generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals(base + "/sub.git", generator.getConfigUrl());
assertEquals(update, generator.getConfigUpdate());
}
@Test
public void resolveInvalidParentUrl() throws IOException,
ConfigInvalidException {
final String path = addSubmoduleToIndex();
String base = "no_slash";
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
base);
config.save();
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertNull(generator.getConfigUpdate());
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "../sub.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
modulesConfig.save();
try {
new SubmoduleInitCommand(db).call();
fail("Exception not thrown");
} catch (JGitInternalException e) {
assertTrue(e.getCause() instanceof IOException);
}
}
private String addSubmoduleToIndex() throws IOException {
final ObjectId id = ObjectId
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
final String path = "sub";
DirCache cache = db.lockDirCache();
DirCacheEditor editor = cache.editor();
editor.add(new PathEdit(path) {
public void apply(DirCacheEntry ent) {
ent.setFileMode(FileMode.GITLINK);
ent.setObjectId(id);
}
});
editor.commit();
return path;
}
} }

69
org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java

@ -137,4 +137,73 @@ public class SubmoduleSyncTest extends RepositoryTestCase {
ConfigConstants.CONFIG_REMOTE_SECTION, ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL)); Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL));
} }
@Test
public void repositoryWithRelativeUriSubmodule() throws Exception {
writeTrashFile("file.txt", "content");
Git git = Git.wrap(db);
git.add().addFilepattern("file.txt").call();
git.commit().setMessage("create file").call();
final ObjectId id = ObjectId
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
final String path = "sub";
DirCache cache = db.lockDirCache();
DirCacheEditor editor = cache.editor();
editor.add(new PathEdit(path) {
public void apply(DirCacheEntry ent) {
ent.setFileMode(FileMode.GITLINK);
ent.setObjectId(id);
}
});
editor.commit();
String base = "git://server/repo.git";
FileBasedConfig config = db.getConfig();
config.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL,
base);
config.save();
FileBasedConfig modulesConfig = new FileBasedConfig(new File(
db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String current = "git://server/repo.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, current);
modulesConfig.save();
Repository subRepo = Git.cloneRepository()
.setURI(db.getDirectory().toURI().toString())
.setDirectory(new File(db.getWorkTree(), path)).call()
.getRepository();
assertNotNull(subRepo);
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertNull(generator.getConfigUrl());
assertEquals(current, generator.getModulesUrl());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, "../sub.git");
modulesConfig.save();
SubmoduleSyncCommand command = new SubmoduleSyncCommand(db);
Map<String, String> synced = command.call();
assertNotNull(synced);
assertEquals(1, synced.size());
Entry<String, String> module = synced.entrySet().iterator().next();
assertEquals(path, module.getKey());
assertEquals("git://server/sub.git", module.getValue());
generator = SubmoduleWalk.forIndex(db);
assertTrue(generator.next());
assertEquals("git://server/sub.git", generator.getConfigUrl());
StoredConfig submoduleConfig = generator.getRepository().getConfig();
assertEquals("git://server/sub.git", submoduleConfig.getString(
ConfigConstants.CONFIG_REMOTE_SECTION,
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL));
}
} }

1
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 startingReadStageWithoutWrittenRequestDataPendingIsNotSupported=Starting read stage without written request data pending is not supported
statelessRPCRequiresOptionToBeEnabled=stateless RPC requires {0} to be enabled statelessRPCRequiresOptionToBeEnabled=stateless RPC requires {0} to be enabled
submoduleExists=Submodule ''{0}'' already exists in the index submoduleExists=Submodule ''{0}'' already exists in the index
submoduleParentRemoteUrlInvalid=Cannot remove segment from remote url ''{0}''
submodulesNotSupported=Submodules are not supported submodulesNotSupported=Submodules are not supported
symlinkCannotBeWrittenAsTheLinkTarget=Symlink "{0}" cannot be written as the link target cannot be read from within Java. 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} systemConfigFileInvalid=Systen wide config file {0} is invalid {1}

1
org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java

@ -484,6 +484,7 @@ public class JGitText extends TranslationBundle {
/***/ public String statelessRPCRequiresOptionToBeEnabled; /***/ public String statelessRPCRequiresOptionToBeEnabled;
/***/ public String submoduleExists; /***/ public String submoduleExists;
/***/ public String submodulesNotSupported; /***/ public String submodulesNotSupported;
/***/ public String submoduleParentRemoteUrlInvalid;
/***/ public String symlinkCannotBeWrittenAsTheLinkTarget; /***/ public String symlinkCannotBeWrittenAsTheLinkTarget;
/***/ public String systemConfigFileInvalid; /***/ public String systemConfigFileInvalid;
/***/ public String tagNameInvalid; /***/ public String tagNameInvalid;

10
org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java

@ -148,12 +148,18 @@ public class SubmoduleAddCommand extends
throw new JGitInternalException(e.getMessage(), e); 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 // Clone submodule repository
File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path); File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path);
CloneCommand clone = Git.cloneRepository(); CloneCommand clone = Git.cloneRepository();
configure(clone); configure(clone);
clone.setDirectory(moduleDirectory); clone.setDirectory(moduleDirectory);
clone.setURI(uri); clone.setURI(resolvedUri);
if (monitor != null) if (monitor != null)
clone.setProgressMonitor(monitor); clone.setProgressMonitor(monitor);
Repository subRepo = clone.call().getRepository(); Repository subRepo = clone.call().getRepository();
@ -161,7 +167,7 @@ public class SubmoduleAddCommand extends
// Save submodule URL to parent repository's config // Save submodule URL to parent repository's config
StoredConfig config = repo.getConfig(); StoredConfig config = repo.getConfig();
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, uri); ConfigConstants.CONFIG_KEY_URL, resolvedUri);
try { try {
config.save(); config.save();
} catch (IOException e) { } catch (IOException e) {

2
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(); String path = generator.getPath();
// Copy 'url' and 'update' fields from .gitmodules to config // Copy 'url' and 'update' fields from .gitmodules to config
// file // file
String url = generator.getModulesUrl(); String url = generator.getRemoteUrl();
String update = generator.getModulesUpdate(); String update = generator.getModulesUpdate();
if (url != null) if (url != null)
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,

2
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>(); Map<String, String> synced = new HashMap<String, String>();
StoredConfig config = repo.getConfig(); StoredConfig config = repo.getConfig();
while (generator.next()) { while (generator.next()) {
String remoteUrl = generator.getModulesUrl(); String remoteUrl = generator.getRemoteUrl();
if (remoteUrl == null) if (remoteUrl == null)
continue; continue;

94
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.File;
import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
@ -176,6 +178,83 @@ public class SubmoduleWalk {
return new File(getSubmoduleDirectory(parent, path), Constants.DOT_GIT); 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 Repository repository;
private final TreeWalk walk; private final TreeWalk walk;
@ -432,4 +511,19 @@ public class SubmoduleWalk {
Ref head = subRepo.getRef(Constants.HEAD); Ref head = subRepo.getRef(Constants.HEAD);
return head != null ? head.getLeaf().getName() : null; 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;
}
} }

Loading…
Cancel
Save