diff options
Diffstat (limited to 'org.eclipse.jgit')
27 files changed, 192 insertions, 112 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java index b69bb8f3ee..ca5370e912 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java @@ -71,12 +71,12 @@ class Candidate { /** * Score assigned to the rename to this candidate. * <p> - * Consider the history "A<-B<-C". If the result file S in C was renamed to - * R in B, the rename score for this rename will be held in this field by - * the candidate object for B. By storing the score with B, the application - * can see what the rename score was as it makes the transition from C/S to - * B/R. This may seem backwards since it was C that performed the rename, - * but the application doesn't learn about path R until B. + * Consider the history "A<-B<-C". If the result file S in C was + * renamed to R in B, the rename score for this rename will be held in this + * field by the candidate object for B. By storing the score with B, the + * application can see what the rename score was as it makes the transition + * from C/S to B/R. This may seem backwards since it was C that performed + * the rename, but the application doesn't learn about path R until B. */ int renameScore; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Region.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Region.java index e226dbf3cc..2236eecbfe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Region.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Region.java @@ -27,7 +27,7 @@ class Region { /** First position in the {@link Candidate} that owns this Region. */ int sourceStart; - /** Length of the region, always >= 1. */ + /** Length of the region, always >= 1. */ int length; Region(int rs, int ss, int len) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index ec21954aa2..49da95c9ab 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -29,12 +29,12 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.eclipse.jgit.api.errors.CanceledException; import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.AmbiguousObjectException; import org.eclipse.jgit.errors.BinaryBlobException; -import org.eclipse.jgit.errors.CancelledException; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; @@ -578,7 +578,7 @@ public class DiffFormatter implements AutoCloseable { renameDetector.addAll(files); try { return renameDetector.compute(reader, progressMonitor); - } catch (CancelledException e) { + } catch (CanceledException e) { // TODO: consider propagating once bug 536323 is tackled // (making DiffEntry.scan() and DiffFormatter.scan() and // format() cancellable). diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java index 225921ecc1..c33f53adde 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java @@ -23,9 +23,9 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; +import org.eclipse.jgit.api.errors.CanceledException; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.diff.SimilarityIndex.TableFullException; -import org.eclipse.jgit.errors.CancelledException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.FileMode; @@ -336,6 +336,7 @@ public class RenameDetector { * Detect renames in the current file set. * <p> * This convenience function runs without a progress monitor. + * </p> * * @return an unmodifiable list of {@link org.eclipse.jgit.diff.DiffEntry}s * representing all files that have been changed. @@ -343,7 +344,12 @@ public class RenameDetector { * file contents cannot be read from the repository. */ public List<DiffEntry> compute() throws IOException { - return compute(NullProgressMonitor.INSTANCE); + try { + return compute(NullProgressMonitor.INSTANCE); + } catch (CanceledException e) { + // Won't happen with a NullProgressMonitor + return Collections.emptyList(); + } } /** @@ -355,13 +361,11 @@ public class RenameDetector { * representing all files that have been changed. * @throws java.io.IOException * file contents cannot be read from the repository. - * @throws CancelledException + * @throws CanceledException * if rename detection was cancelled */ - // TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major - // version public List<DiffEntry> compute(ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { if (!done) { try { return compute(objectReader, pm); @@ -383,13 +387,11 @@ public class RenameDetector { * representing all files that have been changed. * @throws java.io.IOException * file contents cannot be read from the repository. - * @throws CancelledException + * @throws CanceledException * if rename detection was cancelled */ - // TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major - // version public List<DiffEntry> compute(ObjectReader reader, ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { final ContentSource cs = ContentSource.create(reader); return compute(new ContentSource.Pair(cs, cs), pm); } @@ -405,13 +407,11 @@ public class RenameDetector { * representing all files that have been changed. * @throws java.io.IOException * file contents cannot be read from the repository. - * @throws CancelledException + * @throws CanceledException * if rename detection was cancelled */ - // TODO(ms): use org.eclipse.jgit.api.errors.CanceledException in next major - // version public List<DiffEntry> compute(ContentSource.Pair reader, ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { if (!done) { done = true; @@ -451,15 +451,15 @@ public class RenameDetector { done = false; } - private void advanceOrCancel(ProgressMonitor pm) throws CancelledException { + private void advanceOrCancel(ProgressMonitor pm) throws CanceledException { if (pm.isCancelled()) { - throw new CancelledException(JGitText.get().renameCancelled); + throw new CanceledException(JGitText.get().renameCancelled); } pm.update(1); } private void breakModifies(ContentSource.Pair reader, ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { ArrayList<DiffEntry> newEntries = new ArrayList<>(entries.size()); pm.beginTask(JGitText.get().renamesBreakingModifies, entries.size()); @@ -486,7 +486,7 @@ public class RenameDetector { entries = newEntries; } - private void rejoinModifies(ProgressMonitor pm) throws CancelledException { + private void rejoinModifies(ProgressMonitor pm) throws CanceledException { HashMap<String, DiffEntry> nameMap = new HashMap<>(); ArrayList<DiffEntry> newAdded = new ArrayList<>(added.size()); @@ -541,7 +541,7 @@ public class RenameDetector { private void findContentRenames(ContentSource.Pair reader, ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { int cnt = Math.max(added.size(), deleted.size()); if (getRenameLimit() == 0 || cnt <= getRenameLimit()) { SimilarityRenameDetector d; @@ -562,7 +562,7 @@ public class RenameDetector { @SuppressWarnings("unchecked") private void findExactRenames(ProgressMonitor pm) - throws CancelledException { + throws CanceledException { pm.beginTask(JGitText.get().renamesFindingExact, // added.size() + added.size() + deleted.size() + added.size() * deleted.size()); @@ -651,7 +651,7 @@ public class RenameDetector { matrix[mNext] = SimilarityRenameDetector.encode(score, delIdx, addIdx); mNext++; if (pm.isCancelled()) { - throw new CancelledException( + throw new CanceledException( JGitText.get().renameCancelled); } } @@ -744,7 +744,7 @@ public class RenameDetector { @SuppressWarnings("unchecked") private HashMap<AbbreviatedObjectId, Object> populateMap( List<DiffEntry> diffEntries, ProgressMonitor pm) - throws CancelledException { + throws CanceledException { HashMap<AbbreviatedObjectId, Object> map = new HashMap<>(); for (DiffEntry de : diffEntries) { Object old = map.put(id(de), de); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java index 5871b4aeea..9ac94895b1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java @@ -20,9 +20,9 @@ import java.util.Arrays; import java.util.BitSet; import java.util.List; +import org.eclipse.jgit.api.errors.CanceledException; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.diff.SimilarityIndex.TableFullException; -import org.eclipse.jgit.errors.CancelledException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.NullProgressMonitor; @@ -115,7 +115,7 @@ class SimilarityRenameDetector { skipBinaryFiles = value; } - void compute(ProgressMonitor pm) throws IOException, CancelledException { + void compute(ProgressMonitor pm) throws IOException, CanceledException { if (pm == null) pm = NullProgressMonitor.INSTANCE; @@ -130,9 +130,7 @@ class SimilarityRenameDetector { // for (--mNext; mNext >= 0; mNext--) { if (pm.isCancelled()) { - // TODO(ms): use org.eclipse.jgit.api.errors.CanceledException - // in next major version - throw new CancelledException(JGitText.get().renameCancelled); + throw new CanceledException(JGitText.get().renameCancelled); } long ent = matrix[mNext]; int sIdx = srcFile(ent); @@ -202,7 +200,7 @@ class SimilarityRenameDetector { } private int buildMatrix(ProgressMonitor pm) - throws IOException, CancelledException { + throws IOException, CanceledException { // Allocate for the worst-case scenario where every pair has a // score that we need to consider. We might not need that many. // @@ -228,10 +226,7 @@ class SimilarityRenameDetector { for (int dstIdx = 0; dstIdx < dsts.size(); dstIdx++) { if (pm.isCancelled()) { - // TODO(ms): use - // org.eclipse.jgit.api.errors.CanceledException in next - // major version - throw new CancelledException( + throw new CanceledException( JGitText.get().renameCancelled); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java index 07162db4ce..e0c1e93918 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java @@ -280,12 +280,12 @@ public class DirCacheTree { * number of bytes of <code>cache[cacheIdx].path</code> that * matches this tree's path. The value at array position * <code>cache[cacheIdx].path[pathOff-1]</code> is always '/' if - * <code>pathOff</code> is > 0. + * <code>pathOff</code> is > 0. * @param ow * the writer to use when serializing to the store. * @return identity of this tree. * @throws UnmergedPathException - * one or more paths contain higher-order stages (stage > 0), + * one or more paths contain higher-order stages (stage > 0), * which cannot be stored in a tree object. * @throws IOException * an unexpected error occurred writing to the object store. @@ -401,7 +401,7 @@ public class DirCacheTree { * number of bytes of <code>cache[cacheIdx].path</code> that * matches this tree's path. The value at array position * <code>cache[cacheIdx].path[pathOff-1]</code> is always '/' if - * <code>pathOff</code> is > 0. + * <code>pathOff</code> is > 0. */ void validate(final DirCacheEntry[] cache, final int cCnt, int cIdx, final int pathOff) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java index 0708123e91..de210b01c4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, Google Inc. and others + * Copyright (C) 2010, 2021 Google Inc. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -7,29 +7,23 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - package org.eclipse.jgit.errors; -import org.eclipse.jgit.internal.storage.pack.ObjectToPack; - /** * A previously selected representation is no longer available. */ -public class StoredObjectRepresentationNotAvailableException extends Exception { //TODO remove unused ObjectToPack in 5.0 +public class StoredObjectRepresentationNotAvailableException extends Exception { + private static final long serialVersionUID = 1L; /** - * Construct an error for an object. + * Creates a new instance. * - * @param otp - * the object whose current representation is no longer present. * @param cause - * cause - * @since 4.10 + * {@link Throwable} that caused this exception + * @since 6.0 */ - public StoredObjectRepresentationNotAvailableException(ObjectToPack otp, - Throwable cause) { + public StoredObjectRepresentationNotAvailableException(Throwable cause) { super(cause); - // Do nothing. } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java index 095927f3cd..e0a822479f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -578,10 +578,10 @@ public class RepoCommand extends GitCommand<RevCommit> { DirCache index = DirCache.newInCore(); ObjectInserter inserter = repo.newObjectInserter(); + try (RevWalk rw = new RevWalk(repo)) { prepareIndex(renamedProjects, index, inserter); ObjectId treeId = index.writeTree(inserter); - long prevDelay = 0; for (int i = 0; i < LOCK_FAILURE_MAX_RETRIES - 1; i++) { try { @@ -597,7 +597,7 @@ public class RepoCommand extends GitCommand<RevCommit> { } // In the last try, just propagate the exceptions return commitTreeOnCurrentTip(inserter, rw, treeId); - } catch (GitAPIException | IOException | InterruptedException e) { + } catch (IOException | InterruptedException e) { throw new ManifestErrorException(e); } } @@ -609,12 +609,11 @@ public class RepoCommand extends GitCommand<RevCommit> { } return git.commit().setMessage(RepoText.get().repoCommitMessage) .call(); - } catch (GitAPIException | IOException e) { + } catch (IOException e) { throw new ManifestErrorException(e); } } - private void prepareIndex(List<RepoProject> projects, DirCache index, ObjectInserter inserter) throws IOException, GitAPIException { Config cfg = new Config(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java index e87bfe24e6..54c527c03c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java @@ -104,9 +104,10 @@ public final class DfsBlockCache { private final ReentrantLock[] loadLocks; /** - * A separate pool of locks to prevent concurrent loads for same index or bitmap from PackFile. + * A separate pool of locks per pack extension to prevent concurrent loads + * for same index or bitmap from PackFile. */ - private final ReentrantLock[] refLocks; + private final ReentrantLock[][] refLocks; /** Maximum number of bytes the cache should hold. */ private final long maxBytes; @@ -173,13 +174,16 @@ public final class DfsBlockCache { } table = new AtomicReferenceArray<>(tableSize); - loadLocks = new ReentrantLock[cfg.getConcurrencyLevel()]; + int concurrencyLevel = cfg.getConcurrencyLevel(); + loadLocks = new ReentrantLock[concurrencyLevel]; for (int i = 0; i < loadLocks.length; i++) { loadLocks[i] = new ReentrantLock(true /* fair */); } - refLocks = new ReentrantLock[cfg.getConcurrencyLevel()]; - for (int i = 0; i < refLocks.length; i++) { - refLocks[i] = new ReentrantLock(true /* fair */); + refLocks = new ReentrantLock[PackExt.values().length][concurrencyLevel]; + for (int i = 0; i < PackExt.values().length; i++) { + for (int j = 0; j < concurrencyLevel; ++j) { + refLocks[i][j] = new ReentrantLock(true /* fair */); + } } maxBytes = cfg.getBlockLimit(); @@ -636,7 +640,8 @@ public final class DfsBlockCache { } private ReentrantLock lockForRef(DfsStreamKey key) { - return refLocks[(key.hash >>> 1) % refLocks.length]; + int slot = (key.hash >>> 1) % refLocks[key.packExtPos].length; + return refLocks[key.packExtPos][slot]; } private static AtomicLong[] newCounters() { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java index b5bf03fcbb..bb76df1d5d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java @@ -415,8 +415,7 @@ public final class DfsPackFile extends BlockBasedFile { try { readFully(src.offset, buf, 0, 20, ctx); } catch (IOException ioError) { - throw new StoredObjectRepresentationNotAvailableException(src, - ioError); + throw new StoredObjectRepresentationNotAvailableException(ioError); } int c = buf[0] & 0xff; final int typeCode = (c >> 4) & 7; @@ -537,12 +536,11 @@ public final class DfsPackFile extends BlockBasedFile { Long.valueOf(src.offset), getFileName()), dataFormat); - throw new StoredObjectRepresentationNotAvailableException(src, + throw new StoredObjectRepresentationNotAvailableException( corruptObject); } catch (IOException ioError) { - throw new StoredObjectRepresentationNotAvailableException(src, - ioError); + throw new StoredObjectRepresentationNotAvailableException(ioError); } if (quickCopy != null) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java index 29d11104d4..d8e191c4e0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java @@ -23,10 +23,10 @@ import java.util.zip.CRC32; import java.util.zip.Deflater; import org.eclipse.jgit.internal.storage.file.PackIndex; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.transport.PackLock; import org.eclipse.jgit.transport.PackParser; import org.eclipse.jgit.transport.PackedObjectInfo; 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 40c075ec5e..93c6201597 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 @@ -1530,7 +1530,8 @@ public class GC { } /** - * @return {@code true} if number of packs > gc.autopacklimit (default 50) + * @return {@code true} if number of packs > gc.autopacklimit (default + * 50) */ boolean tooManyPacks() { int autopacklimit = repo.getConfig().getInt( @@ -1549,7 +1550,8 @@ public class GC { * Quickly estimate number of loose objects, SHA1 is distributed evenly so * counting objects in one directory (bucket 17) is sufficient * - * @return {@code true} if number of loose objects > gc.auto (default 6700) + * @return {@code true} if number of loose objects > gc.auto (default + * 6700) */ boolean tooManyLooseObjects() { int auto = getLooseObjectLimit(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java index dba8ccd99b..1c23ff20c7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java @@ -34,6 +34,7 @@ import org.eclipse.jgit.lib.CoreConfig; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.storage.pack.PackConfig; +import org.eclipse.jgit.transport.PackLock; import org.eclipse.jgit.transport.PackParser; import org.eclipse.jgit.transport.PackedObjectInfo; import org.eclipse.jgit.util.FileUtils; @@ -431,7 +432,7 @@ public class ObjectDirectoryPackParser extends PackParser { File packDir = new File(db.getDirectory(), "pack"); //$NON-NLS-1$ PackFile finalPack = new PackFile(packDir, id, PackExt.PACK); PackFile finalIdx = finalPack.create(PackExt.INDEX); - final PackLock keep = new PackLock(finalPack, db.getFS()); + final PackLockImpl keep = new PackLockImpl(finalPack, db.getFS()); if (!packDir.exists() && !packDir.mkdir() && !packDir.exists()) { // The objects/pack directory isn't present, and we are unable diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java index 5efd4c5bfc..289c732f4e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java @@ -521,12 +521,11 @@ public class Pack implements Iterable<PackIndex.MutableEntry> { Long.valueOf(src.offset), getPackFile()), dataFormat); - throw new StoredObjectRepresentationNotAvailableException(src, + throw new StoredObjectRepresentationNotAvailableException( corruptObject); } catch (IOException ioError) { - throw new StoredObjectRepresentationNotAvailableException(src, - ioError); + throw new StoredObjectRepresentationNotAvailableException(ioError); } if (quickCopy != null) { @@ -611,7 +610,7 @@ public class Pack implements Iterable<PackIndex.MutableEntry> { try { doOpen(); } catch (IOException thisPackNotValid) { - throw new StoredObjectRepresentationNotAvailableException(otp, + throw new StoredObjectRepresentationNotAvailableException( thisPackNotValid); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackLock.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackLockImpl.java index 482b143e33..7cc5f50549 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackLock.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackLockImpl.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.transport.PackLock; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; @@ -21,7 +22,7 @@ import org.eclipse.jgit.util.FileUtils; * Keeps track of a {@link org.eclipse.jgit.internal.storage.file.Pack}'s * associated <code>.keep</code> file. */ -public class PackLock { +public class PackLockImpl implements PackLock { private final File keepFile; /** @@ -32,7 +33,7 @@ public class PackLock { * @param fs * the filesystem abstraction used by the repository. */ - public PackLock(File packFile, FS fs) { + public PackLockImpl(File packFile, FS fs) { final File p = packFile.getParentFile(); final String n = packFile.getName(); keepFile = new File(p, n.substring(0, n.length() - 5) + ".keep"); //$NON-NLS-1$ @@ -59,12 +60,7 @@ public class PackLock { return lf.commit(); } - /** - * Remove the <code>.keep</code> file that holds this pack in place. - * - * @throws java.io.IOException - * if deletion of .keep file failed - */ + @Override public void unlock() throws IOException { FileUtils.delete(keepFile); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/ssh/OpenSshConfigFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/ssh/OpenSshConfigFile.java index 2dbb7859b9..648d4a1821 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/ssh/OpenSshConfigFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/ssh/OpenSshConfigFile.java @@ -142,7 +142,7 @@ public class OpenSshConfigFile implements SshConfigStore { * real host name, or it may just be a "Host" block in the * configuration file. * @param port - * the user supplied; <= 0 if none + * the user supplied; <= 0 if none * @param userName * the user supplied, may be {@code null} or empty if none given * @return the configuration for the requested name. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java index e4e7cd6e03..22e1f98181 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java @@ -18,6 +18,8 @@ import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.text.MessageFormat; + +import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.internal.JGitText; @@ -77,6 +79,9 @@ public class CommitConfig { * {@code commit.template}. If no {@code i18n.commitEncoding} is specified, * UTF-8 fallback is used. * + * @param repository + * to resolve relative path in local git repo config + * * @return content of the commit template or {@code null} if not present. * @throws IOException * if the template file can not be read @@ -84,9 +89,10 @@ public class CommitConfig { * if the template file does not exists * @throws ConfigInvalidException * if a {@code commitEncoding} is specified and is invalid + * @since 6.0 */ @Nullable - public String getCommitTemplateContent() + public String getCommitTemplateContent(@NonNull Repository repository) throws FileNotFoundException, IOException, ConfigInvalidException { if (commitTemplatePath == null) { @@ -94,11 +100,17 @@ public class CommitConfig { } File commitTemplateFile; + FS fileSystem = repository.getFS(); if (commitTemplatePath.startsWith("~/")) { //$NON-NLS-1$ - commitTemplateFile = FS.DETECTED.resolve(FS.DETECTED.userHome(), + commitTemplateFile = fileSystem.resolve(fileSystem.userHome(), commitTemplatePath.substring(2)); } else { - commitTemplateFile = FS.DETECTED.resolve(null, commitTemplatePath); + commitTemplateFile = fileSystem.resolve(null, commitTemplatePath); + } + if (!commitTemplateFile.isAbsolute()) { + commitTemplateFile = fileSystem.resolve( + repository.getWorkTree().getAbsoluteFile(), + commitTemplatePath); } Charset commitMessageEncoding = getEncoding(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java index d344deac26..f48e1e68cc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java @@ -28,7 +28,6 @@ import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.errors.RemoteRepositoryException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.MutableObjectId; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java index 47d156b667..f04e573feb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java @@ -35,7 +35,6 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchConnection.java index d06ef65c76..9dc0620665 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchConnection.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.Set; import org.eclipse.jgit.errors.TransportException; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java index 34bad6e029..7d7b3ee0a0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java @@ -37,7 +37,6 @@ import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.file.LockFile; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.lib.BatchRefUpdate; import org.eclipse.jgit.lib.BatchingProgressMonitor; import org.eclipse.jgit.lib.Constants; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackLock.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackLock.java new file mode 100644 index 0000000000..bf2140759f --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackLock.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.transport; + +import java.io.IOException; + +/** + * A {@code PackLock} describes a {@code .keep} file that holds a pack in place. + * If {@link PackParser#parse(org.eclipse.jgit.lib.ProgressMonitor)} creates + * such a pack lock, it returns the lock so that it can be unlocked once the + * pack doesn't need a {@code .keep} file anymore. + * + * @since 6.0 + */ +public interface PackLock { + + /** + * Remove the {@code .keep} file that holds a pack in place. + * + * @throws java.io.IOException + * if deletion of the {@code .keep} file failed + */ + void unlock() throws IOException; +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java index 715cbb48fb..e43ea0261e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -29,7 +29,6 @@ import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.TooLargeObjectInPackException; import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.internal.storage.pack.BinaryDelta; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BatchingProgressMonitor; @@ -490,7 +489,7 @@ public abstract class PackParser { * {@link #setLockMessage(String)}. * @throws java.io.IOException * the stream is malformed, or contains corrupt objects. - * @since 3.0 + * @since 6.0 */ public final PackLock parse(ProgressMonitor progress) throws IOException { return parse(progress, progress); @@ -509,7 +508,7 @@ public abstract class PackParser { * {@link #setLockMessage(String)}. * @throws java.io.IOException * the stream is malformed, or contains corrupt objects. - * @since 3.0 + * @since 6.0 */ public PackLock parse(ProgressMonitor receiving, ProgressMonitor resolving) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index 58f8895e00..871ba50a6c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -48,7 +48,6 @@ import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.errors.TooLargePackException; import org.eclipse.jgit.errors.UnpackException; import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.internal.submodule.SubmoduleValidator; import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException; import org.eclipse.jgit.internal.transport.connectivity.FullConnectivityChecker; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigStore.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigStore.java index d98bd2307f..1226a6b5ea 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigStore.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigStore.java @@ -28,7 +28,7 @@ public interface SshConfigStore { * @param hostName * to look up * @param port - * the user supplied; <= 0 if none + * the user supplied; <= 0 if none * @param userName * the user supplied, may be {@code null} or empty if none given * @return the configuration for the requested name. @@ -68,7 +68,7 @@ public interface SshConfigStore { * @param hostName * host name to look up * @param port - * port number; <= 0 if none + * port number; <= 0 if none * @param userName * the user name, may be {@code null} or empty if none given * @return the configuration for the requested name. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java index a6b20451dd..d67fe074e4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java @@ -32,7 +32,6 @@ import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.file.ObjectDirectory; import org.eclipse.jgit.internal.storage.file.PackIndex; -import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.internal.storage.file.UnpackedObject; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index dd656e5f2b..d0007ec219 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -59,6 +59,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; @@ -94,6 +96,9 @@ public abstract class FS { */ protected static final Entry[] NO_ENTRIES = {}; + private static final Pattern VERSION = Pattern + .compile("\\s(\\d+)\\.(\\d+)\\.(\\d+)"); //$NON-NLS-1$ + private volatile Boolean supportSymlinks; /** @@ -1516,26 +1521,76 @@ public abstract class FS { return null; } - // Trick Git into printing the path to the config file by using "echo" - // as the editor. - Map<String, String> env = new HashMap<>(); - env.put("GIT_EDITOR", "echo"); //$NON-NLS-1$ //$NON-NLS-2$ + if (parseVersion(v) < makeVersion(2, 8, 0)) { + // --show-origin was introduced in git 2.8.0. For older git: trick + // it into printing the path to the config file by using "echo" as + // the editor. + Map<String, String> env = new HashMap<>(); + env.put("GIT_EDITOR", "echo"); //$NON-NLS-1$ //$NON-NLS-2$ + + String w; + try { + w = readPipe(gitExe.getParentFile(), + new String[] { gitExe.getPath(), "config", "--system", //$NON-NLS-1$ //$NON-NLS-2$ + "--edit" }, //$NON-NLS-1$ + SystemReader.getInstance().getDefaultCharset().name(), + env); + } catch (CommandFailedException e) { + LOG.warn(e.getMessage()); + return null; + } + if (StringUtils.isEmptyOrNull(w)) { + return null; + } + return new File(w); + } String w; try { w = readPipe(gitExe.getParentFile(), new String[] { gitExe.getPath(), "config", "--system", //$NON-NLS-1$ //$NON-NLS-2$ - "--edit" }, //$NON-NLS-1$ - SystemReader.getInstance().getDefaultCharset().name(), env); + "--show-origin", "--list", "-z" }, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + SystemReader.getInstance().getDefaultCharset().name()); } catch (CommandFailedException e) { LOG.warn(e.getMessage()); return null; } - if (StringUtils.isEmptyOrNull(w)) { + if (w == null) { return null; } + // We get NUL-terminated items; the first one will be a file name, + // prefixed by "file:". (Using -z is crucial, otherwise git quotes file + // names with special characters.) + int nul = w.indexOf(0); + if (nul <= 0) { + return null; + } + w = w.substring(0, nul); + int colon = w.indexOf(':'); + if (colon < 0) { + return null; + } + w = w.substring(colon + 1); + return w.isEmpty() ? null : new File(w); + } + + private long parseVersion(String version) { + Matcher m = VERSION.matcher(version); + if (m.find()) { + try { + return makeVersion( + Integer.parseInt(m.group(1)), + Integer.parseInt(m.group(2)), + Integer.parseInt(m.group(3))); + } catch (NumberFormatException e) { + // Ignore + } + } + return -1; + } - return new File(w); + private long makeVersion(int major, int minor, int patch) { + return ((major * 10_000L) + minor) * 10_000L + patch; } /** |