aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java109
1 files changed, 69 insertions, 40 deletions
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;
}