aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java97
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/AddNoteCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommitMessageProvider.java72
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickResult.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java33
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java220
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java59
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java48
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java32
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListNotesCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PackRefsCommand.java87
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java109
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java41
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RemoveNoteCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java31
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RmCommand.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ShowNoteCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java48
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashListCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java92
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CheckoutConflictException.java5
57 files changed, 956 insertions, 478 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index cb32324043..b4d1cab513 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
- * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com> and others
+ * Copyright (C) 2010, 2025 Stefan Lay <stefan.lay@sap.com> 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
@@ -17,9 +17,10 @@ import static org.eclipse.jgit.lib.FileMode.TYPE_TREE;
import java.io.IOException;
import java.io.InputStream;
+import java.text.MessageFormat;
import java.time.Instant;
-import java.util.Collection;
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.List;
import org.eclipse.jgit.api.errors.FilterFailedException;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -55,12 +56,19 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter;
*/
public class AddCommand extends GitCommand<DirCache> {
- private Collection<String> filepatterns;
+ private List<String> filepatterns;
private WorkingTreeIterator workingTreeIterator;
+ // Update only known index entries, don't add new ones. If there's no file
+ // for an index entry, remove it: stage deletions.
private boolean update = false;
+ // If TRUE, also stage deletions, otherwise only update and add index
+ // entries.
+ // If not set explicitly
+ private Boolean all;
+
// This defaults to true because it's what JGit has been doing
// traditionally. The C git default would be false.
private boolean renormalize = true;
@@ -73,7 +81,7 @@ public class AddCommand extends GitCommand<DirCache> {
*/
public AddCommand(Repository repo) {
super(repo);
- filepatterns = new LinkedList<>();
+ filepatterns = new ArrayList<>();
}
/**
@@ -82,6 +90,17 @@ public class AddCommand extends GitCommand<DirCache> {
* A directory name (e.g. <code>dir</code> to add <code>dir/file1</code> and
* <code>dir/file2</code>) can also be given to add all files in the
* directory, recursively. Fileglobs (e.g. *.c) are not yet supported.
+ * </p>
+ * <p>
+ * If a pattern {@code "."} is added, all changes in the git repository's
+ * working tree will be added.
+ * </p>
+ * <p>
+ * File patterns are required unless {@code isUpdate() == true} or
+ * {@link #setAll(boolean)} is called. If so and no file patterns are given,
+ * all changes will be added (i.e., a file pattern of {@code "."} is
+ * implied).
+ * </p>
*
* @param filepattern
* repository-relative path of file/directory to add (with
@@ -113,15 +132,41 @@ public class AddCommand extends GitCommand<DirCache> {
* Executes the {@code Add} command. Each instance of this class should only
* be used for one invocation of the command. Don't call this method twice
* on an instance.
+ * </p>
+ *
+ * @throws JGitInternalException
+ * on errors, but also if {@code isUpdate() == true} _and_
+ * {@link #setAll(boolean)} had been called
+ * @throws NoFilepatternException
+ * if no file patterns are given if {@code isUpdate() == false}
+ * and {@link #setAll(boolean)} was not called
*/
@Override
public DirCache call() throws GitAPIException, NoFilepatternException {
-
- if (filepatterns.isEmpty())
- throw new NoFilepatternException(JGitText.get().atLeastOnePatternIsRequired);
checkCallable();
+
+ if (update && all != null) {
+ throw new JGitInternalException(MessageFormat.format(
+ JGitText.get().illegalCombinationOfArguments,
+ "--update", "--all/--no-all")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ boolean addAll;
+ if (filepatterns.isEmpty()) {
+ if (update || all != null) {
+ addAll = true;
+ } else {
+ throw new NoFilepatternException(
+ JGitText.get().atLeastOnePatternIsRequired);
+ }
+ } else {
+ addAll = filepatterns.contains("."); //$NON-NLS-1$
+ if (all == null && !update) {
+ all = Boolean.TRUE;
+ }
+ }
+ boolean stageDeletions = update || (all != null && all.booleanValue());
+
DirCache dc = null;
- boolean addAll = filepatterns.contains("."); //$NON-NLS-1$
try (ObjectInserter inserter = repo.newObjectInserter();
NameConflictTreeWalk tw = new NameConflictTreeWalk(repo)) {
@@ -181,7 +226,8 @@ public class AddCommand extends GitCommand<DirCache> {
if (f == null) { // working tree file does not exist
if (entry != null
- && (!update || GITLINK == entry.getFileMode())) {
+ && (!stageDeletions
+ || GITLINK == entry.getFileMode())) {
builder.add(entry);
}
continue;
@@ -252,7 +298,8 @@ public class AddCommand extends GitCommand<DirCache> {
}
/**
- * Set whether to only match against already tracked files
+ * Set whether to only match against already tracked files. If
+ * {@code update == true}, re-sets a previous {@link #setAll(boolean)}.
*
* @param update
* If set to true, the command only matches {@code filepattern}
@@ -314,4 +361,32 @@ public class AddCommand extends GitCommand<DirCache> {
public boolean isRenormalize() {
return renormalize;
}
+
+ /**
+ * Defines whether the command will use '--all' mode: update existing index
+ * entries, add new entries, and remove index entries for which there is no
+ * file. (In other words: also stage deletions.)
+ * <p>
+ * The setting is independent of {@link #setUpdate(boolean)}.
+ * </p>
+ *
+ * @param all
+ * whether to enable '--all' mode
+ * @return {@code this}
+ * @since 7.2
+ */
+ public AddCommand setAll(boolean all) {
+ this.all = Boolean.valueOf(all);
+ return this;
+ }
+
+ /**
+ * Tells whether '--all' has been set for this command.
+ *
+ * @return {@code true} if it was set; {@code false} otherwise
+ * @since 7.2
+ */
+ public boolean isAll() {
+ return all != null && all.booleanValue();
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddNoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddNoteCommand.java
index ceb17fbe25..8805ea2353 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddNoteCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddNoteCommand.java
@@ -51,7 +51,6 @@ public class AddNoteCommand extends GitCommand<Note> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Note call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
index e612924771..df0f616256 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -37,11 +37,12 @@ public class ApplyCommand extends GitCommand<ApplyResult> {
/**
* Constructs the command.
*
- * @param local
+ * @param repo
+ * the repository this command will be used on
*/
- ApplyCommand(Repository local) {
- super(local);
- if (local == null) {
+ ApplyCommand(Repository repo) {
+ super(repo);
+ if (repo == null) {
throw new NullPointerException(JGitText.get().repositoryIsRequired);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
index fdf8b80cd4..81b3611774 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
@@ -177,6 +177,8 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
}
/**
+ * Get the problematic format name
+ *
* @return the problematic format name
*/
public String getFormat() {
@@ -389,7 +391,6 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
}
}
- /** {@inheritDoc} */
@Override
public OutputStream call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index 7319ff4b2f..32c242f271 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
- * Copyright (C) 2011, 2020 Matthias Sohn <matthias.sohn@sap.com> and others
+ * Copyright (C) 2011, 2023 Matthias Sohn <matthias.sohn@sap.com> 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
@@ -17,7 +17,6 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -28,6 +27,7 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
+import org.eclipse.jgit.dircache.Checkout;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
@@ -55,7 +55,6 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
/**
@@ -164,10 +163,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
*/
protected CheckoutCommand(Repository repo) {
super(repo);
- this.paths = new LinkedList<>();
+ this.paths = new ArrayList<>();
}
- /** {@inheritDoc} */
@Override
public Ref call() throws GitAPIException, RefAlreadyExistsException,
RefNotFoundException, InvalidRefNameException,
@@ -326,6 +324,8 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
/**
+ * Set progress monitor
+ *
* @param monitor
* a progress monitor
* @return this instance
@@ -407,13 +407,14 @@ public class CheckoutCommand extends GitCommand<Ref> {
*
* @return this instance
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.api.errors.RefNotFoundException
+ * if {@code Ref} couldn't be resolved
*/
protected CheckoutCommand checkoutPaths() throws IOException,
RefNotFoundException {
actuallyModifiedPaths = new HashSet<>();
- WorkingTreeOptions options = repo.getConfig()
- .get(WorkingTreeOptions.KEY);
+ Checkout checkout = new Checkout(repo).setRecursiveDeletion(true);
DirCache dc = repo.lockDirCache();
try (RevWalk revWalk = new RevWalk(repo);
TreeWalk treeWalk = new TreeWalk(repo,
@@ -422,10 +423,10 @@ public class CheckoutCommand extends GitCommand<Ref> {
if (!checkoutAllPaths)
treeWalk.setFilter(PathFilterGroup.createFromStrings(paths));
if (isCheckoutIndex())
- checkoutPathsFromIndex(treeWalk, dc, options);
+ checkoutPathsFromIndex(treeWalk, dc, checkout);
else {
RevCommit commit = revWalk.parseCommit(getStartPointObjectId());
- checkoutPathsFromCommit(treeWalk, dc, commit, options);
+ checkoutPathsFromCommit(treeWalk, dc, commit, checkout);
}
} finally {
try {
@@ -443,7 +444,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
private void checkoutPathsFromIndex(TreeWalk treeWalk, DirCache dc,
- WorkingTreeOptions options)
+ Checkout checkout)
throws IOException {
DirCacheIterator dci = new DirCacheIterator(dc);
treeWalk.addTree(dci);
@@ -469,7 +470,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
if (stage > DirCacheEntry.STAGE_0) {
if (checkoutStage != null) {
if (stage == checkoutStage.number) {
- checkoutPath(ent, r, options,
+ checkoutPath(ent, r, checkout, path,
new CheckoutMetadata(eolStreamType,
filterCommand));
actuallyModifiedPaths.add(path);
@@ -480,7 +481,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
throw new JGitInternalException(e.getMessage(), e);
}
} else {
- checkoutPath(ent, r, options,
+ checkoutPath(ent, r, checkout, path,
new CheckoutMetadata(eolStreamType,
filterCommand));
actuallyModifiedPaths.add(path);
@@ -494,7 +495,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
private void checkoutPathsFromCommit(TreeWalk treeWalk, DirCache dc,
- RevCommit commit, WorkingTreeOptions options) throws IOException {
+ RevCommit commit, Checkout checkout) throws IOException {
treeWalk.addTree(commit.getTree());
final ObjectReader r = treeWalk.getObjectReader();
DirCacheEditor editor = dc.editor();
@@ -516,7 +517,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
ent.setObjectId(blobId);
ent.setFileMode(mode);
- checkoutPath(ent, r, options,
+ checkoutPath(ent, r, checkout, path,
new CheckoutMetadata(eolStreamType, filterCommand));
actuallyModifiedPaths.add(path);
}
@@ -526,10 +527,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
private void checkoutPath(DirCacheEntry entry, ObjectReader reader,
- WorkingTreeOptions options, CheckoutMetadata checkoutMetadata) {
+ Checkout checkout, String path, CheckoutMetadata checkoutMetadata) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader, true,
- checkoutMetadata, options);
+ checkout.checkout(entry, checkoutMetadata, reader, path);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,
@@ -644,24 +644,6 @@ public class CheckoutCommand extends GitCommand<Ref> {
/**
* Specify to force the ref update in case of a branch switch.
*
- * @param force
- * if <code>true</code> and the branch with the given name
- * already exists, the start-point of an existing branch will be
- * set to a new start-point; if false, the existing branch will
- * not be changed
- * @return this instance
- * @deprecated this method was badly named comparing its semantics to native
- * git's checkout --force option, use
- * {@link #setForceRefUpdate(boolean)} instead
- */
- @Deprecated
- public CheckoutCommand setForce(boolean force) {
- return setForceRefUpdate(force);
- }
-
- /**
- * Specify to force the ref update in case of a branch switch.
- *
* In releases prior to 5.2 this method was called setForce() but this name
* was misunderstood to implement native git's --force option, which is not
* true.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
index 5f8c2b728a..a353d1a135 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
@@ -9,11 +9,12 @@
*/
package org.eclipse.jgit.api;
+import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
import java.io.IOException;
import java.text.MessageFormat;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -62,10 +63,12 @@ import org.eclipse.jgit.treewalk.FileTreeIterator;
public class CherryPickCommand extends GitCommand<CherryPickResult> {
private String reflogPrefix = "cherry-pick:"; //$NON-NLS-1$
- private List<Ref> commits = new LinkedList<>();
+ private List<Ref> commits = new ArrayList<>();
private String ourCommitName = null;
+ private CherryPickCommitMessageProvider messageProvider = ORIGINAL;
+
private MergeStrategy strategy = MergeStrategy.RECURSIVE;
private ContentMergeStrategy contentStrategy;
@@ -99,7 +102,7 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
UnmergedPathsException, ConcurrentRefUpdateException,
WrongRepositoryStateException, NoHeadException {
RevCommit newHead = null;
- List<Ref> cherryPickedRefs = new LinkedList<>();
+ List<Ref> cherryPickedRefs = new ArrayList<>();
checkCallable();
try (RevWalk revWalk = new RevWalk(repo)) {
@@ -168,8 +171,10 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
dco.checkout();
if (!noCommit) {
try (Git git = new Git(getRepository())) {
+ String commitMessage = messageProvider
+ .getCherryPickedCommitMessage(srcCommit);
newHead = git.commit()
- .setMessage(srcCommit.getFullMessage())
+ .setMessage(commitMessage)
.setReflogComment(reflogPrefix + " " //$NON-NLS-1$
+ srcCommit.getShortMessage())
.setAuthor(srcCommit.getAuthorIdent())
@@ -297,6 +302,22 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
}
/**
+ * Set a message provider for a target cherry-picked commit<br>
+ * By default original commit message is used (see
+ * {@link CherryPickCommitMessageProvider#ORIGINAL})
+ *
+ * @param messageProvider
+ * the commit message provider
+ * @return {@code this}
+ * @since 6.9
+ */
+ public CherryPickCommand setCherryPickCommitMessageProvider(
+ CherryPickCommitMessageProvider messageProvider) {
+ this.messageProvider = messageProvider;
+ return this;
+ }
+
+ /**
* Set the prefix to use in the reflog.
* <p>
* This is primarily needed for implementing rebase in terms of
@@ -399,7 +420,6 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
return headName;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommitMessageProvider.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommitMessageProvider.java
new file mode 100644
index 0000000000..50d65b6fa8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommitMessageProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023 Dmitrii Naumenko <dmitrii.naumenko@jetbrains.com>
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is aailable at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.api;
+
+import java.util.List;
+
+import org.eclipse.jgit.revwalk.FooterLine;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * The interface is used to construct a cherry-picked commit message based on
+ * the original commit
+ *
+ * @see #ORIGINAL
+ * @see #ORIGINAL_WITH_REFERENCE
+ * @since 6.9
+ */
+public interface CherryPickCommitMessageProvider {
+
+ /**
+ * This provider returns the original commit message
+ */
+ static final CherryPickCommitMessageProvider ORIGINAL = RevCommit::getFullMessage;
+
+ /**
+ * This provider returns the original commit message with original commit
+ * hash in SHA-1 form.<br>
+ * Example:
+ *
+ * <pre>
+ * <code>my original commit message
+ *
+ * (cherry picked from commit 75355897dc28e9975afed028c1a6d8c6b97b2a3c)</code>
+ * </pre>
+ *
+ * This is similar to <code>-x</code> flag in git-scm (see <a href=
+ * "https://git-scm.com/docs/git-cherry-pick#_options">https://git-scm.com/docs/git-cherry-pick#_options</a>)
+ */
+ static final CherryPickCommitMessageProvider ORIGINAL_WITH_REFERENCE = srcCommit -> {
+ String fullMessage = srcCommit.getFullMessage();
+
+ // Don't add extra new line after footer (aka trailer)
+ // https://stackoverflow.com/questions/70007405/git-log-exclude-cherry-pick-messages-for-trailers
+ // https://lore.kernel.org/git/7vmx136cdc.fsf@alter.siamese.dyndns.org
+ String separator = messageEndsWithFooter(srcCommit) ? "\n" : "\n\n"; //$NON-NLS-1$//$NON-NLS-2$
+ String revisionString = srcCommit.getName();
+ return String.format("%s%s(cherry picked from commit %s)", //$NON-NLS-1$
+ fullMessage, separator, revisionString);
+ };
+
+ /**
+ * @param srcCommit
+ * original cherry-picked commit
+ * @return target cherry-picked commit message
+ */
+ String getCherryPickedCommitMessage(RevCommit srcCommit);
+
+ private static boolean messageEndsWithFooter(RevCommit srcCommit) {
+ byte[] rawBuffer = srcCommit.getRawBuffer();
+ List<FooterLine> footers = srcCommit.getFooterLines();
+ int maxFooterEnd = footers.stream().mapToInt(FooterLine::getEndOffset)
+ .max().orElse(-1);
+ return rawBuffer.length == maxFooterEnd;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickResult.java
index 55d86b7402..995f890389 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickResult.java
@@ -25,21 +25,21 @@ public class CherryPickResult {
* The cherry-pick status
*/
public enum CherryPickStatus {
- /** */
+ /** Cherry-pick succeeded */
OK {
@Override
public String toString() {
return "Ok"; //$NON-NLS-1$
}
},
- /** */
+ /** Cherry-pick failed */
FAILED {
@Override
public String toString() {
return "Failed"; //$NON-NLS-1$
}
},
- /** */
+ /** Cherry-pick found conflicts to be resolved */
CONFLICTING {
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
index 36ca97d694..a4a0c49f45 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java
@@ -113,24 +113,25 @@ public class CleanCommand extends GitCommand<Set<String>> {
}
/**
- * When dryRun is false, deletes the specified path from disk. If dryRun
- * is true, no paths are actually deleted. In both cases, the paths that
- * would have been deleted are added to inFiles and returned.
+ * When dryRun is false, deletes the specified path from disk. If dryRun is
+ * true, no paths are actually deleted. In both cases, the paths that would
+ * have been deleted are added to inFiles and returned.
*
* Paths that are directories are recursively deleted when
- * {@link #directories} is true.
- * Paths that are git repositories are recursively deleted when
- * {@link #directories} and {@link #force} are both true.
+ * {@link #directories} is true. Paths that are git repositories are
+ * recursively deleted when {@link #directories} and {@link #force} are both
+ * true.
*
* @param path
- * The path to be cleaned
+ * The path to be cleaned
* @param inFiles
- * A set of strings representing the files that have been cleaned
- * already, the path to be cleaned will be added to this set
- * before being returned.
+ * A set of strings representing the files that have been cleaned
+ * already, the path to be cleaned will be added to this set
+ * before being returned.
*
* @return a set of strings with the cleaned path added to it
* @throws IOException
+ * if an IO error occurred
*/
private Set<String> cleanPath(String path, Set<String> inFiles)
throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
index 107b00e274..4a536b9534 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
@@ -29,6 +29,7 @@ import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
import org.eclipse.jgit.lib.ConfigConstants;
@@ -66,6 +67,8 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
private boolean bare;
+ private boolean relativePaths;
+
private FS fs;
private String remote = Constants.DEFAULT_REMOTE_NAME;
@@ -100,6 +103,8 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
private List<String> shallowExcludes = new ArrayList<>();
+ private ShutdownHook.Listener shutdownListener = this::cleanup;
+
private enum FETCH_TYPE {
MULTIPLE_BRANCHES, ALL_BRANCHES, MIRROR
}
@@ -181,12 +186,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
@SuppressWarnings("resource") // Closed by caller
Repository repository = init();
FetchResult fetchResult = null;
- Thread cleanupHook = new Thread(() -> cleanup());
- try {
- Runtime.getRuntime().addShutdownHook(cleanupHook);
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
+ ShutdownHook.INSTANCE.register(shutdownListener);
try {
fetchResult = fetch(repository, u);
} catch (IOException ioe) {
@@ -210,11 +210,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
cleanup();
throw e;
} finally {
- try {
- Runtime.getRuntime().removeShutdownHook(cleanupHook);
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
+ ShutdownHook.INSTANCE.unregister(shutdownListener);
}
try {
checkout(repository, fetchResult);
@@ -270,6 +266,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
private Repository init() throws GitAPIException {
InitCommand command = Git.init();
command.setBare(bare);
+ command.setRelativeDirs(relativePaths);
if (fs != null) {
command.setFs(fs);
}
@@ -561,6 +558,20 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
}
/**
+ * Set whether the cloned repository shall use relative paths for GIT_DIR
+ * and GIT_WORK_TREE
+ *
+ * @param relativePaths
+ * if true, use relative paths for GIT_DIR and GIT_WORK_TREE
+ * @return this instance
+ * @since 7.2
+ */
+ public CloneCommand setRelativePaths(boolean relativePaths) {
+ this.relativePaths = relativePaths;
+ return this;
+ }
+
+ /**
* Set the file system abstraction to be used for repositories created by
* this command.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index 3b3baf5a12..a7d409c3f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -16,7 +16,6 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import org.eclipse.jgit.annotations.NonNull;
@@ -52,9 +51,6 @@ import org.eclipse.jgit.lib.CommitConfig.CleanupMode;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
-import org.eclipse.jgit.lib.GpgObjectSigner;
-import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
@@ -63,6 +59,8 @@ import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.Signers;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
@@ -109,7 +107,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
* parents this commit should have. The current HEAD will be in this list
* and also all commits mentioned in .git/MERGE_HEAD
*/
- private List<ObjectId> parents = new LinkedList<>();
+ private List<ObjectId> parents = new ArrayList<>();
private String reflogComment;
@@ -130,7 +128,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
private String signingKey;
- private GpgSigner gpgSigner;
+ private Signer signer;
private GpgConfig gpgConfig;
@@ -320,30 +318,22 @@ public class CommitCommand extends GitCommand<RevCommit> {
}
}
- private void sign(CommitBuilder commit) throws ServiceUnavailableException,
- CanceledException, UnsupportedSigningFormatException {
- if (gpgSigner == null) {
- gpgSigner = GpgSigner.getDefault();
- if (gpgSigner == null) {
- throw new ServiceUnavailableException(
- JGitText.get().signingServiceUnavailable);
+ private void sign(CommitBuilder commit)
+ throws CanceledException, IOException,
+ UnsupportedSigningFormatException {
+ if (signer == null) {
+ signer = Signers.get(gpgConfig.getKeyFormat());
+ if (signer == null) {
+ throw new UnsupportedSigningFormatException(MessageFormat
+ .format(JGitText.get().signatureTypeUnknown,
+ gpgConfig.getKeyFormat().toConfigValue()));
}
}
if (signingKey == null) {
signingKey = gpgConfig.getSigningKey();
}
- if (gpgSigner instanceof GpgObjectSigner) {
- ((GpgObjectSigner) gpgSigner).signObject(commit,
- signingKey, committer, credentialsProvider,
- gpgConfig);
- } else {
- if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
- throw new UnsupportedSigningFormatException(JGitText
- .get().onlyOpenPgpSupportedForSigning);
- }
- gpgSigner.sign(commit, signingKey, committer,
- credentialsProvider);
- }
+ signer.signObject(repo, gpgConfig, commit, committer, signingKey,
+ credentialsProvider);
}
private void updateRef(RepositoryState state, ObjectId headId,
@@ -614,7 +604,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
// specified the commit should not be empty. This behaviour differs
// from native git but can only be adapted in the next release.
// TODO(ch) align the defaults with native git
- allowEmpty = (only.isEmpty()) ? Boolean.TRUE : Boolean.FALSE;
+ allowEmpty = only.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
// when doing a merge commit parse MERGE_HEAD and MERGE_MSG files
if (state == RepositoryState.MERGING_RESOLVED
@@ -1098,22 +1088,22 @@ public class CommitCommand extends GitCommand<RevCommit> {
}
/**
- * Sets the {@link GpgSigner} to use if the commit is to be signed.
+ * Sets the {@link Signer} to use if the commit is to be signed.
*
* @param signer
* to use; if {@code null}, the default signer will be used
* @return {@code this}
- * @since 5.11
+ * @since 7.0
*/
- public CommitCommand setGpgSigner(GpgSigner signer) {
+ public CommitCommand setSigner(Signer signer) {
checkCallable();
- this.gpgSigner = signer;
+ this.signer = signer;
return this;
}
/**
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
- * the discretion of the {@link #setGpgSigner(GpgSigner)}.
+ * the discretion of the {@link #setSigner(Signer)}.
*
* @param config
* to set; if {@code null}, the config will be loaded from the
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java
index 9e77dd7348..013e0ff131 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java
@@ -82,16 +82,13 @@ public class CreateBranchCommand extends GitCommand<Ref> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Ref call() throws GitAPIException, RefAlreadyExistsException,
RefNotFoundException, InvalidRefNameException {
checkCallable();
processOptions();
try (RevWalk revWalk = new RevWalk(repo)) {
- Ref refToCheck = repo.findRef(name);
- boolean exists = refToCheck != null
- && refToCheck.getName().startsWith(R_HEADS);
+ boolean exists = repo.findRef(R_HEADS + name) != null;
if (!force && exists)
throw new RefAlreadyExistsException(MessageFormat.format(
JGitText.get().refAlreadyExists1, name));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
index 3d3ee63568..a5c535f772 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
- * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com> and others
+ * Copyright (C) 2010, 2023 Chris Aniszczyk <caniszczyk@gmail.com> 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
@@ -14,6 +14,7 @@ import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -25,6 +26,8 @@ import org.eclipse.jgit.api.errors.NotMergedException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
@@ -47,8 +50,11 @@ import org.eclipse.jgit.revwalk.RevWalk;
* >Git documentation about Branch</a>
*/
public class DeleteBranchCommand extends GitCommand<List<String>> {
+
private final Set<String> branchNames = new HashSet<>();
+ private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
+
private boolean force;
/**
@@ -61,14 +67,34 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public List<String> call() throws GitAPIException,
NotMergedException, CannotDeleteCurrentBranchException {
checkCallable();
List<String> result = new ArrayList<>();
- if (branchNames.isEmpty())
+ Set<String> shortNames = new HashSet<>();
+ if (branchNames.isEmpty()) {
return result;
+ }
+ Exception error = null;
+ try {
+ deleteBranches(result, shortNames);
+ } catch (Exception e) {
+ error = e;
+ }
+ monitor.beginTask(JGitText.get().updatingConfig, 1);
+ try {
+ updateConfig(shortNames, error);
+ } finally {
+ monitor.update(1);
+ monitor.endTask();
+ }
+ return result;
+ }
+
+ private void deleteBranches(List<String> result,
+ Set<String> shortNames) throws GitAPIException, NotMergedException,
+ CannotDeleteCurrentBranchException {
try {
String currentBranch = repo.getFullBranch();
if (!force) {
@@ -78,12 +104,13 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
RevCommit tip = walk
.parseCommit(repo.resolve(Constants.HEAD));
for (String branchName : branchNames) {
- if (branchName == null)
+ if (branchName == null) {
continue;
+ }
Ref currentRef = repo.findRef(branchName);
- if (currentRef == null)
+ if (currentRef == null) {
continue;
-
+ }
RevCommit base = walk
.parseCommit(repo.resolve(branchName));
if (!walk.isMergedInto(base, tip)) {
@@ -93,58 +120,105 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
}
}
setCallable(false);
- for (String branchName : branchNames) {
- if (branchName == null)
- continue;
- Ref currentRef = repo.findRef(branchName);
- if (currentRef == null)
- continue;
- String fullName = currentRef.getName();
- if (fullName.equals(currentBranch))
- throw new CannotDeleteCurrentBranchException(
- MessageFormat
- .format(
- JGitText.get().cannotDeleteCheckedOutBranch,
- branchName));
- RefUpdate update = repo.updateRef(fullName);
- update.setRefLogMessage("branch deleted", false); //$NON-NLS-1$
- update.setForceUpdate(true);
- Result deleteResult = update.delete();
-
- boolean ok = true;
- switch (deleteResult) {
- case IO_FAILURE:
- case LOCK_FAILURE:
- case REJECTED:
- ok = false;
- break;
- default:
- break;
- }
+ monitor.start(2);
+ monitor.beginTask(JGitText.get().deletingBranches,
+ branchNames.size());
+ try {
+ for (String branchName : branchNames) {
+ if (branchName == null) {
+ monitor.update(1);
+ continue;
+ }
+ Ref currentRef = repo.findRef(branchName);
+ if (currentRef == null) {
+ monitor.update(1);
+ continue;
+ }
+ String fullName = currentRef.getName();
+ if (fullName.equals(currentBranch)) {
+ throw new CannotDeleteCurrentBranchException(
+ MessageFormat.format(JGitText
+ .get().cannotDeleteCheckedOutBranch,
+ branchName));
+ }
+ RefUpdate update = repo.updateRef(fullName);
+ update.setRefLogMessage("branch deleted", false); //$NON-NLS-1$
+ update.setForceUpdate(true);
+ Result deleteResult = update.delete();
- if (ok) {
- result.add(fullName);
- if (fullName.startsWith(Constants.R_HEADS)) {
- String shortenedName = fullName
- .substring(Constants.R_HEADS.length());
- // remove upstream configuration if any
- final StoredConfig cfg = repo.getConfig();
- cfg.unsetSection(
- ConfigConstants.CONFIG_BRANCH_SECTION,
- shortenedName);
- cfg.save();
+ switch (deleteResult) {
+ case IO_FAILURE:
+ case LOCK_FAILURE:
+ case REJECTED:
+ throw new JGitInternalException(MessageFormat.format(
+ JGitText.get().deleteBranchUnexpectedResult,
+ deleteResult.name()));
+ default:
+ result.add(fullName);
+ if (fullName.startsWith(Constants.R_HEADS)) {
+ shortNames.add(fullName
+ .substring(Constants.R_HEADS.length()));
+ }
+ break;
+ }
+ monitor.update(1);
+ if (monitor.isCancelled()) {
+ break;
}
- } else
- throw new JGitInternalException(MessageFormat.format(
- JGitText.get().deleteBranchUnexpectedResult,
- deleteResult.name()));
+ }
+ } finally {
+ monitor.endTask();
}
- return result;
} catch (IOException ioe) {
throw new JGitInternalException(ioe.getMessage(), ioe);
}
}
+ private void updateConfig(Set<String> shortNames, Exception error)
+ throws GitAPIException {
+ IOException configError = null;
+ if (!shortNames.isEmpty()) {
+ try {
+ // Remove upstream configurations if any
+ StoredConfig cfg = repo.getConfig();
+ boolean changed = false;
+ for (String branchName : shortNames) {
+ changed |= cfg.removeSection(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ branchName);
+ }
+ if (changed) {
+ cfg.save();
+ }
+ } catch (IOException e) {
+ configError = e;
+ }
+ }
+ if (error == null) {
+ if (configError != null) {
+ throw new JGitInternalException(configError.getMessage(),
+ configError);
+ }
+ } else if (error instanceof GitAPIException) {
+ if (configError != null) {
+ error.addSuppressed(configError);
+ }
+ throw (GitAPIException) error;
+ } else if (error instanceof RuntimeException) {
+ if (configError != null) {
+ error.addSuppressed(configError);
+ }
+ throw (RuntimeException) error;
+ } else {
+ JGitInternalException internal = new JGitInternalException(
+ error.getMessage(), error);
+ if (configError != null) {
+ internal.addSuppressed(configError);
+ }
+ throw internal;
+ }
+ }
+
/**
* Set the names of the branches to delete
*
@@ -161,6 +235,22 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
}
/**
+ * Sets the names of the branches to delete
+ *
+ * @param branchNames
+ * the names of the branches to delete; if not set, this will do
+ * nothing; invalid branch names will simply be ignored
+ * @return {@code this}
+ * @since 6.8
+ */
+ public DeleteBranchCommand setBranchNames(Collection<String> branchNames) {
+ checkCallable();
+ this.branchNames.clear();
+ this.branchNames.addAll(branchNames);
+ return this;
+ }
+
+ /**
* Set whether to forcefully delete branches
*
* @param force
@@ -176,4 +266,34 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
this.force = force;
return this;
}
+
+ /**
+ * Retrieves the progress monitor.
+ *
+ * @return the {@link ProgressMonitor} for the delete operation
+ * @since 6.8
+ */
+ public ProgressMonitor getProgressMonitor() {
+ return monitor;
+ }
+
+ /**
+ * Sets the progress monitor associated with the delete operation. By
+ * default, this is set to <code>NullProgressMonitor</code>
+ *
+ * @see NullProgressMonitor
+ * @param monitor
+ * a {@link ProgressMonitor}
+ * @return {@code this}
+ * @since 6.8
+ */
+ public DeleteBranchCommand setProgressMonitor(ProgressMonitor monitor) {
+ checkCallable();
+ if (monitor == null) {
+ monitor = NullProgressMonitor.INSTANCE;
+ }
+ this.monitor = monitor;
+ return this;
+ }
+
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
index 64d0d94171..92d88aad7d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
@@ -48,7 +48,6 @@ public class DeleteTagCommand extends GitCommand<List<String>> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public List<String> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
index 805a886392..d2526287f9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -15,11 +15,11 @@ import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT;
import java.io.IOException;
import java.text.MessageFormat;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -76,6 +76,11 @@ public class DescribeCommand extends GitCommand<String> {
private List<FileNameMatcher> matchers = new ArrayList<>();
/**
+ * Pattern matchers to be applied to tags for exclusion.
+ */
+ private List<FileNameMatcher> excludeMatchers = new ArrayList<>();
+
+ /**
* Whether to use all refs in the refs/ namespace
*/
private boolean useAll;
@@ -263,6 +268,27 @@ public class DescribeCommand extends GitCommand<String> {
return this;
}
+ /**
+ * Sets one or more {@code glob(7)} patterns that tags must not match to be
+ * considered. If multiple patterns are provided, they will all be applied.
+ *
+ * @param patterns
+ * the {@code glob(7)} pattern or patterns
+ * @return {@code this}
+ * @throws org.eclipse.jgit.errors.InvalidPatternException
+ * if the pattern passed in was invalid.
+ * @see <a href=
+ * "https://www.kernel.org/pub/software/scm/git/docs/git-describe.html"
+ * >Git documentation about describe</a>
+ * @since 7.2
+ */
+ public DescribeCommand setExclude(String... patterns) throws InvalidPatternException {
+ for (String p : patterns) {
+ excludeMatchers.add(new FileNameMatcher(p, null));
+ }
+ return this;
+ }
+
private final Comparator<Ref> TAG_TIE_BREAKER = new Comparator<>() {
@Override
@@ -274,25 +300,28 @@ public class DescribeCommand extends GitCommand<String> {
}
}
- private Date tagDate(Ref tag) throws IOException {
+ private Instant tagDate(Ref tag) throws IOException {
RevTag t = w.parseTag(tag.getObjectId());
w.parseBody(t);
- return t.getTaggerIdent().getWhen();
+ return t.getTaggerIdent().getWhenAsInstant();
}
};
private Optional<Ref> getBestMatch(List<Ref> tags) {
if (tags == null || tags.isEmpty()) {
return Optional.empty();
- } else if (matchers.isEmpty()) {
+ } else if (matchers.isEmpty() && excludeMatchers.isEmpty()) {
Collections.sort(tags, TAG_TIE_BREAKER);
return Optional.of(tags.get(0));
- } else {
+ }
+
+ Stream<Ref> matchingTags;
+ if (!matchers.isEmpty()) {
// Find the first tag that matches in the stream of all tags
// filtered by matchers ordered by tie break order
- Stream<Ref> matchingTags = Stream.empty();
+ matchingTags = Stream.empty();
for (FileNameMatcher matcher : matchers) {
- Stream<Ref> m = tags.stream().filter(
+ Stream<Ref> m = tags.stream().filter( //
tag -> {
matcher.append(formatRefName(tag.getName()));
boolean result = matcher.isMatch();
@@ -301,8 +330,22 @@ public class DescribeCommand extends GitCommand<String> {
});
matchingTags = Stream.of(matchingTags, m).flatMap(i -> i);
}
- return matchingTags.sorted(TAG_TIE_BREAKER).findFirst();
+ } else {
+ // If there are no matchers, there are only excluders
+ // Assume all tags match for now before applying excluders
+ matchingTags = tags.stream();
+ }
+
+ for (FileNameMatcher matcher : excludeMatchers) {
+ matchingTags = matchingTags.filter( //
+ tag -> {
+ matcher.append(formatRefName(tag.getName()));
+ boolean result = matcher.isMatch();
+ matcher.reset();
+ return !result;
+ });
}
+ return matchingTags.sorted(TAG_TIE_BREAKER).findFirst();
}
private ObjectId getObjectIdFromRef(Ref r) throws JGitInternalException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
index 3c772c2765..f24127bd51 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
@@ -124,7 +124,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
FetchRecurseSubmodulesMode mode = repo.getConfig().getEnum(
FetchRecurseSubmodulesMode.values(),
ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES, null);
+ ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES);
if (mode != null) {
return mode;
}
@@ -132,7 +132,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
// Fall back to fetch.recurseSubmodules, if set
mode = repo.getConfig().getEnum(FetchRecurseSubmodulesMode.values(),
ConfigConstants.CONFIG_FETCH_SECTION, null,
- ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES, null);
+ ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES);
if (mode != null) {
return mode;
}
@@ -491,13 +491,13 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
*
* Default setting is Transport.DEFAULT_FETCH_THIN
*
- * @param thin
+ * @param thinPack
* the thin-pack preference
* @return {@code this}
*/
- public FetchCommand setThin(boolean thin) {
+ public FetchCommand setThin(boolean thinPack) {
checkCallable();
- this.thin = thin;
+ this.thin = thinPack;
return this;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
index 584d2bc394..f6935e1c67 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
+import java.time.Instant;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
@@ -59,10 +60,12 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
private ProgressMonitor monitor;
- private Date expire;
+ private Instant expire;
private PackConfig pconfig;
+ private Boolean packKeptObjects;
+
/**
* Constructor for GarbageCollectCommand.
*
@@ -96,8 +99,29 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
* @param expire
* minimal age of objects to be pruned.
* @return this instance
+ * @deprecated use {@link #setExpire(Instant)} instead
*/
+ @Deprecated(since = "7.2")
public GarbageCollectCommand setExpire(Date expire) {
+ if (expire != null) {
+ this.expire = expire.toInstant();
+ }
+ return this;
+ }
+
+ /**
+ * During gc() or prune() each unreferenced, loose object which has been
+ * created or modified after <code>expire</code> will not be pruned. Only
+ * older objects may be pruned. If set to null then every object is a
+ * candidate for pruning. Use {@link org.eclipse.jgit.util.GitTimeParser} to
+ * parse time formats used by git gc.
+ *
+ * @param expire
+ * minimal age of objects to be pruned.
+ * @return this instance
+ * @since 7.2
+ */
+ public GarbageCollectCommand setExpire(Instant expire) {
this.expire = expire;
return this;
}
@@ -106,8 +130,8 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
* Whether to use aggressive mode or not. If set to true JGit behaves more
* similar to native git's "git gc --aggressive". If set to
* <code>true</code> compressed objects found in old packs are not reused
- * but every object is compressed again. Configuration variables
- * pack.window and pack.depth are set to 250 for this GC.
+ * but every object is compressed again. Configuration variables pack.window
+ * and pack.depth are set to 250 for this GC.
*
* @since 3.6
* @param aggressive
@@ -132,6 +156,19 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
}
/**
+ * Whether to include objects in `.keep` packs when repacking.
+ *
+ * @param packKeptObjects
+ * whether to include objects in `.keep` files when repacking.
+ * @return this instance
+ * @since 5.13.3
+ */
+ public GarbageCollectCommand setPackKeptObjects(boolean packKeptObjects) {
+ this.packKeptObjects = Boolean.valueOf(packKeptObjects);
+ return this;
+ }
+
+ /**
* Whether to preserve old pack files instead of deleting them.
*
* @since 4.7
@@ -163,7 +200,6 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
return this;
}
- /** {@inheritDoc} */
@Override
public Properties call() throws GitAPIException {
checkCallable();
@@ -175,7 +211,9 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
gc.setProgressMonitor(monitor);
if (this.expire != null)
gc.setExpire(expire);
-
+ if (this.packKeptObjects != null) {
+ gc.setPackKeptObjects(packKeptObjects.booleanValue());
+ }
try {
gc.gc().get();
return toProperties(gc.getStatistics());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
index 3b3e10e7b2..a8b866d25b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
@@ -68,6 +68,7 @@ public class Git implements AutoCloseable {
* @return a {@link org.eclipse.jgit.api.Git} object for the existing git
* repository
* @throws java.io.IOException
+ * if an IO error occurred
*/
public static Git open(File dir) throws IOException {
return open(dir, FS.DETECTED);
@@ -84,6 +85,7 @@ public class Git implements AutoCloseable {
* @return a {@link org.eclipse.jgit.api.Git} object for the existing git
* repository. Closing this instance will close the repo.
* @throws java.io.IOException
+ * if an IO error occurred
*/
public static Git open(File dir, FS fs) throws IOException {
RepositoryCache.FileKey key;
@@ -199,7 +201,24 @@ public class Git implements AutoCloseable {
this(repo, false);
}
- Git(Repository repo, boolean closeRepo) {
+ /**
+ * Construct a new {@link org.eclipse.jgit.api.Git} object which can
+ * interact with the specified git repository.
+ * <p>
+ * All command classes returned by methods of this class will always
+ * interact with this git repository.
+ * <p>
+ * If {@code closeRepo = false} the caller is responsible for closing the
+ * repository.
+ *
+ * @param repo
+ * the git repository this class is interacting with;
+ * {@code null} is not allowed.
+ * @param closeRepo
+ * whether to close the repository when this instance is closed
+ * @since 7.4
+ */
+ public Git(Repository repo, boolean closeRepo) {
this.repo = requireNonNull(repo);
this.closeRepo = closeRepo;
}
@@ -712,6 +731,16 @@ public class Git implements AutoCloseable {
}
/**
+ * Return a command object to execute a {@code PackRefs} command
+ *
+ * @return a {@link org.eclipse.jgit.api.PackRefsCommand}
+ * @since 7.1
+ */
+ public PackRefsCommand packRefs() {
+ return new PackRefsCommand(repo);
+ }
+
+ /**
* Return a command object to find human-readable names of revisions.
*
* @return a {@link org.eclipse.jgit.api.NameRevCommand}.
@@ -792,7 +821,6 @@ public class Git implements AutoCloseable {
return repo;
}
- /** {@inheritDoc} */
@Override
public String toString() {
return "Git[" + repo + "]"; //$NON-NLS-1$//$NON-NLS-2$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java
index 240290f4f9..1da71aa6eb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java
@@ -19,6 +19,7 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
@@ -44,6 +45,8 @@ public class InitCommand implements Callable<Git> {
private String initialBranch;
+ private boolean relativePaths;
+
/**
* {@inheritDoc}
* <p>
@@ -100,7 +103,11 @@ public class InitCommand implements Callable<Git> {
: initialBranch);
Repository repository = builder.build();
if (!repository.getObjectDatabase().exists())
- repository.create(bare);
+ if (repository instanceof FileRepository) {
+ ((FileRepository) repository).create(bare, relativePaths);
+ } else {
+ repository.create(bare);
+ }
return new Git(repository, true);
} catch (IOException | ConfigInvalidException e) {
throw new JGitInternalException(e.getMessage(), e);
@@ -214,4 +221,18 @@ public class InitCommand implements Callable<Git> {
this.initialBranch = branch;
return this;
}
+
+ /**
+ * * Set whether the repository shall use relative paths for GIT_DIR and
+ * GIT_WORK_TREE
+ *
+ * @param relativePaths
+ * if true, use relative paths for GIT_DIR and GIT_WORK_TREE
+ * @return {@code this}
+ * @since 7.2
+ */
+ public InitCommand setRelativeDirs(boolean relativePaths) {
+ this.relativePaths = relativePaths;
+ return this;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
index 4b7445fc95..e3c3c89bcb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
@@ -73,7 +73,6 @@ public class ListBranchCommand extends GitCommand<List<Ref>> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public List<Ref> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListNotesCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListNotesCommand.java
index 34955e86f9..9eb52866dc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListNotesCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListNotesCommand.java
@@ -44,7 +44,6 @@ public class ListNotesCommand extends GitCommand<List<Note>> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public List<Note> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
index 27a5288429..9a4a822b59 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
@@ -54,8 +54,11 @@ public class ListTagCommand extends GitCommand<List<Ref>> {
* the specified commit
* @return this command
* @throws IOException
+ * if an IO error occurred
* @throws IncorrectObjectTypeException
+ * if commit has an incorrect object type
* @throws MissingObjectException
+ * if the commit is missing
*
* @since 6.6
*/
@@ -67,7 +70,6 @@ public class ListTagCommand extends GitCommand<List<Ref>> {
return this;
}
- /** {@inheritDoc} */
@Override
public List<Ref> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
index fa40d93e52..2a8d34ed68 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
@@ -53,13 +53,11 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter;
* </pre>
* <p>
*
- * <p>
* Get commits only for a specific file:
*
* <pre>
* git.log().add(head).addPath(&quot;dir/filename.txt&quot;).call();
* </pre>
- * <p>
*
* @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-log.html"
* >Git documentation about Log</a>
@@ -112,10 +110,10 @@ public class LogCommand extends GitCommand<Iterable<RevCommit>> {
}
if (!filters.isEmpty()) {
if (filters.size() == 1) {
- filters.add(TreeFilter.ANY_DIFF);
+ walk.setTreeFilter(filters.get(0));
+ } else {
+ walk.setTreeFilter(AndTreeFilter.create(filters));
}
- walk.setTreeFilter(AndTreeFilter.create(filters));
-
}
if (skip > -1 && maxCount > -1)
walk.setRevFilter(AndRevFilter.create(SkipRevFilter.create(skip),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
index ed4a5342b3..7064f5a57a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
@@ -13,9 +13,9 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -75,7 +75,7 @@ public class MergeCommand extends GitCommand<MergeResult> {
private ContentMergeStrategy contentStrategy;
- private List<Ref> commits = new LinkedList<>();
+ private List<Ref> commits = new ArrayList<>();
private Boolean squash;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
index 7347f63889..0fa11f2cbb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java
@@ -31,7 +31,9 @@ public class MergeResult {
* The status the merge resulted in.
*/
public enum MergeStatus {
- /** */
+ /**
+ * Merge is a fast-forward
+ */
FAST_FORWARD {
@Override
public String toString() {
@@ -44,6 +46,8 @@ public class MergeResult {
}
},
/**
+ * Merge is a fast-forward, squashed
+ *
* @since 2.0
*/
FAST_FORWARD_SQUASHED {
@@ -57,7 +61,9 @@ public class MergeResult {
return true;
}
},
- /** */
+ /**
+ * Already up to date, merge was a no-op
+ */
ALREADY_UP_TO_DATE {
@Override
public String toString() {
@@ -69,7 +75,9 @@ public class MergeResult {
return true;
}
},
- /** */
+ /**
+ * Merge failed
+ */
FAILED {
@Override
public String toString() {
@@ -81,7 +89,9 @@ public class MergeResult {
return false;
}
},
- /** */
+ /**
+ * Merged
+ */
MERGED {
@Override
public String toString() {
@@ -94,6 +104,8 @@ public class MergeResult {
}
},
/**
+ * Merged, squashed, not updating HEAD
+ *
* @since 2.0
*/
MERGED_SQUASHED {
@@ -108,6 +120,8 @@ public class MergeResult {
}
},
/**
+ * Merged, squashed, not committed
+ *
* @since 3.0
*/
MERGED_SQUASHED_NOT_COMMITTED {
@@ -121,7 +135,9 @@ public class MergeResult {
return true;
}
},
- /** */
+ /**
+ * Merge raised conflicts to be resolved
+ */
CONFLICTING {
@Override
public String toString() {
@@ -134,6 +150,8 @@ public class MergeResult {
}
},
/**
+ * Merge was aborted
+ *
* @since 2.2
*/
ABORTED {
@@ -148,6 +166,8 @@ public class MergeResult {
}
},
/**
+ * Merged, not committed
+ *
* @since 3.0
**/
MERGED_NOT_COMMITTED {
@@ -161,7 +181,7 @@ public class MergeResult {
return true;
}
},
- /** */
+ /** Not yet supported */
NOT_SUPPORTED {
@Override
public String toString() {
@@ -191,6 +211,8 @@ public class MergeResult {
};
/**
+ * Whether the merge was successful
+ *
* @return whether the status indicates a successful result
*/
public abstract boolean isSuccessful();
@@ -364,7 +386,6 @@ public class MergeResult {
return base;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java
index e6ab1e6588..1ff6e98b12 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java
@@ -102,7 +102,6 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> {
};
}
- /** {@inheritDoc} */
@Override
public Map<ObjectId, String> call() throws GitAPIException {
try {
@@ -349,7 +348,7 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> {
}
// Don't tiebreak if prefixes are the same, in order to prefer first-parent
// paths.
- return li - ri;
+ return (long) li - ri;
}
private static String simplify(String refName) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PackRefsCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PackRefsCommand.java
new file mode 100644
index 0000000000..29a69c5ac4
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PackRefsCommand.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * 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.api;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Optimize storage of references.
+ *
+ * @since 7.1
+ */
+public class PackRefsCommand extends GitCommand<String> {
+ private ProgressMonitor monitor;
+
+ private boolean all;
+
+ /**
+ * Creates a new {@link PackRefsCommand} instance with default values.
+ *
+ * @param repo
+ * the repository this command will be used on
+ */
+ public PackRefsCommand(Repository repo) {
+ super(repo);
+ this.monitor = NullProgressMonitor.INSTANCE;
+ }
+
+ /**
+ * Set progress monitor
+ *
+ * @param monitor
+ * a progress monitor
+ * @return this instance
+ */
+ public PackRefsCommand setProgressMonitor(ProgressMonitor monitor) {
+ this.monitor = monitor;
+ return this;
+ }
+
+ /**
+ * Specify whether to pack all the references.
+ *
+ * @param all
+ * if <code>true</code> all the loose refs will be packed
+ * @return this instance
+ */
+ public PackRefsCommand setAll(boolean all) {
+ this.all = all;
+ return this;
+ }
+
+ /**
+ * Whether to pack all the references
+ *
+ * @return whether to pack all the references
+ */
+ public boolean isAll() {
+ return all;
+ }
+
+ @Override
+ public String call() throws GitAPIException {
+ checkCallable();
+ try {
+ repo.getRefDatabase().packRefs(monitor, this);
+ return JGitText.get().packRefsSuccessful;
+ } catch (IOException e) {
+ throw new JGitInternalException(JGitText.get().packRefsFailed, e);
+ }
+ }
+}
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 83ae0fc9d4..4b2cee45c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
@@ -533,9 +533,9 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
Config config) {
BranchRebaseMode mode = config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION,
- branchName, ConfigConstants.CONFIG_KEY_REBASE, null);
+ branchName, ConfigConstants.CONFIG_KEY_REBASE);
if (mode == null) {
- mode = config.getEnum(BranchRebaseMode.values(),
+ mode = config.getEnum(
ConfigConstants.CONFIG_PULL_SECTION, null,
ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE);
}
@@ -549,7 +549,7 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
Config config = repo.getConfig();
Merge ffMode = config.getEnum(Merge.values(),
ConfigConstants.CONFIG_PULL_SECTION, null,
- ConfigConstants.CONFIG_KEY_FF, null);
+ ConfigConstants.CONFIG_KEY_FF);
return ffMode != null ? FastForwardMode.valueOf(ffMode) : null;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java
index cbb9cc2f78..fdc7f3f333 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullResult.java
@@ -89,7 +89,6 @@ public class PullResult {
return true;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
index 2ed1c52fd7..e9d1a3213b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
@@ -614,13 +614,13 @@ public class PushCommand extends
*
* Default setting is Transport.DEFAULT_PUSH_THIN
*
- * @param thin
+ * @param thinPack
* the thin-pack preference value
* @return {@code this}
*/
- public PushCommand setThin(boolean thin) {
+ public PushCommand setThin(boolean thinPack) {
checkCallable();
- this.thin = thin;
+ this.thin = thinPack;
return this;
}
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 1e5523f275..3ae7a6c81e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -18,12 +18,13 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@@ -86,7 +87,6 @@ import org.eclipse.jgit.util.RawParseUtils;
* supported options and arguments of this command and a {@link #call()} method
* to finally execute the command. Each instance of this class should only be
* used for one invocation of the command (means: one call to {@link #call()})
- * <p>
*
* @see <a
* href="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html"
@@ -290,13 +290,17 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
RebaseResult res = initFilesAndRewind();
- if (stopAfterInitialization)
+ if (stopAfterInitialization) {
return RebaseResult.INTERACTIVE_PREPARED_RESULT;
+ }
if (res != null) {
- autoStashApply();
- if (rebaseState.getDir().exists())
+ if (!autoStashApply()) {
+ res = RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
+ }
+ if (rebaseState.getDir().exists()) {
FileUtils.delete(rebaseState.getDir(),
FileUtils.RECURSIVE);
+ }
return res;
}
}
@@ -382,7 +386,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
private boolean autoStashApply() throws IOException, GitAPIException {
- boolean conflicts = false;
+ boolean success = true;
if (rebaseState.getFile(AUTOSTASH).exists()) {
String stash = rebaseState.readFile(AUTOSTASH);
try (Git git = Git.wrap(repo)) {
@@ -390,7 +394,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
.ignoreRepositoryState(true).setStrategy(strategy)
.call();
} catch (StashApplyFailureException e) {
- conflicts = true;
+ success = false;
try (RevWalk rw = new RevWalk(repo)) {
ObjectId stashId = repo.resolve(stash);
RevCommit commit = rw.parseCommit(stashId);
@@ -399,7 +403,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
}
- return conflicts;
+ return success;
}
private void updateStashRef(ObjectId commitId, PersonIdent refLogIdent,
@@ -724,13 +728,15 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
boolean lastStepIsForward) throws IOException, GitAPIException {
String headName = rebaseState.readFile(HEAD_NAME);
updateHead(headName, finalHead, upstreamCommit);
- boolean stashConflicts = autoStashApply();
+ boolean unstashSuccessful = autoStashApply();
getRepository().autoGC(monitor);
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
- if (stashConflicts)
+ if (!unstashSuccessful) {
return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
- if (lastStepIsForward || finalHead == null)
+ }
+ if (lastStepIsForward || finalHead == null) {
return RebaseResult.FAST_FORWARD_RESULT;
+ }
return RebaseResult.OK_RESULT;
}
@@ -1000,7 +1006,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
/**
* @return the commit if we had to do a commit, otherwise null
* @throws GitAPIException
+ * if JGit API failed
* @throws IOException
+ * if an IO error occurred
*/
private RevCommit continueRebase() throws GitAPIException, IOException {
// if there are still conflicts, we throw a specific Exception
@@ -1057,12 +1065,16 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
String authorScript = toAuthorScript(author);
rebaseState.createFile(AUTHOR_SCRIPT, authorScript);
rebaseState.createFile(MESSAGE, commitToPick.getFullMessage());
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (DiffFormatter df = new DiffFormatter(bos)) {
- df.setRepository(repo);
- df.format(commitToPick.getParent(0), commitToPick);
+ if (commitToPick.getParentCount() > 0) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (DiffFormatter df = new DiffFormatter(bos)) {
+ df.setRepository(repo);
+ df.format(commitToPick.getParent(0), commitToPick);
+ }
+ rebaseState.createFile(PATCH, new String(bos.toByteArray(), UTF_8));
+ } else {
+ rebaseState.createFile(PATCH, ""); //$NON-NLS-1$
}
- rebaseState.createFile(PATCH, new String(bos.toByteArray(), UTF_8));
rebaseState.createFile(STOPPED_SHA,
repo.newObjectReader()
.abbreviate(
@@ -1102,13 +1114,15 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
* that can not be parsed as steps
*
* @param numSteps
+ * number of steps to remove
* @throws IOException
+ * if an IO error occurred
*/
private void popSteps(int numSteps) throws IOException {
if (numSteps == 0)
return;
- List<RebaseTodoLine> todoLines = new LinkedList<>();
- List<RebaseTodoLine> poppedLines = new LinkedList<>();
+ List<RebaseTodoLine> todoLines = new ArrayList<>();
+ List<RebaseTodoLine> poppedLines = new ArrayList<>();
for (RebaseTodoLine line : repo.readRebaseTodo(
rebaseState.getPath(GIT_REBASE_TODO), true)) {
@@ -1146,7 +1160,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
if (!isInteractive() && walk.isMergedInto(upstream, headCommit))
return RebaseResult.UP_TO_DATE_RESULT;
else if (!isInteractive() && walk.isMergedInto(headCommit, upstream)) {
- // head is already merged into upstream, fast-foward
+ // head is already merged into upstream, fast-forward
monitor.beginTask(MessageFormat.format(
JGitText.get().resettingHead,
upstreamCommit.getShortMessage()), ProgressMonitor.UNKNOWN);
@@ -1217,7 +1231,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
Iterator<RevCommit> commitsToUse = r.iterator();
while (commitsToUse.hasNext()) {
RevCommit commit = commitsToUse.next();
- if (preserveMerges || commit.getParentCount() == 1) {
+ if (preserveMerges || commit.getParentCount() <= 1) {
cherryPickList.add(commit);
}
}
@@ -1234,23 +1248,31 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
walk.markStart(upstreamCommit);
walk.markStart(headCommit);
RevCommit base;
- while ((base = walk.next()) != null)
+ while ((base = walk.next()) != null) {
RebaseState.createFile(rewrittenDir, base.getName(),
upstreamCommit.getName());
-
+ }
Iterator<RevCommit> iterator = cherryPickList.iterator();
pickLoop: while(iterator.hasNext()){
RevCommit commit = iterator.next();
- for (int i = 0; i < commit.getParentCount(); i++) {
- boolean parentRewritten = new File(rewrittenDir, commit
- .getParent(i).getName()).exists();
- if (parentRewritten) {
- new File(rewrittenDir, commit.getName()).createNewFile();
- continue pickLoop;
+ int nOfParents = commit.getParentCount();
+ if (nOfParents == 0) {
+ // Must be the very first commit in the cherryPickList. We
+ // have independent branches.
+ new File(rewrittenDir, commit.getName()).createNewFile();
+ } else {
+ for (int i = 0; i < nOfParents; i++) {
+ boolean parentRewritten = new File(rewrittenDir,
+ commit.getParent(i).getName()).exists();
+ if (parentRewritten) {
+ new File(rewrittenDir, commit.getName())
+ .createNewFile();
+ continue pickLoop;
+ }
}
+ // commit is only merged in, needs not be rewritten
+ iterator.remove();
}
- // commit is only merged in, needs not be rewritten
- iterator.remove();
}
}
return cherryPickList;
@@ -1289,7 +1311,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
* if we can fast-forward to.
* @return the new head, or null
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.api.errors.GitAPIException
+ * if a JGit API exception occurred
*/
public RevCommit tryFastForward(RevCommit newCommit) throws IOException,
GitAPIException {
@@ -1434,13 +1458,14 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
throw new JGitInternalException(
JGitText.get().abortingRebaseFailed);
}
- boolean stashConflicts = autoStashApply();
+ boolean unstashSuccessful = autoStashApply();
// cleanup the files
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
repo.writeCherryPickHead(null);
repo.writeMergeHeads(null);
- if (stashConflicts)
+ if (!unstashSuccessful) {
return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
+ }
return result;
} finally {
@@ -1540,6 +1565,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
* the name of the upstream branch
* @return {@code this}
* @throws org.eclipse.jgit.api.errors.RefNotFoundException
+ * if {@code upstream} Ref couldn't be resolved
*/
public RebaseCommand setUpstream(String upstream)
throws RefNotFoundException {
@@ -1811,23 +1837,26 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
// the time is saved as <seconds since 1970> <timezone offset>
int timeStart = 0;
- if (time.startsWith("@")) //$NON-NLS-1$
+ if (time.startsWith("@")) { //$NON-NLS-1$
timeStart = 1;
- else
+ } else {
timeStart = 0;
- long when = Long
- .parseLong(time.substring(timeStart, time.indexOf(' '))) * 1000;
+ }
+ Instant when = Instant.ofEpochSecond(
+ Long.parseLong(time.substring(timeStart, time.indexOf(' '))));
String tzOffsetString = time.substring(time.indexOf(' ') + 1);
int multiplier = -1;
- if (tzOffsetString.charAt(0) == '+')
+ if (tzOffsetString.charAt(0) == '+') {
multiplier = 1;
+ }
int hours = Integer.parseInt(tzOffsetString.substring(1, 3));
int minutes = Integer.parseInt(tzOffsetString.substring(3, 5));
// this is in format (+/-)HHMM (hours and minutes)
- // we need to convert into minutes
- int tz = (hours * 60 + minutes) * multiplier;
- if (name != null && email != null)
+ ZoneOffset tz = ZoneOffset.ofHoursMinutes(hours * multiplier,
+ minutes * multiplier);
+ if (name != null && email != null) {
return new PersonIdent(name, email, when, tz);
+ }
return null;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java
index 826ea518e4..2aa64df46f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java
@@ -146,6 +146,8 @@ public class RebaseResult {
};
/**
+ * Whether the rebase was successful
+ *
* @return whether the status indicates a successful result
*/
public abstract boolean isSuccessful();
@@ -194,6 +196,7 @@ public class RebaseResult {
* Create <code>RebaseResult</code>
*
* @param status
+ * the overall rebase status
* @param commit
* current commit
* @return the RebaseResult
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
index dead2749b7..a149649004 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
@@ -68,7 +68,7 @@ public class ReflogCommand extends GitCommand<Collection<ReflogEntry>> {
checkCallable();
try {
- ReflogReader reader = repo.getReflogReader(ref);
+ ReflogReader reader = repo.getRefDatabase().getReflogReader(ref);
if (reader == null)
throw new RefNotFoundException(MessageFormat.format(
JGitText.get().refNotResolved, ref));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
index 553fc2e7a0..ad553f07a9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java
@@ -49,18 +49,6 @@ public class RemoteRemoveCommand extends GitCommand<RemoteConfig> {
/**
* The name of the remote to remove.
*
- * @param name
- * a remote name
- * @deprecated use {@link #setRemoteName} instead
- */
- @Deprecated
- public void setName(String name) {
- this.remoteName = name;
- }
-
- /**
- * The name of the remote to remove.
- *
* @param remoteName
* a remote name
* @return {@code this}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
index e3d01861fc..68ddce361f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java
@@ -71,18 +71,6 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> {
/**
* The name of the remote to change the URL for.
*
- * @param name
- * a remote name
- * @deprecated use {@link #setRemoteName} instead
- */
- @Deprecated
- public void setName(String name) {
- this.remoteName = name;
- }
-
- /**
- * The name of the remote to change the URL for.
- *
* @param remoteName
* a remote remoteName
* @return {@code this}
@@ -96,18 +84,6 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> {
/**
* The new URL for the remote.
*
- * @param uri
- * an URL for the remote
- * @deprecated use {@link #setRemoteUri} instead
- */
- @Deprecated
- public void setUri(URIish uri) {
- this.remoteUri = uri;
- }
-
- /**
- * The new URL for the remote.
- *
* @param remoteUri
* an URL for the remote
* @return {@code this}
@@ -121,23 +97,6 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> {
/**
* Whether to change the push URL of the remote instead of the fetch URL.
*
- * @param push
- * <code>true</code> to set the push url, <code>false</code> to
- * set the fetch url
- * @deprecated use {@link #setUriType} instead
- */
- @Deprecated
- public void setPush(boolean push) {
- if (push) {
- setUriType(UriType.PUSH);
- } else {
- setUriType(UriType.FETCH);
- }
- }
-
- /**
- * Whether to change the push URL of the remote instead of the fetch URL.
- *
* @param type
* the <code>UriType</code> value to set
* @return {@code this}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoveNoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoveNoteCommand.java
index f4b60adedb..c65cbf160f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoveNoteCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoveNoteCommand.java
@@ -47,7 +47,6 @@ public class RemoveNoteCommand extends GitCommand<Note> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Note call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java
index 922cb531de..029f9d02d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java
@@ -55,7 +55,6 @@ public class RenameBranchCommand extends GitCommand<Ref> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Ref call() throws GitAPIException, RefNotFoundException, InvalidRefNameException,
RefAlreadyExistsException, DetachedHeadException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
index 87b4acb14c..47145a0563 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ResetCommand.java
@@ -11,8 +11,8 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedList;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -90,7 +90,7 @@ public class ResetCommand extends GitCommand<Ref> {
private ResetType mode;
- private Collection<String> filepaths = new LinkedList<>();
+ private Collection<String> filepaths = new ArrayList<>();
private boolean isReflogDisabled;
@@ -436,7 +436,6 @@ public class ResetCommand extends GitCommand<Ref> {
repo.writeMergeCommitMsg(null);
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
index 513f579b67..6643c83662 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and others
+ * Copyright (C) 2010, 2024 Christian Halstrick <christian.halstrick@sap.com> 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
@@ -13,7 +13,7 @@ import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
import java.io.IOException;
import java.text.MessageFormat;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -58,11 +58,13 @@ import org.eclipse.jgit.treewalk.FileTreeIterator;
* >Git documentation about revert</a>
*/
public class RevertCommand extends GitCommand<RevCommit> {
- private List<Ref> commits = new LinkedList<>();
+ private List<Ref> commits = new ArrayList<>();
private String ourCommitName = null;
- private List<Ref> revertedRefs = new LinkedList<>();
+ private boolean insertChangeId;
+
+ private List<Ref> revertedRefs = new ArrayList<>();
private MergeResult failingResult;
@@ -132,7 +134,7 @@ public class RevertCommand extends GitCommand<RevCommit> {
String ourName = calculateOurName(headRef);
String revertName = srcCommit.getId()
- .abbreviate(OBJECT_ID_ABBREV_STRING_LENGTH).name() + " " //$NON-NLS-1$
+ .abbreviate(OBJECT_ID_ABBREV_STRING_LENGTH).name() + ' '
+ srcCommit.getShortMessage();
ResolveMerger merger = (ResolveMerger) strategy.newMerger(repo);
@@ -141,8 +143,8 @@ public class RevertCommand extends GitCommand<RevCommit> {
merger.setCommitNames(new String[] {
"BASE", ourName, revertName }); //$NON-NLS-1$
- String shortMessage = "Revert \"" + srcCommit.getShortMessage() //$NON-NLS-1$
- + "\""; //$NON-NLS-1$
+ String shortMessage = "Revert \"" //$NON-NLS-1$
+ + srcCommit.getFirstMessageLine() + '"';
String newMessage = shortMessage + "\n\n" //$NON-NLS-1$
+ "This reverts commit " + srcCommit.getId().getName() //$NON-NLS-1$
+ ".\n"; //$NON-NLS-1$
@@ -162,6 +164,7 @@ public class RevertCommand extends GitCommand<RevCommit> {
dco.checkout();
try (Git git = new Git(getRepository())) {
newHead = git.commit().setMessage(newMessage)
+ .setInsertChangeId(insertChangeId)
.setReflogComment("revert: " + shortMessage) //$NON-NLS-1$
.call();
}
@@ -327,4 +330,18 @@ public class RevertCommand extends GitCommand<RevCommit> {
this.monitor = monitor;
return this;
}
+
+ /**
+ * Defines whether to add a Gerrit change ID to each revert commit message.
+ *
+ * @param insertChangeId
+ * whether to insert a change ID
+ * @return {@code this}
+ * @since 6.8
+ */
+ public RevertCommand setInsertChangeId(boolean insertChangeId) {
+ this.insertChangeId = insertChangeId;
+ return this;
+ }
+
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RmCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RmCommand.java
index 656f36a81a..7459e7298f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RmCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RmCommand.java
@@ -13,7 +13,6 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -71,7 +70,7 @@ public class RmCommand extends GitCommand<DirCache> {
*/
public RmCommand(Repository repo) {
super(repo);
- filepatterns = new LinkedList<>();
+ filepatterns = new ArrayList<>();
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ShowNoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ShowNoteCommand.java
index f64cb6b831..7bb9de0ef4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ShowNoteCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ShowNoteCommand.java
@@ -44,7 +44,6 @@ public class ShowNoteCommand extends GitCommand<Note> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Note call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
index 17036a9cd3..b0b715e06b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2021 GitHub Inc. and others
+ * Copyright (C) 2012, 2023 GitHub 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
@@ -23,6 +23,7 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.StashApplyFailureException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
+import org.eclipse.jgit.dircache.Checkout;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheCheckout;
@@ -48,7 +49,6 @@ import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.WorkingTreeOptions;
/**
* Command class to apply a stashed commit.
@@ -263,18 +263,6 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
/**
* Whether to restore the index state
*
- * @param applyIndex
- * true (default) if the command should restore the index state
- * @deprecated use {@link #setRestoreIndex} instead
- */
- @Deprecated
- public void setApplyIndex(boolean applyIndex) {
- this.restoreIndex = applyIndex;
- }
-
- /**
- * Whether to restore the index state
- *
* @param restoreIndex
* true (default) if the command should restore the index state
* @return {@code this}
@@ -319,19 +307,6 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
/**
* Whether the command should restore untracked files
*
- * @param applyUntracked
- * true (default) if the command should restore untracked files
- * @since 3.4
- * @deprecated use {@link #setRestoreUntracked} instead
- */
- @Deprecated
- public void setApplyUntracked(boolean applyUntracked) {
- this.restoreUntracked = applyUntracked;
- }
-
- /**
- * Whether the command should restore untracked files
- *
* @param restoreUntracked
* true (default) if the command should restore untracked files
* @return {@code this}
@@ -383,8 +358,7 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
private void resetUntracked(RevTree tree) throws CheckoutConflictException,
IOException {
Set<String> actuallyModifiedPaths = new HashSet<>();
- WorkingTreeOptions options = repo.getConfig()
- .get(WorkingTreeOptions.KEY);
+ Checkout checkout = new Checkout(repo).setRecursiveDeletion(true);
// TODO maybe NameConflictTreeWalk ?
try (TreeWalk walk = new TreeWalk(repo)) {
walk.addTree(tree);
@@ -408,17 +382,17 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
FileTreeIterator fIter = walk
.getTree(1, FileTreeIterator.class);
+ String gitPath = entry.getPathString();
if (fIter != null) {
if (fIter.isModified(entry, true, reader)) {
// file exists and is dirty
- throw new CheckoutConflictException(
- entry.getPathString());
+ throw new CheckoutConflictException(gitPath);
}
}
- checkoutPath(entry, reader, options,
+ checkoutPath(entry, gitPath, reader, checkout,
new CheckoutMetadata(eolStreamType, null));
- actuallyModifiedPaths.add(entry.getPathString());
+ actuallyModifiedPaths.add(gitPath);
}
} finally {
if (!actuallyModifiedPaths.isEmpty()) {
@@ -428,11 +402,11 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
}
}
- private void checkoutPath(DirCacheEntry entry, ObjectReader reader,
- WorkingTreeOptions options, CheckoutMetadata checkoutMetadata) {
+ private void checkoutPath(DirCacheEntry entry, String gitPath,
+ ObjectReader reader,
+ Checkout checkout, CheckoutMetadata checkoutMetadata) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader, true,
- checkoutMetadata, options);
+ checkout.checkout(entry, checkoutMetadata, reader, gitPath);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
index 23fbe0197f..2dba0ef0f2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
@@ -165,7 +165,8 @@ public class StashDropCommand extends GitCommand<ObjectId> {
List<ReflogEntry> entries;
try {
- ReflogReader reader = repo.getReflogReader(R_STASH);
+ ReflogReader reader = repo.getRefDatabase()
+ .getReflogReader(R_STASH);
if (reader == null) {
throw new RefNotFoundException(MessageFormat
.format(JGitText.get().refNotResolved, stashRef));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashListCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashListCommand.java
index 8171c4c3ae..828a3020f8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashListCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashListCommand.java
@@ -43,7 +43,6 @@ public class StashListCommand extends GitCommand<Collection<RevCommit>> {
super(repo);
}
- /** {@inheritDoc} */
@Override
public Collection<RevCommit> call() throws GitAPIException,
InvalidRefNameException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
index eab389460a..cdd078ea25 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StatusCommand.java
@@ -10,7 +10,7 @@
package org.eclipse.jgit.api;
import java.io.IOException;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -83,7 +83,7 @@ public class StatusCommand extends GitCommand<Status> {
*/
public StatusCommand addPath(String path) {
if (paths == null)
- paths = new LinkedList<>();
+ paths = new ArrayList<>();
paths.add(path);
return this;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index 606d567393..5105dfc2e5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -66,6 +66,7 @@ public class SubmoduleAddCommand extends
* Set the submodule name
*
* @param name
+ * name of the submodule
* @return this command
* @since 5.1
*/
@@ -117,6 +118,7 @@ public class SubmoduleAddCommand extends
*
* @return true if submodule exists in index, false otherwise
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected boolean submoduleExists() throws IOException {
TreeFilter filter = PathFilter.create(path);
@@ -174,8 +176,9 @@ public class SubmoduleAddCommand extends
CloneCommand clone = Git.cloneRepository();
configure(clone);
clone.setDirectory(moduleDirectory);
- clone.setGitDir(new File(new File(repo.getDirectory(),
- Constants.MODULES), path));
+ clone.setGitDir(new File(
+ new File(repo.getCommonDirectory(), Constants.MODULES), path));
+ clone.setRelativePaths(true);
clone.setURI(resolvedUri);
if (monitor != null)
clone.setProgressMonitor(monitor);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
index f4b8ac2e07..0aa1515334 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
@@ -61,6 +61,7 @@ public class SubmoduleDeinitCommand
* Constructor of SubmoduleDeinitCommand
*
* @param repo
+ * repository this command works on
*/
public SubmoduleDeinitCommand(Repository repo) {
super(repo);
@@ -69,7 +70,6 @@ public class SubmoduleDeinitCommand
/**
* {@inheritDoc}
- * <p>
*
* @return the set of repositories successfully deinitialized.
* @throws NoSuchSubmoduleException
@@ -135,6 +135,7 @@ public class SubmoduleDeinitCommand
* @param path
* the path to clean
* @throws IOException
+ * if an IO error occurred
*/
private void deinit(String path) throws IOException {
File dir = new File(repo.getWorkTree(), path);
@@ -157,10 +158,14 @@ public class SubmoduleDeinitCommand
* the parent repo's index or HEAD.
*
* @param revWalk
+ * used to walk commit graph
* @param path
+ * path of the submodule
* @return status of the command
* @throws GitAPIException
+ * if JGit API failed
* @throws IOException
+ * if an IO error occurred
*/
private SubmoduleDeinitStatus checkDirty(RevWalk revWalk, String path)
throws GitAPIException, IOException {
@@ -216,6 +221,7 @@ public class SubmoduleDeinitCommand
* @return {@code true} if path exists and is a submodule in index,
* {@code false} otherwise
* @throws IOException
+ * if an IO error occurred
*/
private boolean submoduleExists(String path) throws IOException {
TreeFilter filter = PathFilter.create(path);
@@ -241,6 +247,7 @@ public class SubmoduleDeinitCommand
* else it will refuse to do so.
*
* @param force
+ * execute the command forcefully if there are local modifications
* @return {@code this}
*/
public SubmoduleDeinitCommand setForce(boolean force) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java
index 8129be4a71..b7d7b66333 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java
@@ -25,6 +25,7 @@ public class SubmoduleDeinitResult {
* @param path
* path of the submodule
* @param status
+ * effect of a SubmoduleDeinitCommand's execution
*/
public SubmoduleDeinitResult(String path,
SubmoduleDeinitCommand.SubmoduleDeinitStatus status) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
index bdceabad37..03b4a000ad 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
@@ -61,7 +61,6 @@ public class SubmoduleInitCommand extends GitCommand<Collection<String>> {
return this;
}
- /** {@inheritDoc} */
@Override
public Collection<String> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
index 196ef7b2a9..d5bc0dda98 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
@@ -61,7 +61,6 @@ public class SubmoduleStatusCommand extends
return this;
}
- /** {@inheritDoc} */
@Override
public Map<String, SubmoduleStatus> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
index b319a1b478..4f3e8512c3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
@@ -70,6 +70,7 @@ public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> {
* a {@link org.eclipse.jgit.lib.Repository} object.
* @return shortened branch name, null on failures
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected String getHeadBranch(Repository subRepo) throws IOException {
Ref head = subRepo.exactRef(Constants.HEAD);
@@ -79,7 +80,6 @@ public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> {
return null;
}
- /** {@inheritDoc} */
@Override
public Map<String, String> call() throws GitAPIException {
checkCallable();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
index df73164161..5e4b2ee0b7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
@@ -28,6 +28,7 @@ import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -39,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.submodule.SubmoduleWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.util.FileUtils;
/**
* A class used to execute a submodule update command.
@@ -62,6 +64,8 @@ public class SubmoduleUpdateCommand extends
private boolean fetch = false;
+ private boolean clonedRestored;
+
/**
* <p>
* Constructor for SubmoduleUpdateCommand.
@@ -116,25 +120,77 @@ public class SubmoduleUpdateCommand extends
return this;
}
+ private static boolean submoduleExists(File gitDir) {
+ if (gitDir != null && gitDir.isDirectory()) {
+ File[] files = gitDir.listFiles();
+ return files != null && files.length != 0;
+ }
+ return false;
+ }
+
+ private static void restoreSubmodule(File gitDir, File workingTree)
+ throws IOException {
+ LockFile dotGitLock = new LockFile(
+ new File(workingTree, Constants.DOT_GIT));
+ if (dotGitLock.lock()) {
+ String content = Constants.GITDIR
+ + getRelativePath(gitDir, workingTree);
+ dotGitLock.write(Constants.encode(content));
+ dotGitLock.commit();
+ }
+ }
+
+ private static String getRelativePath(File gitDir, File workingTree) {
+ File relPath;
+ try {
+ relPath = workingTree.toPath().relativize(gitDir.toPath())
+ .toFile();
+ } catch (IllegalArgumentException e) {
+ relPath = gitDir;
+ }
+ return FileUtils.pathToString(relPath);
+ }
+
+ private String determineUpdateMode(String mode) {
+ if (clonedRestored) {
+ return ConfigConstants.CONFIG_KEY_CHECKOUT;
+ }
+ return mode;
+ }
+
private Repository getOrCloneSubmodule(SubmoduleWalk generator, String url)
throws IOException, GitAPIException {
Repository repository = generator.getRepository();
+ boolean restored = false;
+ boolean cloned = false;
if (repository == null) {
- if (callback != null) {
- callback.cloningSubmodule(generator.getPath());
- }
- CloneCommand clone = Git.cloneRepository();
- configure(clone);
- clone.setURI(url);
- clone.setDirectory(generator.getDirectory());
- clone.setGitDir(
- new File(new File(repo.getDirectory(), Constants.MODULES),
- generator.getPath()));
- if (monitor != null) {
- clone.setProgressMonitor(monitor);
+ File gitDir = new File(
+ new File(repo.getCommonDirectory(), Constants.MODULES),
+ generator.getPath());
+ if (submoduleExists(gitDir)) {
+ restoreSubmodule(gitDir, generator.getDirectory());
+ restored = true;
+ clonedRestored = true;
+ repository = generator.getRepository();
+ } else {
+ if (callback != null) {
+ callback.cloningSubmodule(generator.getPath());
+ }
+ CloneCommand clone = Git.cloneRepository();
+ configure(clone);
+ clone.setURI(url);
+ clone.setDirectory(generator.getDirectory());
+ clone.setGitDir(gitDir);
+ clone.setRelativePaths(true);
+ if (monitor != null) {
+ clone.setProgressMonitor(monitor);
+ }
+ repository = clone.call().getRepository();
+ cloned = true;
+ clonedRestored = true;
}
- repository = clone.call().getRepository();
- } else if (this.fetch) {
+ }
+ if ((this.fetch || restored) && !cloned) {
if (fetchCallback != null) {
fetchCallback.fetchingSubmodule(generator.getPath());
}
@@ -171,15 +227,17 @@ public class SubmoduleUpdateCommand extends
continue;
// Skip submodules not registered in parent repository's config
String url = generator.getConfigUrl();
- if (url == null)
+ if (url == null) {
continue;
-
+ }
+ clonedRestored = false;
try (Repository submoduleRepo = getOrCloneSubmodule(generator,
url); RevWalk walk = new RevWalk(submoduleRepo)) {
RevCommit commit = walk
.parseCommit(generator.getObjectId());
- String update = generator.getConfigUpdate();
+ String update = determineUpdateMode(
+ generator.getConfigUpdate());
if (ConfigConstants.CONFIG_KEY_MERGE.equals(update)) {
MergeCommand merge = new MergeCommand(submoduleRepo);
merge.include(commit);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
index 58c18b38d1..cc8589fa1c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
@@ -18,14 +18,11 @@ import org.eclipse.jgit.api.errors.InvalidTagNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
-import org.eclipse.jgit.api.errors.ServiceUnavailableException;
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GpgConfig;
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
-import org.eclipse.jgit.lib.GpgObjectSigner;
-import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
@@ -33,7 +30,8 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.lib.Signer;
+import org.eclipse.jgit.lib.Signers;
import org.eclipse.jgit.lib.TagBuilder;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -51,13 +49,11 @@ import org.eclipse.jgit.transport.CredentialsProvider;
* </pre>
* <p>
*
- * <p>
* Create a new unannotated tag for the current commit:
*
* <pre>
* git.tag().setName(&quot;v1.0&quot;).setAnnotated(false).call();
* </pre>
- * <p>
*
* @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html"
* >Git documentation about Tag</a>
@@ -82,7 +78,7 @@ public class TagCommand extends GitCommand<Ref> {
private GpgConfig gpgConfig;
- private GpgObjectSigner gpgSigner;
+ private Signer signer;
private CredentialsProvider credentialsProvider;
@@ -110,9 +106,7 @@ public class TagCommand extends GitCommand<Ref> {
public Ref call() throws GitAPIException, ConcurrentRefUpdateException,
InvalidTagNameException, NoHeadException {
checkCallable();
-
- RepositoryState state = repo.getRepositoryState();
- processOptions(state);
+ processOptions();
try (RevWalk revWalk = new RevWalk(repo)) {
// if no id is set, we should attempt to use HEAD
@@ -138,9 +132,9 @@ public class TagCommand extends GitCommand<Ref> {
newTag.setTagger(tagger);
newTag.setObjectId(id);
- if (gpgSigner != null) {
- gpgSigner.signObject(newTag, signingKey, tagger,
- credentialsProvider, gpgConfig);
+ if (signer != null) {
+ signer.signObject(repo, gpgConfig, newTag, tagger, signingKey,
+ credentialsProvider);
}
// write the tag object
@@ -199,20 +193,14 @@ public class TagCommand extends GitCommand<Ref> {
* Sets default values for not explicitly specified options. Then validates
* that all required data has been provided.
*
- * @param state
- * the state of the repository we are working on
- *
* @throws InvalidTagNameException
* if the tag name is null or invalid
- * @throws ServiceUnavailableException
- * if the tag should be signed but no signer can be found
* @throws UnsupportedSigningFormatException
* if the tag should be signed but {@code gpg.format} is not
* {@link GpgFormat#OPENPGP}
*/
- private void processOptions(RepositoryState state)
- throws InvalidTagNameException, ServiceUnavailableException,
- UnsupportedSigningFormatException {
+ private void processOptions()
+ throws InvalidTagNameException, UnsupportedSigningFormatException {
if (name == null
|| !Repository.isValidRefName(Constants.R_TAGS + name)) {
throw new InvalidTagNameException(
@@ -238,16 +226,15 @@ public class TagCommand extends GitCommand<Ref> {
doSign = gpgConfig.isSignAnnotated();
}
if (doSign) {
- if (signingKey == null) {
- signingKey = gpgConfig.getSigningKey();
- }
- if (gpgSigner == null) {
- GpgSigner signer = GpgSigner.getDefault();
- if (!(signer instanceof GpgObjectSigner)) {
- throw new ServiceUnavailableException(
- JGitText.get().signingServiceUnavailable);
+ if (signer == null) {
+ signer = Signers.get(gpgConfig.getKeyFormat());
+ if (signer == null) {
+ throw new UnsupportedSigningFormatException(
+ MessageFormat.format(
+ JGitText.get().signatureTypeUnknown,
+ gpgConfig.getKeyFormat()
+ .toConfigValue()));
}
- gpgSigner = (GpgObjectSigner) signer;
}
// The message of a signed tag must end in a newline because
// the signature will be appended.
@@ -334,22 +321,22 @@ public class TagCommand extends GitCommand<Ref> {
}
/**
- * Sets the {@link GpgSigner} to use if the commit is to be signed.
+ * Sets the {@link Signer} to use if the commit is to be signed.
*
* @param signer
* to use; if {@code null}, the default signer will be used
* @return {@code this}
- * @since 5.11
+ * @since 7.0
*/
- public TagCommand setGpgSigner(GpgObjectSigner signer) {
+ public TagCommand setSigner(Signer signer) {
checkCallable();
- this.gpgSigner = signer;
+ this.signer = signer;
return this;
}
/**
* Sets an external {@link GpgConfig} to use. Whether it will be used is at
- * the discretion of the {@link #setGpgSigner(GpgObjectSigner)}.
+ * the discretion of the {@link #setSigner(Signer)}.
*
* @param config
* to set; if {@code null}, the config will be loaded from the
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java
index 1af880d792..30f1bc9cc6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java
@@ -22,7 +22,9 @@ import org.eclipse.jgit.transport.Transport;
* {@link org.eclipse.jgit.api.TransportConfigCallback}.
*
* @param <C>
+ * concrete type of this {@code GitCommand}
* @param <T>
+ * the return type of the {@code GitCommand}'s {@code call()} method
*/
public abstract class TransportCommand<C extends GitCommand, T> extends
GitCommand<T> {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
index 21cddf75b7..f5f4b06e45 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerificationResult.java
@@ -9,7 +9,7 @@
*/
package org.eclipse.jgit.api;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
+import org.eclipse.jgit.lib.SignatureVerifier;
import org.eclipse.jgit.revwalk.RevObject;
/**
@@ -34,8 +34,9 @@ public interface VerificationResult {
* Retrieves the signature verification result.
*
* @return the result, or {@code null} if none was computed
+ * @since 7.0
*/
- GpgSignatureVerifier.SignatureVerification getVerification();
+ SignatureVerifier.SignatureVerification getVerification();
/**
* Retrieves the git object of which the signature was verified.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
index 6a2a44ea2d..487ff04323 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/VerifySignatureCommand.java
@@ -25,11 +25,10 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GpgConfig;
-import org.eclipse.jgit.lib.GpgSignatureVerifier;
-import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
-import org.eclipse.jgit.lib.GpgSignatureVerifierFactory;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SignatureVerifier.SignatureVerification;
+import org.eclipse.jgit.lib.SignatureVerifiers;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -65,12 +64,8 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
private VerifyMode mode = VerifyMode.ANY;
- private GpgSignatureVerifier verifier;
-
private GpgConfig config;
- private boolean ownVerifier;
-
/**
* Creates a new {@link VerifySignatureCommand} for the given {@link Repository}.
*
@@ -140,22 +135,7 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
}
/**
- * Sets the {@link GpgSignatureVerifier} to use.
- *
- * @param verifier
- * the {@link GpgSignatureVerifier} to use, or {@code null} to
- * use the default verifier
- * @return {@code this}
- */
- public VerifySignatureCommand setVerifier(GpgSignatureVerifier verifier) {
- checkCallable();
- this.verifier = verifier;
- return this;
- }
-
- /**
- * Sets an external {@link GpgConfig} to use. Whether it will be used it at
- * the discretion of the {@link #setVerifier(GpgSignatureVerifier)}.
+ * Sets an external {@link GpgConfig} to use.
*
* @param config
* to set; if {@code null}, the config will be loaded from the
@@ -170,16 +150,6 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
}
/**
- * Retrieves the currently set {@link GpgSignatureVerifier}. Can be used
- * after a successful {@link #call()} to get the verifier that was used.
- *
- * @return the {@link GpgSignatureVerifier}
- */
- public GpgSignatureVerifier getVerifier() {
- return verifier;
- }
-
- /**
* {@link Repository#resolve(String) Resolves} all names added to the
* command to git objects and verifies their signature. Non-existing objects
* are ignored.
@@ -193,9 +163,6 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
*
* @return a map of the given names to the corresponding
* {@link VerificationResult}, excluding ignored or skipped objects.
- * @throws ServiceUnavailableException
- * if no {@link GpgSignatureVerifier} was set and no
- * {@link GpgSignatureVerifierFactory} is available
* @throws WrongObjectTypeException
* if a name resolves to an object of a type not allowed by the
* {@link #setMode(VerifyMode)} mode
@@ -207,16 +174,6 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
checkCallable();
setCallable(false);
Map<String, VerificationResult> result = new HashMap<>();
- if (verifier == null) {
- GpgSignatureVerifierFactory factory = GpgSignatureVerifierFactory
- .getDefault();
- if (factory == null) {
- throw new ServiceUnavailableException(
- JGitText.get().signatureVerificationUnavailable);
- }
- verifier = factory.getVerifier();
- ownVerifier = true;
- }
if (config == null) {
config = new GpgConfig(repo.getConfig());
}
@@ -239,10 +196,6 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
} catch (IOException e) {
throw new JGitInternalException(
JGitText.get().signatureVerificationError, e);
- } finally {
- if (ownVerifier) {
- verifier.clear();
- }
}
return result;
}
@@ -258,8 +211,8 @@ public class VerifySignatureCommand extends GitCommand<Map<String, VerificationR
}
if (type == Constants.OBJ_COMMIT || type == Constants.OBJ_TAG) {
try {
- GpgSignatureVerifier.SignatureVerification verification = verifier
- .verifySignature(object, config);
+ SignatureVerification verification = SignatureVerifiers
+ .verify(repo, config, object);
if (verification == null) {
// Not signed
return null;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CheckoutConflictException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CheckoutConflictException.java
index 3b71373b6e..5538711192 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CheckoutConflictException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/CheckoutConflictException.java
@@ -37,7 +37,7 @@
*/
package org.eclipse.jgit.api.errors;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -94,11 +94,12 @@ public class CheckoutConflictException extends GitAPIException {
* Adds a new conflicting path
*
* @param conflictingPath
+ * the new conflicting path
* @return {@code this}
*/
CheckoutConflictException addConflictingPath(String conflictingPath) {
if (conflictingPaths == null)
- conflictingPaths = new LinkedList<>();
+ conflictingPaths = new ArrayList<>();
conflictingPaths.add(conflictingPath);
return this;
}