aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/config-options.md5
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java18
-rw-r--r--org.eclipse.jgit/.settings/.api_filters12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java6
6 files changed, 49 insertions, 9 deletions
diff --git a/Documentation/config-options.md b/Documentation/config-options.md
index 754accf787..cbcb36a250 100644
--- a/Documentation/config-options.md
+++ b/Documentation/config-options.md
@@ -42,6 +42,7 @@ For details on native git options see also the official [git config documentatio
| `core.precomposeUnicode` | `true` on Mac OS | ✅ | MacOS only. When `true`, JGit reverts the unicode decomposition of filenames done by Mac OS. |
| `core.quotePath` | `true` | ✅ | Commands that output paths (e.g. ls-files, diff), will quote "unusual" characters in the pathname by enclosing the pathname in double-quotes and escaping those characters with backslashes in the same way C escapes control characters (e.g. `\t` for TAB, `\n` for LF, `\\` for backslash) or bytes with values larger than `0x80` (e.g. octal `\302\265` for "micro" in UTF-8). |
| `core.repositoryFormatVersion` | `1` | ⃞ | Internal version identifying the repository format and layout version. Don't set manually. |
+| `core.sha1Implementation` | `java` | ⃞ | Choose the SHA1 implementation used by JGit. Set it to `java` to use JGit's Java implementation which detects SHA1 collisions if system property `org.eclipse.jgit.util.sha1.detectCollision` is unset or `true`. Set it to `jdkNative` to use the native implementation available in the JDK, can also be set using system property `org.eclipse.jgit.util.sha1.implementation`. If both are set the system property takes precedence. Performance of `jdkNative` is around 10% higher than `java` when `detectCollision=false` and 30% higher when `detectCollision=true`.|
| `core.streamFileThreshold` | `50 MiB` | ⃞ | The size threshold beyond which objects must be streamed. |
| `core.supportsAtomicFileCreation` | `true` | ⃞ | Whether the filesystem supports atomic file creation. |
| `core.symlinks` | Auto detect if filesystem supports symlinks| ✅ | If false, symbolic links are checked out as small plain files that contain the link text. |
@@ -101,8 +102,8 @@ Proxy configuration uses the standard Java mechanisms via class `java.net.ProxyS
| `pack.indexVersion` | `2` | ✅ | Pack index file format version. |
| `pack.minBytesForObjSizeIndex` | `-1` | ⃞ | Minimum size of an object (inclusive, in bytes) to be included in the size index. -1 to disable the object size index. |
| `pack.minSizePreventRacyPack` | `100 MiB` | ⃞ | Minimum packfile size for which we wait before opening a newly written pack to prevent its lastModified timestamp could be racy if `pack.waitPreventRacyPack` is `true`. |
-| `pack.preserveOldPacks` | `false` | ⃞ | Whether to preserve old packs in a preserved directory. |
-| `prunePreserved`, only via API of PackConfig | `false` | ⃞ | Whether to remove preserved pack files in a preserved directory. |
+| `pack.preserveOldPacks` | `false` | ⃞ | Whether to preserve old packs during gc in the `objects/pack/preserved` directory. This can avoid rare races between gc removing pack files and other concurrent operations. If this option is false data loss can occur in rare cases when an object is believed to be unreferenced when object repacking is running, and then garbage collection deletes it while another concurrent operation references this object shortly before garbage collection deletes it. When this happens, a new reference is created which points to a now missing object. |
+| `pack.prunePreserved` | `false` | ⃞ | Whether to prune preserved pack files from the previous run of gc from the `objects/pack/preserved` directory. This helps to limit the additional storage space needed to preserve old packs when `pack.preserveOldPacks = true`. |
| `pack.reuseDeltas` | `true` |⃞ | Whether to reuse deltas existing in repository. |
| `pack.reuseObjects` | `true` | ⃞ | Whether to reuse existing objects representation in repository. |
| `pack.searchForReuseTimeout` | | ⃞ | Search for reuse phase timeout. Expressed as a `Duration`, i.e.: `50sec`. |
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
index 177be7066d..c87f0b6dcf 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java
@@ -10,6 +10,7 @@
package org.eclipse.jgit.pgm;
+import org.eclipse.jgit.api.GarbageCollectCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.TextProgressMonitor;
@@ -21,20 +22,25 @@ class Gc extends TextBuiltin {
private boolean aggressive;
@Option(name = "--preserve-oldpacks", usage = "usage_PreserveOldPacks")
- private boolean preserveOldPacks;
+ private Boolean preserveOldPacks;
@Option(name = "--prune-preserved", usage = "usage_PrunePreserved")
- private boolean prunePreserved;
+ private Boolean prunePreserved;
/** {@inheritDoc} */
@Override
protected void run() {
Git git = Git.wrap(db);
try {
- git.gc().setAggressive(aggressive)
- .setPreserveOldPacks(preserveOldPacks)
- .setPrunePreserved(prunePreserved)
- .setProgressMonitor(new TextProgressMonitor(errw)).call();
+ GarbageCollectCommand command = git.gc().setAggressive(aggressive)
+ .setProgressMonitor(new TextProgressMonitor(errw));
+ if (preserveOldPacks != null) {
+ command.setPreserveOldPacks(preserveOldPacks.booleanValue());
+ }
+ if (prunePreserved != null) {
+ command.setPrunePreserved(prunePreserved.booleanValue());
+ }
+ command.call();
} catch (GitAPIException e) {
throw die(e.getMessage(), e);
}
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 107b7d5ea3..b9de762855 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -9,6 +9,18 @@
</filter>
<filter id="1142947843">
<message_arguments>
+ <message_argument value="5.13.2"/>
+ <message_argument value="CONFIG_KEY_PRESERVE_OLD_PACKS"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="5.13.2"/>
+ <message_argument value="CONFIG_KEY_PRUNE_PRESERVED"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
<message_argument value="6.1.1"/>
<message_argument value="CONFIG_KEY_TRUST_PACKED_REFS_STAT"/>
</message_arguments>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 7f8f56bba8..065c20b616 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -35,6 +35,7 @@ import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.security.DigestInputStream;
import java.security.MessageDigest;
@@ -906,7 +907,7 @@ public class RefDirectory extends RefDatabase {
try (InputStream stream = Files
.newInputStream(packedRefsFile.toPath())) {
// open the file to refresh attributes (on some NFS clients)
- } catch (FileNotFoundException e) {
+ } catch (FileNotFoundException | NoSuchFileException e) {
// Ignore as packed-refs may not exist
}
//$FALL-THROUGH$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index 608a4842a4..704395513f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -919,4 +919,18 @@ public final class ConfigConstants {
* @since 6.1.1
*/
public static final String CONFIG_KEY_TRUST_PACKED_REFS_STAT = "trustPackedRefsStat";
+
+ /**
+ * The "pack.preserveOldPacks" key
+ *
+ * @since 5.13.2
+ */
+ public static final String CONFIG_KEY_PRESERVE_OLD_PACKS = "preserveoldpacks";
+
+ /**
+ * The "pack.prunePreserved" key
+ *
+ * @since 5.13.2
+ */
+ public static final String CONFIG_KEY_PRUNE_PRESERVED = "prunepreserved";
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java
index 2d0d4ee700..a0c978f6ea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java
@@ -38,6 +38,8 @@ import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW_MEMORY;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PRESERVE_OLD_PACKS;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PRUNE_PRESERVED;
import java.time.Duration;
import java.util.concurrent.Executor;
@@ -1322,6 +1324,10 @@ public class PackConfig {
setMinBytesForObjSizeIndex(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX,
DEFAULT_MIN_BYTES_FOR_OBJ_SIZE_INDEX));
+ setPreserveOldPacks(rc.getBoolean(CONFIG_PACK_SECTION,
+ CONFIG_KEY_PRESERVE_OLD_PACKS, DEFAULT_PRESERVE_OLD_PACKS));
+ setPrunePreserved(rc.getBoolean(CONFIG_PACK_SECTION,
+ CONFIG_KEY_PRUNE_PRESERVED, DEFAULT_PRUNE_PRESERVED));
}
/** {@inheritDoc} */