Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java141
1 files changed, 133 insertions, 8 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
index e105dc063b..1de8a0be2e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java
@@ -49,11 +49,14 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.UnsupportedOperationException;
+import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.StringJoiner;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.Git;
@@ -67,6 +70,7 @@ import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.gitrepo.ManifestParser.IncludedFileReader;
import org.eclipse.jgit.gitrepo.RepoProject.CopyFile;
+import org.eclipse.jgit.gitrepo.RepoProject.LinkFile;
import org.eclipse.jgit.gitrepo.internal.RepoText;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
@@ -106,7 +110,8 @@ import org.eclipse.jgit.util.FileUtils;
*/
public class RepoCommand extends GitCommand<RevCommit> {
private String manifestPath;
- private String uri;
+ private String baseUri;
+ private URI targetUri;
private String groupsParam;
private String branch;
private String targetBranch = Constants.HEAD;
@@ -274,7 +279,25 @@ public class RepoCommand extends GitCommand<RevCommit> {
* @return this command
*/
public RepoCommand setURI(String uri) {
- this.uri = uri;
+ this.baseUri = uri;
+ return this;
+ }
+
+ /**
+ * Set the URI of the superproject (this repository), so the .gitmodules
+ * file can specify the submodule URLs relative to the superproject.
+ *
+ * @param uri
+ * the URI of the repository holding the superproject.
+ * @return this command
+ * @since 4.8
+ */
+ public RepoCommand setTargetURI(String uri) {
+ // The repo name is interpreted as a directory, for example
+ // Gerrit (http://gerrit.googlesource.com/gerrit) has a
+ // .gitmodules referencing ../plugins/hooks, which is
+ // on http://gerrit.googlesource.com/plugins/hooks,
+ this.targetUri = URI.create(uri + "/"); //$NON-NLS-1$
return this;
}
@@ -452,9 +475,8 @@ public class RepoCommand extends GitCommand<RevCommit> {
public RevCommit call() throws GitAPIException {
try {
checkCallable();
- if (uri == null || uri.length() == 0) {
- throw new IllegalArgumentException(
- JGitText.get().uriNotConfigured);
+ if (baseUri == null) {
+ baseUri = ""; //$NON-NLS-1$
}
if (inputStream == null) {
if (manifestPath == null || manifestPath.length() == 0)
@@ -478,7 +500,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
git = new Git(repo);
ManifestParser parser = new ManifestParser(
- includedReader, manifestPath, branch, uri, groupsParam, repo);
+ includedReader, manifestPath, branch, baseUri, groupsParam, repo);
try {
parser.read(inputStream);
for (RepoProject proj : parser.getFilteredProjects()) {
@@ -486,6 +508,7 @@ public class RepoCommand extends GitCommand<RevCommit> {
proj.getPath(),
proj.getRevision(),
proj.getCopyFiles(),
+ proj.getLinkFiles(),
proj.getGroups(),
proj.getRecommendShallow());
}
@@ -550,8 +573,13 @@ public class RepoCommand extends GitCommand<RevCommit> {
rec.append("\n"); //$NON-NLS-1$
attributes.append(rec.toString());
}
+
+ URI submodUrl = URI.create(nameUri);
+ if (targetUri != null) {
+ submodUrl = relativize(targetUri, submodUrl);
+ }
cfg.setString("submodule", path, "path", path); //$NON-NLS-1$ //$NON-NLS-2$
- cfg.setString("submodule", path, "url", nameUri); //$NON-NLS-1$ //$NON-NLS-2$
+ cfg.setString("submodule", path, "url", submodUrl.toString()); //$NON-NLS-1$ //$NON-NLS-2$
// create gitlink
DirCacheEntry dcEntry = new DirCacheEntry(path);
@@ -568,6 +596,25 @@ public class RepoCommand extends GitCommand<RevCommit> {
dcEntry.setFileMode(FileMode.REGULAR_FILE);
builder.add(dcEntry);
}
+ for (LinkFile linkfile : proj.getLinkFiles()) {
+ String link;
+ if (linkfile.dest.contains("/")) { //$NON-NLS-1$
+ link = FileUtils.relativizeGitPath(
+ linkfile.dest.substring(0,
+ linkfile.dest.lastIndexOf('/')),
+ proj.getPath() + "/" + linkfile.src); //$NON-NLS-1$
+ } else {
+ link = proj.getPath() + "/" + linkfile.src; //$NON-NLS-1$
+ }
+
+ objectId = inserter.insert(Constants.OBJ_BLOB,
+ link.getBytes(
+ Constants.CHARACTER_ENCODING));
+ dcEntry = new DirCacheEntry(linkfile.dest);
+ dcEntry.setObjectId(objectId);
+ dcEntry.setFileMode(FileMode.SYMLINK);
+ builder.add(dcEntry);
+ }
}
String content = cfg.toText();
@@ -642,13 +689,20 @@ public class RepoCommand extends GitCommand<RevCommit> {
}
private void addSubmodule(String url, String path, String revision,
- List<CopyFile> copyfiles, Set<String> groups, String recommendShallow)
+ List<CopyFile> copyfiles, List<LinkFile> linkfiles,
+ Set<String> groups, String recommendShallow)
throws GitAPIException, IOException {
if (repo.isBare()) {
RepoProject proj = new RepoProject(url, path, revision, null, groups, recommendShallow);
proj.addCopyFiles(copyfiles);
+ proj.addLinkFiles(linkfiles);
bareProjects.add(proj);
} else {
+ if (!linkfiles.isEmpty()) {
+ throw new UnsupportedOperationException(
+ JGitText.get().nonBareLinkFilesNotSupported);
+ }
+
SubmoduleAddCommand add = git
.submoduleAdd()
.setPath(path)
@@ -672,6 +726,77 @@ public class RepoCommand extends GitCommand<RevCommit> {
}
}
+ /*
+ * Assume we are document "a/b/index.html", what should we put in a href to get to "a/" ?
+ * Returns the child if either base or child is not a bare path. This provides a missing feature in
+ * java.net.URI (see http://bugs.java.com/view_bug.do?bug_id=6226081).
+ */
+ private static final String SLASH = "/"; //$NON-NLS-1$
+ static URI relativize(URI current, URI target) {
+
+ // We only handle bare paths for now.
+ if (!target.toString().equals(target.getPath())) {
+ return target;
+ }
+ if (!current.toString().equals(current.getPath())) {
+ return target;
+ }
+
+ String cur = current.normalize().getPath();
+ String dest = target.normalize().getPath();
+
+ // TODO(hanwen): maybe (absolute, relative) should throw an exception.
+ if (cur.startsWith(SLASH) != dest.startsWith(SLASH)) {
+ return target;
+ }
+
+ while (cur.startsWith(SLASH)) {
+ cur = cur.substring(1);
+ }
+ while (dest.startsWith(SLASH)) {
+ dest = dest.substring(1);
+ }
+
+ if (cur.indexOf('/') == -1 || dest.indexOf('/') == -1) {
+ // Avoid having to special-casing in the next two ifs.
+ String prefix = "prefix/"; //$NON-NLS-1$
+ cur = prefix + cur;
+ dest = prefix + dest;
+ }
+
+ if (!cur.endsWith(SLASH)) {
+ // The current file doesn't matter.
+ int lastSlash = cur.lastIndexOf('/');
+ cur = cur.substring(0, lastSlash);
+ }
+ String destFile = ""; //$NON-NLS-1$
+ if (!dest.endsWith(SLASH)) {
+ // We always have to provide the destination file.
+ int lastSlash = dest.lastIndexOf('/');
+ destFile = dest.substring(lastSlash + 1, dest.length());
+ dest = dest.substring(0, dest.lastIndexOf('/'));
+ }
+
+ String[] cs = cur.split(SLASH);
+ String[] ds = dest.split(SLASH);
+
+ int common = 0;
+ while (common < cs.length && common < ds.length && cs[common].equals(ds[common])) {
+ common++;
+ }
+
+ StringJoiner j = new StringJoiner(SLASH);
+ for (int i = common; i < cs.length; i++) {
+ j.add(".."); //$NON-NLS-1$
+ }
+ for (int i = common; i < ds.length; i++) {
+ j.add(ds[i]);
+ }
+
+ j.add(destFile);
+ return URI.create(j.toString());
+ }
+
private static String findRef(String ref, Repository repo)
throws IOException {
if (!ObjectId.isId(ref)) {

Back to the top