Implement mirror option in CloneCommand
Bug: 552173 Change-Id: If79adf578b303890314a3285d7a6d2c71f48d091 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
parent
8e356fc45e
commit
6216b0de8a
|
@ -67,6 +67,7 @@
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.lib.StoredConfig;
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
import org.eclipse.jgit.revwalk.RevBlob;
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
|
@ -96,10 +97,15 @@ public void setUp() throws Exception {
|
||||||
writeTrashFile("Test.txt", "Hello world");
|
writeTrashFile("Test.txt", "Hello world");
|
||||||
git.add().addFilepattern("Test.txt").call();
|
git.add().addFilepattern("Test.txt").call();
|
||||||
git.commit().setMessage("Initial commit").call();
|
git.commit().setMessage("Initial commit").call();
|
||||||
git.tag().setName("tag-initial").setMessage("Tag initial").call();
|
Ref head = git.tag().setName("tag-initial").setMessage("Tag initial")
|
||||||
|
.call();
|
||||||
|
|
||||||
// create a test branch and switch to it
|
// create a test branch and switch to it
|
||||||
git.checkout().setCreateBranch(true).setName("test").call();
|
git.checkout().setCreateBranch(true).setName("test").call();
|
||||||
|
// create a non-standard ref
|
||||||
|
RefUpdate ru = db.updateRef("refs/meta/foo/bar");
|
||||||
|
ru.setNewObjectId(head.getObjectId());
|
||||||
|
ru.update();
|
||||||
|
|
||||||
// commit something on the test branch
|
// commit something on the test branch
|
||||||
writeTrashFile("Test.txt", "Some change");
|
writeTrashFile("Test.txt", "Some change");
|
||||||
|
@ -424,6 +430,32 @@ public void testBareCloneRepositoryOnlyOneBranch() throws Exception {
|
||||||
specs.get(0));
|
specs.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBareCloneRepositoryMirror() throws Exception {
|
||||||
|
File directory = createTempDirectory(
|
||||||
|
"testCloneRepositoryWithBranch_mirror");
|
||||||
|
CloneCommand command = Git.cloneRepository();
|
||||||
|
command.setBranch("refs/heads/master");
|
||||||
|
command.setMirror(true); // implies bare repository
|
||||||
|
command.setDirectory(directory);
|
||||||
|
command.setURI(fileUri());
|
||||||
|
Git git2 = command.call();
|
||||||
|
addRepoToClose(git2.getRepository());
|
||||||
|
assertNotNull(git2);
|
||||||
|
assertNotNull(git2.getRepository().resolve("tag-for-blob"));
|
||||||
|
assertNotNull(git2.getRepository().resolve("tag-initial"));
|
||||||
|
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master");
|
||||||
|
assertEquals("refs/heads/master, refs/heads/test", allRefNames(
|
||||||
|
git2.branchList().setListMode(ListMode.ALL).call()));
|
||||||
|
assertNotNull(git2.getRepository().exactRef("refs/meta/foo/bar"));
|
||||||
|
RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(),
|
||||||
|
Constants.DEFAULT_REMOTE_NAME);
|
||||||
|
List<RefSpec> specs = cfg.getFetchRefSpecs();
|
||||||
|
assertEquals(1, specs.size());
|
||||||
|
assertEquals(new RefSpec("+refs/*:refs/*"),
|
||||||
|
specs.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCloneRepositoryOnlyOneTag() throws Exception {
|
public void testCloneRepositoryOnlyOneTag() throws Exception {
|
||||||
File directory = createTempDirectory("testCloneRepositoryWithBranch");
|
File directory = createTempDirectory("testCloneRepositoryWithBranch");
|
||||||
|
|
|
@ -77,8 +77,8 @@
|
||||||
import org.eclipse.jgit.transport.RemoteConfig;
|
import org.eclipse.jgit.transport.RemoteConfig;
|
||||||
import org.eclipse.jgit.transport.TagOpt;
|
import org.eclipse.jgit.transport.TagOpt;
|
||||||
import org.eclipse.jgit.transport.URIish;
|
import org.eclipse.jgit.transport.URIish;
|
||||||
import org.eclipse.jgit.util.FileUtils;
|
|
||||||
import org.eclipse.jgit.util.FS;
|
import org.eclipse.jgit.util.FS;
|
||||||
|
import org.eclipse.jgit.util.FileUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a repository into a new working directory
|
* Clone a repository into a new working directory
|
||||||
|
@ -104,7 +104,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
|
||||||
|
|
||||||
private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
|
private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
|
||||||
|
|
||||||
private boolean cloneAllBranches;
|
private FETCH_TYPE fetchType = FETCH_TYPE.ALL_BRANCHES;
|
||||||
|
|
||||||
private boolean cloneSubmodules;
|
private boolean cloneSubmodules;
|
||||||
|
|
||||||
|
@ -118,6 +118,10 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
|
||||||
|
|
||||||
private boolean gitDirExistsInitially;
|
private boolean gitDirExistsInitially;
|
||||||
|
|
||||||
|
private enum FETCH_TYPE {
|
||||||
|
MULTIPLE_BRANCHES, ALL_BRANCHES, MIRROR
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for status of clone operation.
|
* Callback for status of clone operation.
|
||||||
*
|
*
|
||||||
|
@ -282,12 +286,11 @@ private FetchResult fetch(Repository clonedRepo, URIish u)
|
||||||
RemoteConfig config = new RemoteConfig(clonedRepo.getConfig(), remote);
|
RemoteConfig config = new RemoteConfig(clonedRepo.getConfig(), remote);
|
||||||
config.addURI(u);
|
config.addURI(u);
|
||||||
|
|
||||||
final String dst = (bare ? Constants.R_HEADS : Constants.R_REMOTES
|
boolean fetchAll = fetchType == FETCH_TYPE.ALL_BRANCHES
|
||||||
+ config.getName() + '/') + '*';
|
|| fetchType == FETCH_TYPE.MIRROR;
|
||||||
boolean fetchAll = cloneAllBranches || branchesToClone == null
|
|
||||||
|| branchesToClone.isEmpty();
|
|
||||||
|
|
||||||
config.setFetchRefSpecs(calculateRefSpecs(fetchAll, dst));
|
config.setFetchRefSpecs(calculateRefSpecs(fetchType, config.getName()));
|
||||||
|
config.setMirror(fetchType == FETCH_TYPE.MIRROR);
|
||||||
config.update(clonedRepo.getConfig());
|
config.update(clonedRepo.getConfig());
|
||||||
|
|
||||||
clonedRepo.getConfig().save();
|
clonedRepo.getConfig().save();
|
||||||
|
@ -302,26 +305,33 @@ private FetchResult fetch(Repository clonedRepo, URIish u)
|
||||||
return command.call();
|
return command.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RefSpec> calculateRefSpecs(boolean fetchAll, String dst) {
|
private List<RefSpec> calculateRefSpecs(FETCH_TYPE type,
|
||||||
RefSpec heads = new RefSpec();
|
String remoteName) {
|
||||||
heads = heads.setForceUpdate(true);
|
|
||||||
heads = heads.setSourceDestination(Constants.R_HEADS + '*', dst);
|
|
||||||
List<RefSpec> specs = new ArrayList<>();
|
List<RefSpec> specs = new ArrayList<>();
|
||||||
if (!fetchAll) {
|
if (type == FETCH_TYPE.MIRROR) {
|
||||||
RefSpec tags = new RefSpec();
|
specs.add(new RefSpec().setForceUpdate(true).setSourceDestination(
|
||||||
tags = tags.setForceUpdate(true);
|
Constants.R_REFS + '*', Constants.R_REFS + '*'));
|
||||||
tags = tags.setSourceDestination(Constants.R_TAGS + '*',
|
|
||||||
Constants.R_TAGS + '*');
|
|
||||||
for (String selectedRef : branchesToClone) {
|
|
||||||
if (heads.matchSource(selectedRef)) {
|
|
||||||
specs.add(heads.expandFromSource(selectedRef));
|
|
||||||
} else if (tags.matchSource(selectedRef)) {
|
|
||||||
specs.add(tags.expandFromSource(selectedRef));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We'll fetch the tags anyway.
|
RefSpec heads = new RefSpec();
|
||||||
specs.add(heads);
|
heads = heads.setForceUpdate(true);
|
||||||
|
final String dst = (bare ? Constants.R_HEADS
|
||||||
|
: Constants.R_REMOTES + remoteName + '/') + '*';
|
||||||
|
heads = heads.setSourceDestination(Constants.R_HEADS + '*', dst);
|
||||||
|
if (type == FETCH_TYPE.MULTIPLE_BRANCHES) {
|
||||||
|
RefSpec tags = new RefSpec().setForceUpdate(true)
|
||||||
|
.setSourceDestination(Constants.R_TAGS + '*',
|
||||||
|
Constants.R_TAGS + '*');
|
||||||
|
for (String selectedRef : branchesToClone) {
|
||||||
|
if (heads.matchSource(selectedRef)) {
|
||||||
|
specs.add(heads.expandFromSource(selectedRef));
|
||||||
|
} else if (tags.matchSource(selectedRef)) {
|
||||||
|
specs.add(tags.expandFromSource(selectedRef));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We'll fetch the tags anyway.
|
||||||
|
specs.add(heads);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return specs;
|
return specs;
|
||||||
}
|
}
|
||||||
|
@ -609,7 +619,31 @@ public CloneCommand setProgressMonitor(ProgressMonitor monitor) {
|
||||||
* @return {@code this}
|
* @return {@code this}
|
||||||
*/
|
*/
|
||||||
public CloneCommand setCloneAllBranches(boolean cloneAllBranches) {
|
public CloneCommand setCloneAllBranches(boolean cloneAllBranches) {
|
||||||
this.cloneAllBranches = cloneAllBranches;
|
this.fetchType = cloneAllBranches ? FETCH_TYPE.ALL_BRANCHES
|
||||||
|
: this.fetchType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a mirror of the source repository. This implies that a bare
|
||||||
|
* repository will be created. Compared to {@link #setBare},
|
||||||
|
* {@code #setMirror} not only maps local branches of the source to local
|
||||||
|
* branches of the target, it maps all refs (including remote-tracking
|
||||||
|
* branches, notes etc.) and sets up a refspec configuration such that all
|
||||||
|
* these refs are overwritten by a git remote update in the target
|
||||||
|
* repository.
|
||||||
|
*
|
||||||
|
* @param mirror
|
||||||
|
* whether to mirror all refs from the source repository
|
||||||
|
*
|
||||||
|
* @return {@code this}
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
public CloneCommand setMirror(boolean mirror) {
|
||||||
|
if (mirror) {
|
||||||
|
this.fetchType = FETCH_TYPE.MIRROR;
|
||||||
|
setBare(true);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +675,13 @@ public CloneCommand setCloneSubmodules(boolean cloneSubmodules) {
|
||||||
* @return {@code this}
|
* @return {@code this}
|
||||||
*/
|
*/
|
||||||
public CloneCommand setBranchesToClone(Collection<String> branchesToClone) {
|
public CloneCommand setBranchesToClone(Collection<String> branchesToClone) {
|
||||||
this.branchesToClone = branchesToClone;
|
if (branchesToClone == null || branchesToClone.isEmpty()) {
|
||||||
|
// fallback to default
|
||||||
|
fetchType = FETCH_TYPE.ALL_BRANCHES;
|
||||||
|
} else {
|
||||||
|
this.fetchType = FETCH_TYPE.MULTIPLE_BRANCHES;
|
||||||
|
this.branchesToClone = branchesToClone;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue