Merge branch 'stable-4.8'
* stable-4.8: Use a dedicated executor to run auto-gc in command line interface Allow to use an external ExecutorService for background auto-gc Fetch: Add --recurse-submodules and --no-recurse-submodules options Fix capitalization of command help summaries Change-Id: I7c85f11daa34c11c7f6389de885a2183a686197e Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
This commit is contained in:
commit
2dc66e93ca
|
@ -67,12 +67,14 @@ failedToLockIndex=failed to lock index
|
|||
failedToLockTag=Failed to lock tag {0}: {1}
|
||||
fatalError=fatal: {0}
|
||||
fatalThisProgramWillDestroyTheRepository=fatal: This program will destroy the repository\nfatal:\nfatal:\nfatal: {0}\nfatal:\nfatal: To continue, add {1} to the command line\nfatal:
|
||||
fetchingSubmodule=Fetching submodule {0}
|
||||
fileIsRequired=argument file is required
|
||||
ffNotPossibleAborting=Not possible to fast-forward, aborting.
|
||||
forcedUpdate=forced update
|
||||
fromURI=From {0}
|
||||
initializedEmptyGitRepositoryIn=Initialized empty Git repository in {0}
|
||||
invalidHttpProxyOnlyHttpSupported=Invalid http_proxy: {0}: Only http supported.
|
||||
invalidRecurseSubmodulesMode=Invalid recurse submodules mode: {0}
|
||||
jgitVersion=jgit version {0}
|
||||
lineFormat={0}
|
||||
listeningOn=Listening on {0}
|
||||
|
@ -285,7 +287,7 @@ usage_actOnRemoteTrackingBranches=act on remote-tracking branches
|
|||
usage_addFileContentsToTheIndex=Add file contents to the index
|
||||
usage_alterTheDetailShown=alter the detail shown
|
||||
usage_approveDestructionOfRepository=approve destruction of repository
|
||||
usage_archive=zip up files from the named tree
|
||||
usage_archive=Zip up files from the named tree
|
||||
usage_archiveFormat=archive format. Currently supported formats: 'tar', 'zip', 'tgz', 'tbz2', 'txz'
|
||||
usage_archiveOutput=output file to write the archive to
|
||||
usage_archivePrefix=string to prepend to each pathname in the archive
|
||||
|
@ -359,6 +361,7 @@ usage_noCheckoutAfterClone=no checkout of HEAD is performed after the clone is c
|
|||
usage_noCommit=Don't commit after a successful merge
|
||||
usage_noPrefix=do not show any source or destination prefix
|
||||
usage_noRenames=disable rename detection
|
||||
usage_noRecurseSubmodules=Disable recursive fetching of submodules (this has the same effect as using the --recurse-submodules=no option)
|
||||
usage_noShowStandardNotes=Disable showing notes from the standard /refs/notes/commits branch
|
||||
usage_onlyMatchAgainstAlreadyTrackedFiles=Only match <filepattern> against already tracked files in the index rather than the working tree
|
||||
usage_outputFile=Output file
|
||||
|
@ -384,7 +387,7 @@ usage_resetMixed=Resets the index but not the working tree
|
|||
usage_runLfsStore=Run LFS Store in a given directory
|
||||
usage_S3NoSslVerify=Skip verification of Amazon server certificate and hostname
|
||||
usage_setTheGitRepositoryToOperateOn=set the git repository to operate on
|
||||
usage_show=display one commit
|
||||
usage_show=Display one commit
|
||||
usage_showRefNamesMatchingCommits=Show ref names matching commits
|
||||
usage_showPatch=display patch
|
||||
usage_showNotes=Add this ref to the list of note branches from which notes are displayed
|
||||
|
|
|
@ -90,6 +90,9 @@ protected void showFetchResult(final FetchResult r) throws IOException {
|
|||
}
|
||||
}
|
||||
showRemoteMessages(errw, r.getMessages());
|
||||
for (FetchResult submoduleResult : r.submoduleResults().values()) {
|
||||
showFetchResult(submoduleResult);
|
||||
}
|
||||
}
|
||||
|
||||
static void showRemoteMessages(ThrowingPrintWriter writer, String pkt) throws IOException {
|
||||
|
|
|
@ -45,11 +45,15 @@
|
|||
|
||||
package org.eclipse.jgit.pgm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.api.FetchCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.SubmoduleConfig.FetchRecurseSubmodulesMode;
|
||||
import org.eclipse.jgit.pgm.internal.CLIText;
|
||||
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||
import org.eclipse.jgit.transport.FetchResult;
|
||||
import org.eclipse.jgit.transport.RefSpec;
|
||||
|
@ -58,7 +62,7 @@
|
|||
import org.kohsuke.args4j.Option;
|
||||
|
||||
@Command(common = true, usage = "usage_updateRemoteRefsFromAnotherRepository")
|
||||
class Fetch extends AbstractFetchCommand {
|
||||
class Fetch extends AbstractFetchCommand implements FetchCommand.Callback {
|
||||
@Option(name = "--timeout", metaVar = "metaVar_seconds", usage = "usage_abortConnectionIfNoActivity")
|
||||
int timeout = -1;
|
||||
|
||||
|
@ -96,6 +100,31 @@ void notags(@SuppressWarnings("unused")
|
|||
tags = Boolean.FALSE;
|
||||
}
|
||||
|
||||
private FetchRecurseSubmodulesMode recurseSubmodules;
|
||||
|
||||
@Option(name = "--recurse-submodules", usage = "usage_recurseSubmodules")
|
||||
void recurseSubmodules(String mode) {
|
||||
if (mode == null || mode.isEmpty()) {
|
||||
recurseSubmodules = FetchRecurseSubmodulesMode.YES;
|
||||
} else {
|
||||
for (FetchRecurseSubmodulesMode m : FetchRecurseSubmodulesMode
|
||||
.values()) {
|
||||
if (m.matchConfigValue(mode)) {
|
||||
recurseSubmodules = m;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw die(MessageFormat
|
||||
.format(CLIText.get().invalidRecurseSubmodulesMode, mode));
|
||||
}
|
||||
}
|
||||
|
||||
@Option(name = "--no-recurse-submodules", usage = "usage_noRecurseSubmodules")
|
||||
void noRecurseSubmodules(@SuppressWarnings("unused")
|
||||
final boolean ignored) {
|
||||
recurseSubmodules = FetchRecurseSubmodulesMode.NO;
|
||||
}
|
||||
|
||||
@Argument(index = 0, metaVar = "metaVar_uriish")
|
||||
private String remote = Constants.DEFAULT_REMOTE_NAME;
|
||||
|
||||
|
@ -124,12 +153,25 @@ protected void run() throws Exception {
|
|||
fetch.setThin(thin.booleanValue());
|
||||
if (quiet == null || !quiet.booleanValue())
|
||||
fetch.setProgressMonitor(new TextProgressMonitor(errw));
|
||||
fetch.setRecurseSubmodules(recurseSubmodules).setCallback(this);
|
||||
|
||||
FetchResult result = fetch.call();
|
||||
if (result.getTrackingRefUpdates().isEmpty())
|
||||
if (result.getTrackingRefUpdates().isEmpty()
|
||||
&& result.submoduleResults().isEmpty())
|
||||
return;
|
||||
|
||||
showFetchResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchingSubmodule(String name) {
|
||||
try {
|
||||
outw.println(MessageFormat.format(CLIText.get().fetchingSubmodule,
|
||||
name));
|
||||
outw.flush();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jgit.awtui.AwtAuthenticator;
|
||||
import org.eclipse.jgit.awtui.AwtCredentialsProvider;
|
||||
|
@ -98,6 +102,8 @@ public class Main {
|
|||
|
||||
PrintWriter writer;
|
||||
|
||||
private ExecutorService gcExecutor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -105,6 +111,17 @@ public Main() {
|
|||
HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
|
||||
CleanFilter.register();
|
||||
SmudgeFilter.register();
|
||||
gcExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||
private final ThreadFactory baseFactory = Executors
|
||||
.defaultThreadFactory();
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable taskBody) {
|
||||
Thread thr = baseFactory.newThread(taskBody);
|
||||
thr.setName("JGit-autoGc"); //$NON-NLS-1$
|
||||
return thr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,6 +209,8 @@ protected void run(final String[] argv) throws Exception {
|
|||
// broken pipe
|
||||
exit(1, null);
|
||||
}
|
||||
gcExecutor.shutdown();
|
||||
gcExecutor.awaitTermination(10, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
PrintWriter createErrorWriter() {
|
||||
|
|
|
@ -143,12 +143,14 @@ public static String fatalError(String message) {
|
|||
/***/ public String failedToLockTag;
|
||||
/***/ public String fatalError;
|
||||
/***/ public String fatalThisProgramWillDestroyTheRepository;
|
||||
/***/ public String fetchingSubmodule;
|
||||
/***/ public String fileIsRequired;
|
||||
/***/ public String ffNotPossibleAborting;
|
||||
/***/ public String forcedUpdate;
|
||||
/***/ public String fromURI;
|
||||
/***/ public String initializedEmptyGitRepositoryIn;
|
||||
/***/ public String invalidHttpProxyOnlyHttpSupported;
|
||||
/***/ public String invalidRecurseSubmodulesMode;
|
||||
/***/ public String jgitVersion;
|
||||
/***/ public String lfsNoAccessKey;
|
||||
/***/ public String lfsNoSecretKey;
|
||||
|
|
|
@ -85,6 +85,7 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.0",
|
|||
org.eclipse.jgit.treewalk,
|
||||
org.eclipse.jgit.transport,
|
||||
org.eclipse.jgit.submodule",
|
||||
org.eclipse.jgit.lib.internal;version="4.9.0";x-internal:=true,
|
||||
org.eclipse.jgit.merge;version="4.9.0";
|
||||
uses:="org.eclipse.jgit.lib,
|
||||
org.eclipse.jgit.treewalk,
|
||||
|
|
|
@ -99,6 +99,24 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
|
|||
|
||||
private FetchRecurseSubmodulesMode submoduleRecurseMode = null;
|
||||
|
||||
private Callback callback;
|
||||
|
||||
/**
|
||||
* Callback for status of fetch operation.
|
||||
*
|
||||
* @since 4.8
|
||||
*
|
||||
*/
|
||||
public interface Callback {
|
||||
/**
|
||||
* Notify fetching a submodule.
|
||||
*
|
||||
* @param name
|
||||
* the submodule name.
|
||||
*/
|
||||
void fetchingSubmodule(String name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param repo
|
||||
*/
|
||||
|
@ -173,6 +191,9 @@ private void fetchSubmodules(FetchResult results)
|
|||
.setThin(thin).setRefSpecs(refSpecs)
|
||||
.setDryRun(dryRun)
|
||||
.setRecurseSubmodules(recurseMode);
|
||||
if (callback != null) {
|
||||
callback.fetchingSubmodule(walk.getPath());
|
||||
}
|
||||
results.addSubmodule(walk.getPath(), f.call());
|
||||
}
|
||||
}
|
||||
|
@ -434,4 +455,17 @@ public FetchCommand setTagOpt(TagOpt tagOpt) {
|
|||
this.tagOption = tagOpt;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a progress callback.
|
||||
*
|
||||
* @param callback
|
||||
* the callback
|
||||
* @return {@code this}
|
||||
* @since 4.8
|
||||
*/
|
||||
public FetchCommand setCallback(Callback callback) {
|
||||
this.callback = callback;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@
|
|||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -107,6 +106,7 @@
|
|||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Ref.Storage;
|
||||
import org.eclipse.jgit.lib.internal.WorkQueue;
|
||||
import org.eclipse.jgit.lib.RefDatabase;
|
||||
import org.eclipse.jgit.lib.ReflogEntry;
|
||||
import org.eclipse.jgit.lib.ReflogReader;
|
||||
|
@ -151,7 +151,19 @@ public class GC {
|
|||
|
||||
private static final int DEFAULT_AUTOLIMIT = 6700;
|
||||
|
||||
private static ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||
private static volatile ExecutorService executor;
|
||||
|
||||
/**
|
||||
* Set the executor for running auto-gc in the background. If no executor is
|
||||
* set JGit's own WorkQueue will be used.
|
||||
*
|
||||
* @param e
|
||||
* the executor to be used for running auto-gc
|
||||
* @since 4.8
|
||||
*/
|
||||
public static void setExecutor(ExecutorService e) {
|
||||
executor = e;
|
||||
}
|
||||
|
||||
private final FileRepository repo;
|
||||
|
||||
|
@ -271,7 +283,7 @@ public Collection<PackFile> gc() throws IOException, ParseException {
|
|||
}
|
||||
return Collections.emptyList();
|
||||
};
|
||||
Future<Collection<PackFile>> result = executor.submit(gcTask);
|
||||
Future<Collection<PackFile>> result = executor().submit(gcTask);
|
||||
if (background) {
|
||||
// TODO(ms): in 5.0 change signature and return the Future
|
||||
return Collections.emptyList();
|
||||
|
@ -283,6 +295,10 @@ public Collection<PackFile> gc() throws IOException, ParseException {
|
|||
}
|
||||
}
|
||||
|
||||
private ExecutorService executor() {
|
||||
return (executor != null) ? executor : WorkQueue.getExecutor();
|
||||
}
|
||||
|
||||
private Collection<PackFile> doGc() throws IOException, ParseException {
|
||||
if (automatic && !needGc()) {
|
||||
return Collections.emptyList();
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jgit.lib.internal.WorkQueue;
|
||||
|
||||
/** ProgressMonitor that batches update events. */
|
||||
public abstract class BatchingProgressMonitor implements ProgressMonitor {
|
||||
private long delayStartTime;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
import org.eclipse.jgit.annotations.NonNull;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||
import org.eclipse.jgit.lib.internal.WorkQueue;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
import org.eclipse.jgit.util.IO;
|
||||
import org.eclipse.jgit.util.RawParseUtils;
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
|
||||
package org.eclipse.jgit.lib;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jgit.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Submodule section of a Git configuration file.
|
||||
*
|
||||
|
@ -75,12 +79,17 @@ private FetchRecurseSubmodulesMode(String configValue) {
|
|||
|
||||
@Override
|
||||
public String toConfigValue() {
|
||||
return configValue;
|
||||
return name().toLowerCase(Locale.ROOT).replace('_', '-');
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchConfigValue(String s) {
|
||||
return configValue.equals(s);
|
||||
if (StringUtils.isEmptyOrNull(s)) {
|
||||
return false;
|
||||
}
|
||||
s = s.replace('-', '_');
|
||||
return name().equalsIgnoreCase(s)
|
||||
|| configValue.equalsIgnoreCase(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.eclipse.jgit.lib;
|
||||
package org.eclipse.jgit.lib.internal;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
|
@ -50,7 +50,7 @@
|
|||
/**
|
||||
* Simple work queue to run tasks in the background
|
||||
*/
|
||||
class WorkQueue {
|
||||
public class WorkQueue {
|
||||
private static final ScheduledThreadPoolExecutor executor;
|
||||
|
||||
static final Object executorKiller;
|
||||
|
@ -94,7 +94,10 @@ protected void finalize() {
|
|||
};
|
||||
}
|
||||
|
||||
static ScheduledThreadPoolExecutor getExecutor() {
|
||||
/**
|
||||
* @return the WorkQueue's executor
|
||||
*/
|
||||
public static ScheduledThreadPoolExecutor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue