Browse Source

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>
stable-4.9
David Pursehouse 7 years ago
parent
commit
2dc66e93ca
  1. 7
      org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
  2. 3
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java
  3. 46
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
  4. 19
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
  5. 2
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
  6. 1
      org.eclipse.jgit/META-INF/MANIFEST.MF
  7. 34
      org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
  8. 22
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
  9. 2
      org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java
  10. 1
      org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
  11. 13
      org.eclipse.jgit/src/org/eclipse/jgit/lib/SubmoduleConfig.java
  12. 9
      org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java

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

@ -67,12 +67,14 @@ failedToLockIndex=failed to lock index
failedToLockTag=Failed to lock tag {0}: {1} failedToLockTag=Failed to lock tag {0}: {1}
fatalError=fatal: {0} 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: 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 fileIsRequired=argument file is required
ffNotPossibleAborting=Not possible to fast-forward, aborting. ffNotPossibleAborting=Not possible to fast-forward, aborting.
forcedUpdate=forced update forcedUpdate=forced update
fromURI=From {0} fromURI=From {0}
initializedEmptyGitRepositoryIn=Initialized empty Git repository in {0} initializedEmptyGitRepositoryIn=Initialized empty Git repository in {0}
invalidHttpProxyOnlyHttpSupported=Invalid http_proxy: {0}: Only http supported. invalidHttpProxyOnlyHttpSupported=Invalid http_proxy: {0}: Only http supported.
invalidRecurseSubmodulesMode=Invalid recurse submodules mode: {0}
jgitVersion=jgit version {0} jgitVersion=jgit version {0}
lineFormat={0} lineFormat={0}
listeningOn=Listening on {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_addFileContentsToTheIndex=Add file contents to the index
usage_alterTheDetailShown=alter the detail shown usage_alterTheDetailShown=alter the detail shown
usage_approveDestructionOfRepository=approve destruction of repository 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_archiveFormat=archive format. Currently supported formats: 'tar', 'zip', 'tgz', 'tbz2', 'txz'
usage_archiveOutput=output file to write the archive to usage_archiveOutput=output file to write the archive to
usage_archivePrefix=string to prepend to each pathname in the archive 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_noCommit=Don't commit after a successful merge
usage_noPrefix=do not show any source or destination prefix usage_noPrefix=do not show any source or destination prefix
usage_noRenames=disable rename detection 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_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_onlyMatchAgainstAlreadyTrackedFiles=Only match <filepattern> against already tracked files in the index rather than the working tree
usage_outputFile=Output file 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_runLfsStore=Run LFS Store in a given directory
usage_S3NoSslVerify=Skip verification of Amazon server certificate and hostname usage_S3NoSslVerify=Skip verification of Amazon server certificate and hostname
usage_setTheGitRepositoryToOperateOn=set the git repository to operate on 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_showRefNamesMatchingCommits=Show ref names matching commits
usage_showPatch=display patch usage_showPatch=display patch
usage_showNotes=Add this ref to the list of note branches from which notes are displayed usage_showNotes=Add this ref to the list of note branches from which notes are displayed

3
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java

@ -90,6 +90,9 @@ abstract class AbstractFetchCommand extends TextBuiltin {
} }
} }
showRemoteMessages(errw, r.getMessages()); showRemoteMessages(errw, r.getMessages());
for (FetchResult submoduleResult : r.submoduleResults().values()) {
showFetchResult(submoduleResult);
}
} }
static void showRemoteMessages(ThrowingPrintWriter writer, String pkt) throws IOException { static void showRemoteMessages(ThrowingPrintWriter writer, String pkt) throws IOException {

46
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java

@ -45,11 +45,15 @@
package org.eclipse.jgit.pgm; package org.eclipse.jgit.pgm;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List; import java.util.List;
import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Constants; 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.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RefSpec;
@ -58,7 +62,7 @@ import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option; import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_updateRemoteRefsFromAnotherRepository") @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") @Option(name = "--timeout", metaVar = "metaVar_seconds", usage = "usage_abortConnectionIfNoActivity")
int timeout = -1; int timeout = -1;
@ -96,6 +100,31 @@ class Fetch extends AbstractFetchCommand {
tags = Boolean.FALSE; 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") @Argument(index = 0, metaVar = "metaVar_uriish")
private String remote = Constants.DEFAULT_REMOTE_NAME; private String remote = Constants.DEFAULT_REMOTE_NAME;
@ -124,12 +153,25 @@ class Fetch extends AbstractFetchCommand {
fetch.setThin(thin.booleanValue()); fetch.setThin(thin.booleanValue());
if (quiet == null || !quiet.booleanValue()) if (quiet == null || !quiet.booleanValue())
fetch.setProgressMonitor(new TextProgressMonitor(errw)); fetch.setProgressMonitor(new TextProgressMonitor(errw));
fetch.setRecurseSubmodules(recurseSubmodules).setCallback(this);
FetchResult result = fetch.call(); FetchResult result = fetch.call();
if (result.getTrackingRefUpdates().isEmpty()) if (result.getTrackingRefUpdates().isEmpty()
&& result.submoduleResults().isEmpty())
return; return;
showFetchResult(result); showFetchResult(result);
} }
} }
@Override
public void fetchingSubmodule(String name) {
try {
outw.println(MessageFormat.format(CLIText.get().fetchingSubmodule,
name));
outw.flush();
} catch (IOException e) {
// ignore
}
}
} }

19
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java

@ -57,6 +57,10 @@ import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; 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.AwtAuthenticator;
import org.eclipse.jgit.awtui.AwtCredentialsProvider; import org.eclipse.jgit.awtui.AwtCredentialsProvider;
@ -98,6 +102,8 @@ public class Main {
PrintWriter writer; PrintWriter writer;
private ExecutorService gcExecutor;
/** /**
* *
*/ */
@ -105,6 +111,17 @@ public class Main {
HttpTransport.setConnectionFactory(new HttpClientConnectionFactory()); HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
CleanFilter.register(); CleanFilter.register();
SmudgeFilter.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 @@ public class Main {
// broken pipe // broken pipe
exit(1, null); exit(1, null);
} }
gcExecutor.shutdown();
gcExecutor.awaitTermination(10, TimeUnit.MINUTES);
} }
PrintWriter createErrorWriter() { PrintWriter createErrorWriter() {

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

@ -143,12 +143,14 @@ public class CLIText extends TranslationBundle {
/***/ public String failedToLockTag; /***/ public String failedToLockTag;
/***/ public String fatalError; /***/ public String fatalError;
/***/ public String fatalThisProgramWillDestroyTheRepository; /***/ public String fatalThisProgramWillDestroyTheRepository;
/***/ public String fetchingSubmodule;
/***/ public String fileIsRequired; /***/ public String fileIsRequired;
/***/ public String ffNotPossibleAborting; /***/ public String ffNotPossibleAborting;
/***/ public String forcedUpdate; /***/ public String forcedUpdate;
/***/ public String fromURI; /***/ public String fromURI;
/***/ public String initializedEmptyGitRepositoryIn; /***/ public String initializedEmptyGitRepositoryIn;
/***/ public String invalidHttpProxyOnlyHttpSupported; /***/ public String invalidHttpProxyOnlyHttpSupported;
/***/ public String invalidRecurseSubmodulesMode;
/***/ public String jgitVersion; /***/ public String jgitVersion;
/***/ public String lfsNoAccessKey; /***/ public String lfsNoAccessKey;
/***/ public String lfsNoSecretKey; /***/ public String lfsNoSecretKey;

1
org.eclipse.jgit/META-INF/MANIFEST.MF

@ -85,6 +85,7 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.0",
org.eclipse.jgit.treewalk, org.eclipse.jgit.treewalk,
org.eclipse.jgit.transport, org.eclipse.jgit.transport,
org.eclipse.jgit.submodule", org.eclipse.jgit.submodule",
org.eclipse.jgit.lib.internal;version="4.9.0";x-internal:=true,
org.eclipse.jgit.merge;version="4.9.0"; org.eclipse.jgit.merge;version="4.9.0";
uses:="org.eclipse.jgit.lib, uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk, org.eclipse.jgit.treewalk,

34
org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java

@ -99,6 +99,24 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
private FetchRecurseSubmodulesMode submoduleRecurseMode = null; 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 * @param repo
*/ */
@ -173,6 +191,9 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
.setThin(thin).setRefSpecs(refSpecs) .setThin(thin).setRefSpecs(refSpecs)
.setDryRun(dryRun) .setDryRun(dryRun)
.setRecurseSubmodules(recurseMode); .setRecurseSubmodules(recurseMode);
if (callback != null) {
callback.fetchingSubmodule(walk.getPath());
}
results.addSubmodule(walk.getPath(), f.call()); results.addSubmodule(walk.getPath(), f.call());
} }
} }
@ -434,4 +455,17 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
this.tagOption = tagOpt; this.tagOption = tagOpt;
return this; 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;
}
} }

22
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

@ -78,7 +78,6 @@ import java.util.TreeMap;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -107,6 +106,7 @@ import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Ref.Storage; 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.RefDatabase;
import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.lib.ReflogReader;
@ -151,7 +151,19 @@ public class GC {
private static final int DEFAULT_AUTOLIMIT = 6700; 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; private final FileRepository repo;
@ -271,7 +283,7 @@ public class GC {
} }
return Collections.emptyList(); return Collections.emptyList();
}; };
Future<Collection<PackFile>> result = executor.submit(gcTask); Future<Collection<PackFile>> result = executor().submit(gcTask);
if (background) { if (background) {
// TODO(ms): in 5.0 change signature and return the Future // TODO(ms): in 5.0 change signature and return the Future
return Collections.emptyList(); return Collections.emptyList();
@ -283,6 +295,10 @@ public class GC {
} }
} }
private ExecutorService executor() {
return (executor != null) ? executor : WorkQueue.getExecutor();
}
private Collection<PackFile> doGc() throws IOException, ParseException { private Collection<PackFile> doGc() throws IOException, ParseException {
if (automatic && !needGc()) { if (automatic && !needGc()) {
return Collections.emptyList(); return Collections.emptyList();

2
org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java

@ -46,6 +46,8 @@ package org.eclipse.jgit.lib;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.internal.WorkQueue;
/** ProgressMonitor that batches update events. */ /** ProgressMonitor that batches update events. */
public abstract class BatchingProgressMonitor implements ProgressMonitor { public abstract class BatchingProgressMonitor implements ProgressMonitor {
private long delayStartTime; private long delayStartTime;

1
org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java

@ -55,6 +55,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.storage.file.FileRepository; 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.FS;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;

13
org.eclipse.jgit/src/org/eclipse/jgit/lib/SubmoduleConfig.java

@ -43,6 +43,10 @@
package org.eclipse.jgit.lib; package org.eclipse.jgit.lib;
import java.util.Locale;
import org.eclipse.jgit.util.StringUtils;
/** /**
* Submodule section of a Git configuration file. * Submodule section of a Git configuration file.
* *
@ -75,12 +79,17 @@ public class SubmoduleConfig {
@Override @Override
public String toConfigValue() { public String toConfigValue() {
return configValue; return name().toLowerCase(Locale.ROOT).replace('_', '-');
} }
@Override @Override
public boolean matchConfigValue(String s) { 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);
} }
} }
} }

9
org.eclipse.jgit/src/org/eclipse/jgit/lib/WorkQueue.java → org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java

@ -41,7 +41,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
@ -50,7 +50,7 @@ import java.util.concurrent.ThreadFactory;
/** /**
* Simple work queue to run tasks in the background * Simple work queue to run tasks in the background
*/ */
class WorkQueue { public class WorkQueue {
private static final ScheduledThreadPoolExecutor executor; private static final ScheduledThreadPoolExecutor executor;
static final Object executorKiller; static final Object executorKiller;
@ -94,7 +94,10 @@ class WorkQueue {
}; };
} }
static ScheduledThreadPoolExecutor getExecutor() { /**
* @return the WorkQueue's executor
*/
public static ScheduledThreadPoolExecutor getExecutor() {
return executor; return executor;
} }
} }
Loading…
Cancel
Save