Browse Source

Clone: add --recurse-submodules option

Add the --recurse-submodules option on the command, which causes
submodules to also be initialized and updated.

Add a callback interface on CloneCommand and SubmoduleUpdateCommand to
them to provide progress feedback for clone operations.

Change-Id: I41b1668bc0d0bdfa46a9a89882c9657ea3063fc1
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-4.8
David Pursehouse 8 years ago committed by Matthias Sohn
parent
commit
005e5feb4e
  1. 3
      org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
  2. 49
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
  3. 2
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
  4. 56
      org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
  5. 20
      org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java

3
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties

@ -44,6 +44,7 @@ cantFindGitDirectory=error: can't find git directory
cantWrite=Can''t write {0} cantWrite=Can''t write {0}
changesNotStagedForCommit=Changes not staged for commit: changesNotStagedForCommit=Changes not staged for commit:
changesToBeCommitted=Changes to be committed: changesToBeCommitted=Changes to be committed:
checkingOut=Submodule path ''{0}'': checked out ''{1}''
checkoutConflict=error: Your local changes to the following files would be overwritten by checkout: checkoutConflict=error: Your local changes to the following files would be overwritten by checkout:
checkoutConflictPathLine=\t{0} checkoutConflictPathLine=\t{0}
cleanRequireForce=clean.requireForce defaults to true and neither -n nor -f given; refusing to clean cleanRequireForce=clean.requireForce defaults to true and neither -n nor -f given; refusing to clean
@ -197,6 +198,7 @@ statusAddedByThem=added by them:
statusDeletedByUs=deleted by us: statusDeletedByUs=deleted by us:
statusBothAdded=both added: statusBothAdded=both added:
statusBothModified=both modified: statusBothModified=both modified:
submoduleRegistered=Submodule {0} registered
switchedToNewBranch=Switched to a new branch ''{0}'' switchedToNewBranch=Switched to a new branch ''{0}''
switchedToBranch=Switched to branch ''{0}'' switchedToBranch=Switched to branch ''{0}''
tagAlreadyExists=tag ''{0}'' already exists tagAlreadyExists=tag ''{0}'' already exists
@ -371,6 +373,7 @@ usage_pushUrls=push URLs are manipulated
usage_quiet=don't show progress messages usage_quiet=don't show progress messages
usage_recordChangesToRepository=Record changes to the repository usage_recordChangesToRepository=Record changes to the repository
usage_recurseIntoSubtrees=recurse into subtrees usage_recurseIntoSubtrees=recurse into subtrees
usage_recurseSubmodules=recurse into submodules
usage_removeUntrackedDirectories=remove untracked directories usage_removeUntrackedDirectories=remove untracked directories
usage_renameLimit=limit size of rename matrix usage_renameLimit=limit size of rename matrix
usage_reset=Reset current HEAD to the specified state usage_reset=Reset current HEAD to the specified state

49
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java

@ -44,11 +44,14 @@
package org.eclipse.jgit.pgm; package org.eclipse.jgit.pgm;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Collection;
import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.pgm.internal.CLIText;
@ -58,7 +61,7 @@ import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option; import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_cloneRepositoryIntoNewDir") @Command(common = true, usage = "usage_cloneRepositoryIntoNewDir")
class Clone extends AbstractFetchCommand { class Clone extends AbstractFetchCommand implements CloneCommand.Callback {
@Option(name = "--origin", aliases = { "-o" }, metaVar = "metaVar_remoteName", usage = "usage_useNameInsteadOfOriginToTrackUpstream") @Option(name = "--origin", aliases = { "-o" }, metaVar = "metaVar_remoteName", usage = "usage_useNameInsteadOfOriginToTrackUpstream")
private String remoteName = Constants.DEFAULT_REMOTE_NAME; private String remoteName = Constants.DEFAULT_REMOTE_NAME;
@ -74,6 +77,9 @@ class Clone extends AbstractFetchCommand {
@Option(name = "--quiet", usage = "usage_quiet") @Option(name = "--quiet", usage = "usage_quiet")
private Boolean quiet; private Boolean quiet;
@Option(name = "--recurse-submodules", usage = "usage_recurseSubmodules")
private boolean cloneSubmodules;
@Argument(index = 0, required = true, metaVar = "metaVar_uriish") @Argument(index = 0, required = true, metaVar = "metaVar_uriish")
private String sourceUri; private String sourceUri;
@ -109,13 +115,15 @@ class Clone extends AbstractFetchCommand {
CloneCommand command = Git.cloneRepository(); CloneCommand command = Git.cloneRepository();
command.setURI(sourceUri).setRemote(remoteName).setBare(isBare) command.setURI(sourceUri).setRemote(remoteName).setBare(isBare)
.setNoCheckout(noCheckout).setBranch(branch); .setNoCheckout(noCheckout).setBranch(branch)
.setCloneSubmodules(cloneSubmodules);
command.setGitDir(gitdir == null ? null : new File(gitdir)); command.setGitDir(gitdir == null ? null : new File(gitdir));
command.setDirectory(localNameF); command.setDirectory(localNameF);
boolean msgs = quiet == null || !quiet.booleanValue(); boolean msgs = quiet == null || !quiet.booleanValue();
if (msgs) { if (msgs) {
command.setProgressMonitor(new TextProgressMonitor(errw)); command.setProgressMonitor(new TextProgressMonitor(errw))
.setCallback(this);
outw.println(MessageFormat.format( outw.println(MessageFormat.format(
CLIText.get().cloningInto, localName)); CLIText.get().cloningInto, localName));
outw.flush(); outw.flush();
@ -136,4 +144,39 @@ class Clone extends AbstractFetchCommand {
outw.flush(); outw.flush();
} }
} }
@Override
public void initializedSubmodules(Collection<String> submodules) {
try {
for (String submodule : submodules) {
outw.println(MessageFormat
.format(CLIText.get().submoduleRegistered, submodule));
}
outw.flush();
} catch (IOException e) {
// ignore
}
}
@Override
public void cloningSubmodule(String path) {
try {
outw.println(MessageFormat.format(
CLIText.get().cloningInto, path));
outw.flush();
} catch (IOException e) {
// ignore
}
}
@Override
public void checkingOut(AnyObjectId commit, String path) {
try {
outw.println(MessageFormat.format(CLIText.get().checkingOut,
path, commit.getName()));
outw.flush();
} catch (IOException e) {
// ignore
}
}
} }

2
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java

@ -121,6 +121,7 @@ public class CLIText extends TranslationBundle {
/***/ public String cantWrite; /***/ public String cantWrite;
/***/ public String changesNotStagedForCommit; /***/ public String changesNotStagedForCommit;
/***/ public String changesToBeCommitted; /***/ public String changesToBeCommitted;
/***/ public String checkingOut;
/***/ public String checkoutConflict; /***/ public String checkoutConflict;
/***/ public String checkoutConflictPathLine; /***/ public String checkoutConflictPathLine;
/***/ public String cleanRequireForce; /***/ public String cleanRequireForce;
@ -263,6 +264,7 @@ public class CLIText extends TranslationBundle {
/***/ public String statusDeletedByUs; /***/ public String statusDeletedByUs;
/***/ public String statusBothAdded; /***/ public String statusBothAdded;
/***/ public String statusBothModified; /***/ public String statusBothModified;
/***/ public String submoduleRegistered;
/***/ public String switchedToNewBranch; /***/ public String switchedToNewBranch;
/***/ public String switchedToBranch; /***/ public String switchedToBranch;
/***/ public String tagAlreadyExists; /***/ public String tagAlreadyExists;

56
org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java

@ -58,6 +58,7 @@ import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode; import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
@ -106,6 +107,42 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
private Collection<String> branchesToClone; private Collection<String> branchesToClone;
private Callback callback;
/**
* Callback for status of clone operation.
*
* @since 4.8
*/
public interface Callback {
/**
* Notify initialized submodules.
*
* @param submodules
* the submodules
*
*/
void initializedSubmodules(Collection<String> submodules);
/**
* Notify starting to clone a submodule.
*
* @param path
* the submodule path
*/
void cloningSubmodule(String path);
/**
* Notify checkout of commit
*
* @param commit
* the id of the commit being checked out
* @param path
* the submodule path
*/
void checkingOut(AnyObjectId commit, String path);
}
/** /**
* Create clone command with no repository set * Create clone command with no repository set
*/ */
@ -280,12 +317,18 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
private void cloneSubmodules(Repository clonedRepo) throws IOException, private void cloneSubmodules(Repository clonedRepo) throws IOException,
GitAPIException { GitAPIException {
SubmoduleInitCommand init = new SubmoduleInitCommand(clonedRepo); SubmoduleInitCommand init = new SubmoduleInitCommand(clonedRepo);
if (init.call().isEmpty()) Collection<String> submodules = init.call();
if (submodules.isEmpty()) {
return; return;
}
if (callback != null) {
callback.initializedSubmodules(submodules);
}
SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(clonedRepo); SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(clonedRepo);
configure(update); configure(update);
update.setProgressMonitor(monitor); update.setProgressMonitor(monitor);
update.setCallback(callback);
if (!update.call().isEmpty()) { if (!update.call().isEmpty()) {
SubmoduleWalk walk = SubmoduleWalk.forIndex(clonedRepo); SubmoduleWalk walk = SubmoduleWalk.forIndex(clonedRepo);
while (walk.next()) { while (walk.next()) {
@ -523,6 +566,17 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
return this; return this;
} }
/**
* Register a progress callback.
*
* @param callback
* the callback
* @since 4.8
*/
public void setCallback(Callback callback) {
this.callback = callback;
}
private static void validateDirs(File directory, File gitDir, boolean bare) private static void validateDirs(File directory, File gitDir, boolean bare)
throws IllegalStateException { throws IllegalStateException {
if (directory != null) { if (directory != null) {

20
org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java

@ -89,6 +89,8 @@ public class SubmoduleUpdateCommand extends
private MergeStrategy strategy = MergeStrategy.RECURSIVE; private MergeStrategy strategy = MergeStrategy.RECURSIVE;
private CloneCommand.Callback callback;
/** /**
* @param repo * @param repo
*/ */
@ -161,6 +163,9 @@ public class SubmoduleUpdateCommand extends
Repository submoduleRepo = generator.getRepository(); Repository submoduleRepo = generator.getRepository();
// Clone repository is not present // Clone repository is not present
if (submoduleRepo == null) { if (submoduleRepo == null) {
if (callback != null) {
callback.cloningSubmodule(generator.getPath());
}
CloneCommand clone = Git.cloneRepository(); CloneCommand clone = Git.cloneRepository();
configure(clone); configure(clone);
clone.setURI(url); clone.setURI(url);
@ -201,6 +206,10 @@ public class SubmoduleUpdateCommand extends
Constants.HEAD, true); Constants.HEAD, true);
refUpdate.setNewObjectId(commit); refUpdate.setNewObjectId(commit);
refUpdate.forceUpdate(); refUpdate.forceUpdate();
if (callback != null) {
callback.checkingOut(commit,
generator.getPath());
}
} }
} finally { } finally {
submoduleRepo.close(); submoduleRepo.close();
@ -225,4 +234,15 @@ public class SubmoduleUpdateCommand extends
this.strategy = strategy; this.strategy = strategy;
return this; return this;
} }
/**
* Set status callback for submodule clone operation.
*
* @param callback
* the callback
* @since 4.8
*/
public void setCallback(CloneCommand.Callback callback) {
this.callback = callback;
}
} }

Loading…
Cancel
Save