diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/StrictWorkMonitor.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/StrictWorkMonitor.java index 96d7aac54..c77bca975 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/StrictWorkMonitor.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/StrictWorkMonitor.java @@ -50,4 +50,9 @@ public void endTask() { public boolean isCancelled() { return false; } + + @Override + public void showDuration(boolean enabled) { + // not implemented + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java index 6a84f0a38..7a0ffdbec 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java @@ -378,44 +378,44 @@ public void testPullMergeProgrammaticConfigurationImpliedTargetBranch() } private enum TestPullMode { - MERGE, REBASE, REBASE_PREASERVE + MERGE, REBASE, REBASE_MERGES } @Test /** global rebase config should be respected */ - public void testPullWithRebasePreserve1Config() throws Exception { + public void testPullWithRebaseMerges1Config() throws Exception { Callable setup = () -> { StoredConfig config = dbTarget.getConfig(); - config.setString("pull", null, "rebase", "preserve"); + config.setString("pull", null, "rebase", "merges"); config.save(); return target.pull().call(); }; - doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); + doTestPullWithRebase(setup, TestPullMode.REBASE_MERGES); } @Test /** the branch-local config should win over the global config */ - public void testPullWithRebasePreserveConfig2() throws Exception { + public void testPullWithRebaseMergesConfig2() throws Exception { Callable setup = () -> { StoredConfig config = dbTarget.getConfig(); config.setString("pull", null, "rebase", "false"); - config.setString("branch", "master", "rebase", "preserve"); + config.setString("branch", "master", "rebase", "merges"); config.save(); return target.pull().call(); }; - doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); + doTestPullWithRebase(setup, TestPullMode.REBASE_MERGES); } @Test /** the branch-local config should be respected */ - public void testPullWithRebasePreserveConfig3() throws Exception { + public void testPullWithRebaseMergesConfig3() throws Exception { Callable setup = () -> { StoredConfig config = dbTarget.getConfig(); - config.setString("branch", "master", "rebase", "preserve"); + config.setString("branch", "master", "rebase", "merges"); config.save(); return target.pull().call(); }; - doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); + doTestPullWithRebase(setup, TestPullMode.REBASE_MERGES); } @Test @@ -435,7 +435,7 @@ public void testPullWithRebaseConfig1() throws Exception { public void testPullWithRebaseConfig2() throws Exception { Callable setup = () -> { StoredConfig config = dbTarget.getConfig(); - config.setString("pull", null, "rebase", "preserve"); + config.setString("pull", null, "rebase", "merges"); config.setString("branch", "master", "rebase", "true"); config.save(); return target.pull().call(); @@ -543,7 +543,7 @@ private void doTestPullWithRebase(Callable pullSetup, assertEquals(sourceCommit, next.getParent(1)); // since both parents are known do no further checks here } else { - if (expectedPullMode == TestPullMode.REBASE_PREASERVE) { + if (expectedPullMode == TestPullMode.REBASE_MERGES) { next = rw.next(); assertEquals(2, next.getParentCount()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java index 3fe8f52fb..2a403c769 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java @@ -504,6 +504,43 @@ public void testWriteIndex() throws Exception { } } + @Test + public void testWriteObjectSizeIndex_noDeltas() throws Exception { + config.setMinBytesForObjSizeIndex(0); + HashSet interesting = new HashSet<>(); + interesting.add(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); + + NullProgressMonitor m1 = NullProgressMonitor.INSTANCE; + writer = new PackWriter(config, db.newObjectReader()); + writer.setUseBitmaps(false); + writer.setThin(false); + writer.setIgnoreMissingUninteresting(false); + writer.preparePack(m1, interesting, NONE); + writer.writePack(m1, m1, os); + + PackIndex idx; + try (ByteArrayOutputStream is = new ByteArrayOutputStream()) { + writer.writeIndex(is); + idx = PackIndex.read(new ByteArrayInputStream(is.toByteArray())); + } + + PackObjectSizeIndex objSizeIdx; + try (ByteArrayOutputStream objSizeStream = new ByteArrayOutputStream()) { + writer.writeObjectSizeIndex(objSizeStream); + objSizeIdx = PackObjectSizeIndexLoader.load( + new ByteArrayInputStream(objSizeStream.toByteArray())); + } + writer.close(); + + ObjectId knownBlob1 = ObjectId + .fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"); + ObjectId knownBlob2 = ObjectId + .fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"); + assertEquals(18009, objSizeIdx.getSize(idx.findPosition(knownBlob1))); + assertEquals(18787, objSizeIdx.getSize(idx.findPosition(knownBlob2))); + } + @Test public void testExclude() throws Exception { // TestRepository closes repo diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStreamTest.java index 09a7c0b28..58ed7850b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStreamTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/io/CancellableDigestOutputStreamTest.java @@ -54,6 +54,11 @@ public void endTask() { public boolean isCancelled() { return cancelled; } + + @Override + public void showDuration(boolean enabled) { + // not implemented + } } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ThreadSafeProgressMonitorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ThreadSafeProgressMonitorTest.java index 8f84155dd..e21ff580b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ThreadSafeProgressMonitorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ThreadSafeProgressMonitorTest.java @@ -167,5 +167,10 @@ public void endTask() { public boolean isCancelled() { return false; } + + @Override + public void showDuration(boolean enabled) { + // not implemented + } } } diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index bc4e9ea1c..e215f7aa3 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -1,5 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -42,6 +92,14 @@ + + + + + + + + @@ -58,6 +116,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java index 281ecfd01..83ae0fc9d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -137,8 +137,8 @@ public PullCommand setRebase(boolean useRebase) { *
BranchRebaseMode.REBASE
*
Equivalent to {@code --rebase} on the command line: use rebase * instead of merge after fetching.
- *
BranchRebaseMode.PRESERVE
- *
Equivalent to {@code --preserve-merges} on the command line: rebase + *
BranchRebaseMode.MERGES
+ *
Equivalent to {@code --rebase-merges} on the command line: rebase * preserving local merge commits.
*
BranchRebaseMode.INTERACTIVE
*
Equivalent to {@code --interactive} on the command line: use @@ -362,7 +362,7 @@ public PullResult call() throws GitAPIException, .setStrategy(strategy) .setContentMergeStrategy(contentStrategy) .setPreserveMerges( - pullRebaseMode == BranchRebaseMode.PRESERVE) + pullRebaseMode == BranchRebaseMode.MERGES) .call(); result = new PullResult(fetchRes, remote, rebaseRes); } else { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java index 4e0d9d78c..1e5523f27 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java @@ -151,7 +151,7 @@ public class RebaseCommand extends GitCommand { /** * The folder containing the hashes of (potentially) rewritten commits when - * --preserve-merges is used. + * --rebase-merges is used. *

* Native git rebase --merge uses a file of that name to record * commits to copy notes at the end of the whole rebase. @@ -160,7 +160,7 @@ public class RebaseCommand extends GitCommand { private static final String REWRITTEN = "rewritten"; //$NON-NLS-1$ /** - * File containing the current commit(s) to cherry pick when --preserve-merges + * File containing the current commit(s) to cherry pick when --rebase-merges * is used. */ private static final String CURRENT_COMMIT = "current-commit"; //$NON-NLS-1$ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index 502262a5f..a350561cc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -279,17 +279,17 @@ private Collection doGc() throws IOException, ParseException { if (!lock.lock()) { return Collections.emptyList(); } - pm.start(6 /* tasks */); - packRefs(); - // TODO: implement reflog_expire(pm, repo); - Collection newPacks = repack(); - prune(Collections.emptySet()); - // TODO: implement rerere_gc(pm); - if (shouldWriteCommitGraphWhenGc()) { - writeCommitGraph(refsToObjectIds(getAllRefs())); + pm.start(6 /* tasks */); + packRefs(); + // TODO: implement reflog_expire(pm, repo); + Collection newPacks = repack(); + prune(Collections.emptySet()); + // TODO: implement rerere_gc(pm); + if (shouldWriteCommitGraphWhenGc()) { + writeCommitGraph(refsToObjectIds(getAllRefs())); + } + return newPacks; } - return newPacks; - } } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java index 1d02c0279..adad411c6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java @@ -33,7 +33,10 @@ public enum PackExt { REVERSE_INDEX("rev"), //$NON-NLS-1$ /** A commit graph file extension. */ - COMMIT_GRAPH("graph"); //$NON-NLS-1$ + COMMIT_GRAPH("graph"), //$NON-NLS-1$ + + /** An object size index. */ + OBJECT_SIZE_INDEX("objsize"); //$NON-NLS-1$ private final String ext; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index d42d348a1..bad572459 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -61,6 +61,7 @@ import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexWriterV1; import org.eclipse.jgit.internal.storage.file.PackIndexWriter; +import org.eclipse.jgit.internal.storage.file.PackObjectSizeIndexWriter; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AsyncObjectSizeQueue; import org.eclipse.jgit.lib.BatchingProgressMonitor; @@ -1091,6 +1092,50 @@ public void writeIndex(OutputStream indexStream) throws IOException { stats.timeWriting += System.currentTimeMillis() - writeStart; } + /** + * Create an object size index file for the contents of the pack file just + * written. + *

+ * Called after + * {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)} that + * populates the list of objects to pack and before + * {@link #writeBitmapIndex(OutputStream)} that destroys it. + *

+ * Writing this index is only required for local pack storage. Packs sent on + * the network do not need to create an object size index. + * + * @param objIdxStream + * output for the object size index data. Caller is responsible + * for closing this stream. + * @throws IOException + * errors while writing + */ + public void writeObjectSizeIndex(OutputStream objIdxStream) + throws IOException { + if (config.getMinBytesForObjSizeIndex() < 0) { + return; + } + + long writeStart = System.currentTimeMillis(); + // We only need to populate the size of blobs + AsyncObjectSizeQueue sizeQueue = reader + .getObjectSize(objectsLists[OBJ_BLOB], /* reportMissing= */false); + try { + while (sizeQueue.next()) { + ObjectToPack otp = sizeQueue.getCurrent(); + long sz = sizeQueue.getSize(); + otp.setFullSize(sz); + } + } finally { + sizeQueue.release(); + } + PackObjectSizeIndexWriter iw = PackObjectSizeIndexWriter.createWriter( + objIdxStream, config.getMinBytesForObjSizeIndex()); + // All indexed objects because their positions must match primary index order + iw.write(sortByName()); + stats.timeWriting += System.currentTimeMillis() - writeStart; + } + /** * Create a bitmap index file to match the pack file just written. *

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java index 49e295aed..f82605737 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java @@ -10,21 +10,29 @@ package org.eclipse.jgit.lib; +import java.time.Duration; +import java.time.Instant; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.lib.internal.WorkQueue; +import org.eclipse.jgit.util.SystemReader; /** * ProgressMonitor that batches update events. */ public abstract class BatchingProgressMonitor implements ProgressMonitor { + private static boolean performanceTrace = SystemReader.getInstance() + .isPerformanceTraceEnabled(); + private long delayStartTime; private TimeUnit delayStartUnit = TimeUnit.MILLISECONDS; private Task task; + private Boolean showDuration; + /** * Set an optional delay before the first output. * @@ -76,6 +84,11 @@ public boolean isCancelled() { return false; } + @Override + public void showDuration(boolean enabled) { + showDuration = Boolean.valueOf(enabled); + } + /** * Update the progress monitor if the total work isn't known, * @@ -83,8 +96,12 @@ public boolean isCancelled() { * name of the task. * @param workCurr * number of units already completed. + * @param duration + * how long this task runs + * @since 6.5 */ - protected abstract void onUpdate(String taskName, int workCurr); + protected abstract void onUpdate(String taskName, int workCurr, + Duration duration); /** * Finish the progress monitor when the total wasn't known in advance. @@ -93,8 +110,12 @@ public boolean isCancelled() { * name of the task. * @param workCurr * total number of units processed. + * @param duration + * how long this task runs + * @since 6.5 */ - protected abstract void onEndTask(String taskName, int workCurr); + protected abstract void onEndTask(String taskName, int workCurr, + Duration duration); /** * Update the progress monitor when the total is known in advance. @@ -107,9 +128,12 @@ public boolean isCancelled() { * estimated number of units to process. * @param percentDone * {@code workCurr * 100 / workTotal}. + * @param duration + * how long this task runs + * @since 6.5 */ protected abstract void onUpdate(String taskName, int workCurr, - int workTotal, int percentDone); + int workTotal, int percentDone, Duration duration); /** * Finish the progress monitor when the total is known in advance. @@ -122,9 +146,58 @@ protected abstract void onUpdate(String taskName, int workCurr, * estimated number of units to process. * @param percentDone * {@code workCurr * 100 / workTotal}. + * @param duration + * duration of the task + * @since 6.5 */ protected abstract void onEndTask(String taskName, int workCurr, - int workTotal, int percentDone); + int workTotal, int percentDone, Duration duration); + + private boolean showDuration() { + return showDuration != null ? showDuration.booleanValue() + : performanceTrace; + } + + /** + * Append formatted duration if system property or environment variable + * GIT_TRACE_PERFORMANCE is set to "true". If both are defined the system + * property takes precedence. + * + * @param s + * StringBuilder to append the formatted duration to + * @param duration + * duration to format + * @since 6.5 + */ + @SuppressWarnings({ "boxing", "nls" }) + protected void appendDuration(StringBuilder s, Duration duration) { + if (!showDuration()) { + return; + } + long hours = duration.toHours(); + int minutes = duration.toMinutesPart(); + int seconds = duration.toSecondsPart(); + s.append(" ["); + if (hours > 0) { + s.append(hours).append(':'); + s.append(String.format("%02d", minutes)).append(':'); + s.append(String.format("%02d", seconds)); + } else if (minutes > 0) { + s.append(minutes).append(':'); + s.append(String.format("%02d", seconds)); + } else { + s.append(seconds); + } + s.append('.').append(String.format("%03d", duration.toMillisPart())); + if (hours > 0) { + s.append('h'); + } else if (minutes > 0) { + s.append('m'); + } else { + s.append('s'); + } + s.append(']'); + } private static class Task implements Runnable { /** Title of the current task. */ @@ -148,10 +221,13 @@ private static class Task implements Runnable { /** Percentage of {@link #totalWork} that is done. */ private int lastPercent; + private final Instant startTime; + Task(String taskName, int totalWork) { this.taskName = taskName; this.totalWork = totalWork; this.display = true; + this.startTime = Instant.now(); } void delay(long time, TimeUnit unit) { @@ -170,7 +246,7 @@ void update(BatchingProgressMonitor pm, int completed) { if (totalWork == UNKNOWN) { // Only display once per second, as the alarm fires. if (display) { - pm.onUpdate(taskName, lastWork); + pm.onUpdate(taskName, lastWork, elapsedTime()); output = true; restartTimer(); } @@ -178,12 +254,14 @@ void update(BatchingProgressMonitor pm, int completed) { // Display once per second or when 1% is done. int currPercent = Math.round(lastWork * 100F / totalWork); if (display) { - pm.onUpdate(taskName, lastWork, totalWork, currPercent); + pm.onUpdate(taskName, lastWork, totalWork, currPercent, + elapsedTime()); output = true; restartTimer(); lastPercent = currPercent; } else if (currPercent != lastPercent) { - pm.onUpdate(taskName, lastWork, totalWork, currPercent); + pm.onUpdate(taskName, lastWork, totalWork, currPercent, + elapsedTime()); output = true; lastPercent = currPercent; } @@ -199,14 +277,18 @@ private void restartTimer() { void end(BatchingProgressMonitor pm) { if (output) { if (totalWork == UNKNOWN) { - pm.onEndTask(taskName, lastWork); + pm.onEndTask(taskName, lastWork, elapsedTime()); } else { int currPercent = Math.round(lastWork * 100F / totalWork); - pm.onEndTask(taskName, lastWork, totalWork, currPercent); + pm.onEndTask(taskName, lastWork, totalWork, currPercent, elapsedTime()); } } if (timerFuture != null) timerFuture.cancel(false /* no interrupt */); } + + private Duration elapsedTime() { + return Duration.between(startTime, Instant.now()); + } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java index aa613d07e..19495dff1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java @@ -30,8 +30,12 @@ public enum BranchRebaseMode implements Config.ConfigEnum { /** Value for rebasing */ REBASE("true"), //$NON-NLS-1$ - /** Value for rebasing preserving local merge commits */ - PRESERVE("preserve"), //$NON-NLS-1$ + /** + * Value for rebasing preserving local merge commits + * + * @since 6.5 used instead of deprecated "preserve" option + */ + MERGES("merges"), //$NON-NLS-1$ /** Value for rebasing interactively */ INTERACTIVE("interactive"), //$NON-NLS-1$ /** Value for not rebasing at all but merging */ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java index 6b201e6bc..94d28eb34 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java @@ -48,4 +48,8 @@ public boolean isCancelled() { return false; } + @Override + public void showDuration(boolean enabled) { + // not implemented + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java index 10904b695..127cca9d1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java @@ -52,4 +52,9 @@ public boolean isCancelled() { public void endTask() { // Do not report. } + + @Override + public void showDuration(boolean enabled) { + // don't show + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ProgressMonitor.java index 9ebb0a46b..2ce73ace8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ProgressMonitor.java @@ -65,4 +65,13 @@ public interface ProgressMonitor { * @return true if the user asked the process to stop working. */ boolean isCancelled(); + + /** + * Set whether the monitor should show elapsed time per task + * + * @param enabled + * whether to show elapsed time per task + * @since 6.5 + */ + void showDuration(boolean enabled); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java index 03a78eb8a..85aa0b663 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java @@ -17,6 +17,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; +import java.time.Duration; /** * A simple progress reporter printing on a stream. @@ -46,49 +47,53 @@ public TextProgressMonitor(Writer out) { /** {@inheritDoc} */ @Override - protected void onUpdate(String taskName, int workCurr) { + protected void onUpdate(String taskName, int workCurr, Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, workCurr); + format(s, taskName, workCurr, duration); send(s); } /** {@inheritDoc} */ @Override - protected void onEndTask(String taskName, int workCurr) { + protected void onEndTask(String taskName, int workCurr, Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, workCurr); + format(s, taskName, workCurr, duration); s.append("\n"); //$NON-NLS-1$ send(s); } - private void format(StringBuilder s, String taskName, int workCurr) { + private void format(StringBuilder s, String taskName, int workCurr, + Duration duration) { s.append("\r"); //$NON-NLS-1$ s.append(taskName); s.append(": "); //$NON-NLS-1$ while (s.length() < 25) s.append(' '); s.append(workCurr); + appendDuration(s, duration); } /** {@inheritDoc} */ @Override - protected void onUpdate(String taskName, int cmp, int totalWork, int pcnt) { + protected void onUpdate(String taskName, int cmp, int totalWork, int pcnt, + Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, cmp, totalWork, pcnt); + format(s, taskName, cmp, totalWork, pcnt, duration); send(s); } /** {@inheritDoc} */ @Override - protected void onEndTask(String taskName, int cmp, int totalWork, int pcnt) { + protected void onEndTask(String taskName, int cmp, int totalWork, int pcnt, + Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, cmp, totalWork, pcnt); + format(s, taskName, cmp, totalWork, pcnt, duration); s.append("\n"); //$NON-NLS-1$ send(s); } private void format(StringBuilder s, String taskName, int cmp, - int totalWork, int pcnt) { + int totalWork, int pcnt, Duration duration) { s.append("\r"); //$NON-NLS-1$ s.append(taskName); s.append(": "); //$NON-NLS-1$ @@ -106,9 +111,10 @@ private void format(StringBuilder s, String taskName, int cmp, s.append(pcnt); s.append("% ("); //$NON-NLS-1$ s.append(curStr); - s.append("/"); //$NON-NLS-1$ + s.append('/'); s.append(endStr); - s.append(")"); //$NON-NLS-1$ + s.append(')'); + appendDuration(s, duration); } private void send(StringBuilder s) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java index 180fbdc46..e55395556 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java @@ -158,6 +158,11 @@ public void endTask() { pm.endTask(); } + @Override + public void showDuration(boolean enabled) { + pm.showDuration(enabled); + } + private boolean isMainThread() { return Thread.currentThread() == mainThread; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SideBandProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SideBandProgressMonitor.java index 83e8bc291..33308600d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SideBandProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SideBandProgressMonitor.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.OutputStream; +import java.time.Duration; import org.eclipse.jgit.lib.BatchingProgressMonitor; import org.eclipse.jgit.lib.Constants; @@ -29,48 +30,52 @@ class SideBandProgressMonitor extends BatchingProgressMonitor { /** {@inheritDoc} */ @Override - protected void onUpdate(String taskName, int workCurr) { + protected void onUpdate(String taskName, int workCurr, Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, workCurr); + format(s, taskName, workCurr, duration); s.append(" \r"); //$NON-NLS-1$ send(s); } /** {@inheritDoc} */ @Override - protected void onEndTask(String taskName, int workCurr) { + protected void onEndTask(String taskName, int workCurr, Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, workCurr); + format(s, taskName, workCurr, duration); s.append(", done\n"); //$NON-NLS-1$ send(s); } - private void format(StringBuilder s, String taskName, int workCurr) { + private void format(StringBuilder s, String taskName, int workCurr, + Duration duration) { s.append(taskName); s.append(": "); //$NON-NLS-1$ s.append(workCurr); + appendDuration(s, duration); } /** {@inheritDoc} */ @Override - protected void onUpdate(String taskName, int cmp, int totalWork, int pcnt) { + protected void onUpdate(String taskName, int cmp, int totalWork, int pcnt, + Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, cmp, totalWork, pcnt); + format(s, taskName, cmp, totalWork, pcnt, duration); s.append(" \r"); //$NON-NLS-1$ send(s); } /** {@inheritDoc} */ @Override - protected void onEndTask(String taskName, int cmp, int totalWork, int pcnt) { + protected void onEndTask(String taskName, int cmp, int totalWork, int pcnt, + Duration duration) { StringBuilder s = new StringBuilder(); - format(s, taskName, cmp, totalWork, pcnt); + format(s, taskName, cmp, totalWork, pcnt, duration); s.append("\n"); //$NON-NLS-1$ send(s); } private void format(StringBuilder s, String taskName, int cmp, - int totalWork, int pcnt) { + int totalWork, int pcnt, Duration duration) { s.append(taskName); s.append(": "); //$NON-NLS-1$ if (pcnt < 100) @@ -80,9 +85,10 @@ private void format(StringBuilder s, String taskName, int cmp, s.append(pcnt); s.append("% ("); //$NON-NLS-1$ s.append(cmp); - s.append("/"); //$NON-NLS-1$ + s.append('/'); s.append(totalWork); - s.append(")"); //$NON-NLS-1$ + s.append(')'); + appendDuration(s, duration); } private void send(StringBuilder s) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java index 5ced0713e..a8a77904a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java @@ -65,6 +65,21 @@ public abstract class SystemReader { private static volatile Boolean isLinux; + private static final String GIT_TRACE_PERFORMANCE = "GIT_TRACE_PERFORMANCE"; //$NON-NLS-1$ + + private static final boolean performanceTrace = initPerformanceTrace(); + + private static boolean initPerformanceTrace() { + String val = System.getenv(GIT_TRACE_PERFORMANCE); + if (val == null) { + val = System.getenv(GIT_TRACE_PERFORMANCE); + } + if (val != null) { + return Boolean.valueOf(val).booleanValue(); + } + return false; + } + static { SystemReader r = new Default(); r.init(); @@ -560,6 +575,16 @@ public boolean isLinux() { return isLinux.booleanValue(); } + /** + * Whether performance trace is enabled + * + * @return whether performance trace is enabled + * @since 6.5 + */ + public boolean isPerformanceTraceEnabled() { + return performanceTrace; + } + private String getOsName() { return AccessController.doPrivileged( (PrivilegedAction) () -> getProperty("os.name") //$NON-NLS-1$