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
This commit is contained in:
parent
a9892fba46
commit
b57845c0cc
|
@ -47,6 +47,7 @@
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.jgit.JGitText;
|
||||
|
@ -58,6 +59,7 @@
|
|||
import org.eclipse.jgit.dircache.DirCacheEditor;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.lib.ConfigConstants;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
|
@ -169,4 +171,45 @@ public void apply(DirCacheEntry ent) {
|
|||
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));
|
||||
}
|
||||
}
|
|
@ -46,12 +46,14 @@
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.jgit.api.SubmoduleInitCommand;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor;
|
||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
||||
|
@ -81,19 +83,7 @@ public void repositoryWithNoSubmodules() {
|
|||
@Test
|
||||
public void repositoryWithUninitializedModule() throws IOException,
|
||||
ConfigInvalidException {
|
||||
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();
|
||||
final String path = addSubmoduleToIndex();
|
||||
|
||||
SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
|
||||
assertTrue(generator.next());
|
||||
|
@ -123,4 +113,220 @@ public void apply(DirCacheEntry ent) {
|
|||
assertEquals(url, generator.getConfigUrl());
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,4 +137,73 @@ public void apply(DirCacheEntry ent) {
|
|||
ConfigConstants.CONFIG_REMOTE_SECTION,
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -484,6 +484,7 @@ public static JGitText get() {
|
|||
/***/ public String statelessRPCRequiresOptionToBeEnabled;
|
||||
/***/ public String submoduleExists;
|
||||
/***/ public String submodulesNotSupported;
|
||||
/***/ public String submoduleParentRemoteUrlInvalid;
|
||||
/***/ public String symlinkCannotBeWrittenAsTheLinkTarget;
|
||||
/***/ public String systemConfigFileInvalid;
|
||||
/***/ public String tagNameInvalid;
|
||||
|
|
|
@ -148,12 +148,18 @@ public Repository call() throws JGitInternalException {
|
|||
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 Repository call() throws JGitInternalException {
|
|||
// 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) {
|
||||
|
|
|
@ -106,7 +106,7 @@ public Collection<String> call() throws JGitInternalException {
|
|||
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,
|
||||
|
|
|
@ -116,7 +116,7 @@ public Map<String, String> call() throws JGitInternalException {
|
|||
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;
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
|
||||
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 static File getSubmoduleGitDirectory(final Repository parent,
|
|||
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 String getHeadRef() throws IOException {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue