/*
- * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2010, 2013 Mathias Kinzler <mathias.kinzler@sap.com>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
*/
public class RebaseCommand extends GitCommand<RebaseResult> {
/**
- * The name of the "rebase-merge" folder
+ * The name of the "rebase-merge" folder for interactive rebases.
*/
public static final String REBASE_MERGE = "rebase-merge"; //$NON-NLS-1$
+ /**
+ * The name of the "rebase-apply" folder for non-interactive rebases.
+ */
+ private static final String REBASE_APPLY = "rebase-apply"; //$NON-NLS-1$
+
/**
* The name of the "stopped-sha" file
*/
private final RevWalk walk;
- private final File rebaseDir;
+ private final RebaseState rebaseState;
private InteractiveHandler interactiveHandler;
protected RebaseCommand(Repository repo) {
super(repo);
walk = new RevWalk(repo);
- rebaseDir = new File(repo.getDirectory(), REBASE_MERGE);
+ rebaseState = new RebaseState(repo.getDirectory());
}
/**
case SKIP:
// fall through
case CONTINUE:
- String upstreamCommitId = readFile(rebaseDir, ONTO);
+ String upstreamCommitId = rebaseState.readFile(ONTO);
try {
- upstreamCommitName = readFile(rebaseDir, ONTO_NAME);
+ upstreamCommitName = rebaseState.readFile(ONTO_NAME);
} catch (FileNotFoundException e) {
// Fall back to commit ID if file doesn't exist (e.g. rebase
// was started by C Git)
if (operation == Operation.CONTINUE) {
newHead = continueRebase();
- File amendFile = new File(rebaseDir, AMEND);
+ File amendFile = rebaseState.getFile(AMEND);
boolean amendExists = amendFile.exists();
if (amendExists) {
FileUtils.delete(amendFile);
List<Step> steps = loadSteps();
if (isInteractive()) {
interactiveHandler.prepareSteps(steps);
- BufferedWriter fw = new BufferedWriter(
- new OutputStreamWriter(new FileOutputStream(new File(
- rebaseDir, GIT_REBASE_TODO)),
+ BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(
+ rebaseState.getFile(GIT_REBASE_TODO)),
Constants.CHARACTER_ENCODING));
fw.newLine();
try {
.setAmend(true).call();
continue;
case EDIT:
- createFile(rebaseDir, AMEND, commitToPick.name());
+ rebaseState.createFile(AMEND, commitToPick.name());
return stop(commitToPick);
}
} finally {
}
}
if (newHead != null) {
- String headName = readFile(rebaseDir, HEAD_NAME);
+ String headName = rebaseState.readFile(HEAD_NAME);
updateHead(headName, newHead);
- FileUtils.delete(rebaseDir, FileUtils.RECURSIVE);
+ FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
if (lastStepWasForward)
return RebaseResult.FAST_FORWARD_RESULT;
return RebaseResult.OK_RESULT;
if (needsCommit) {
CommitCommand commit = new Git(repo).commit();
- commit.setMessage(readFile(rebaseDir, MESSAGE));
+ commit.setMessage(rebaseState.readFile(MESSAGE));
commit.setAuthor(parseAuthor());
return commit.call();
}
}
private PersonIdent parseAuthor() throws IOException {
- File authorScriptFile = new File(rebaseDir, AUTHOR_SCRIPT);
+ File authorScriptFile = rebaseState.getFile(AUTHOR_SCRIPT);
byte[] raw;
try {
raw = IO.readFully(authorScriptFile);
private RebaseResult stop(RevCommit commitToPick) throws IOException {
PersonIdent author = commitToPick.getAuthorIdent();
String authorScript = toAuthorScript(author);
- createFile(rebaseDir, AUTHOR_SCRIPT, authorScript);
- createFile(rebaseDir, MESSAGE, commitToPick.getFullMessage());
+ rebaseState.createFile(AUTHOR_SCRIPT, authorScript);
+ rebaseState.createFile(MESSAGE, commitToPick.getFullMessage());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DiffFormatter df = new DiffFormatter(bos);
df.setRepository(repo);
df.format(commitToPick.getParent(0), commitToPick);
- createFile(rebaseDir, PATCH, new String(bos.toByteArray(),
+ rebaseState.createFile(PATCH, new String(bos.toByteArray(),
Constants.CHARACTER_ENCODING));
- createFile(rebaseDir, STOPPED_SHA, repo.newObjectReader().abbreviate(
+ rebaseState.createFile(STOPPED_SHA,
+ repo.newObjectReader()
+ .abbreviate(
commitToPick).name());
// Remove cherry pick state file created by CherryPickCommand, it's not
// needed for rebase
return;
List<String> todoLines = new ArrayList<String>();
List<String> poppedLines = new ArrayList<String>();
- File todoFile = new File(rebaseDir, GIT_REBASE_TODO);
- File doneFile = new File(rebaseDir, DONE);
+ File todoFile = rebaseState.getFile(GIT_REBASE_TODO);
+ File doneFile = rebaseState.getFile(DONE);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(todoFile), Constants.CHARACTER_ENCODING));
try {
Collections.reverse(cherryPickList);
// create the folder for the meta information
- FileUtils.mkdir(rebaseDir);
+ FileUtils.mkdir(rebaseState.getDir());
repo.writeOrigHead(headId);
- createFile(rebaseDir, REBASE_HEAD, headId.name());
- createFile(rebaseDir, HEAD_NAME, headName);
- createFile(rebaseDir, ONTO, upstreamCommit.name());
- createFile(rebaseDir, ONTO_NAME, upstreamCommitName);
- createFile(rebaseDir, INTERACTIVE, ""); //$NON-NLS-1$
+ rebaseState.createFile(REBASE_HEAD, headId.name());
+ rebaseState.createFile(HEAD_NAME, headName);
+ rebaseState.createFile(ONTO, upstreamCommit.name());
+ rebaseState.createFile(ONTO_NAME, upstreamCommitName);
+ rebaseState.createFile(INTERACTIVE, ""); //$NON-NLS-1$
BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(new File(rebaseDir, GIT_REBASE_TODO)),
+ new FileOutputStream(rebaseState.getFile(GIT_REBASE_TODO)),
Constants.CHARACTER_ENCODING));
fw.write("# Created by EGit: rebasing " + upstreamCommit.name()
+ " onto " + headId.name());
checkoutOk = checkoutCommit(upstreamCommit);
} finally {
if (!checkoutOk)
- FileUtils.delete(rebaseDir, FileUtils.RECURSIVE);
+ FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
}
monitor.endTask();
}
}
- private void createFile(File parentDir, String name, String content)
- throws IOException {
- File file = new File(parentDir, name);
- FileOutputStream fos = new FileOutputStream(file);
- try {
- fos.write(content.getBytes(Constants.CHARACTER_ENCODING));
- fos.write('\n');
- } finally {
- fos.close();
- }
- }
-
private RebaseResult abort(RebaseResult result) throws IOException {
try {
ObjectId origHead = repo.readOrigHead();
monitor.endTask();
}
try {
- String headName = readFile(rebaseDir, HEAD_NAME);
+ String headName = rebaseState.readFile(HEAD_NAME);
if (headName.startsWith(Constants.R_REFS)) {
monitor.beginTask(MessageFormat.format(
JGitText.get().resettingHead, headName),
}
}
// cleanup the files
- FileUtils.delete(rebaseDir, FileUtils.RECURSIVE);
+ FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
repo.writeCherryPickHead(null);
return result;
}
}
- private String readFile(File directory, String fileName) throws IOException {
- byte[] content = IO.readFully(new File(directory, fileName));
- // strip off the last LF
- int end = content.length;
- while (0 < end && content[end - 1] == '\n')
- end--;
- return RawParseUtils.decode(content, 0, end);
- }
-
private boolean checkoutCommit(RevCommit commit) throws IOException,
CheckoutConflictException {
try {
}
List<Step> loadSteps() throws IOException {
- byte[] buf = IO.readFully(new File(rebaseDir, GIT_REBASE_TODO));
+ byte[] buf = IO.readFully(rebaseState.getFile(GIT_REBASE_TODO));
int ptr = 0;
int tokenBegin = 0;
ArrayList<Step> r = new ArrayList<Step>();
return new PersonIdent(name, email, when, tz);
return null;
}
+
+ private static class RebaseState {
+
+ private final File repoDirectory;
+ private File dir;
+
+ public RebaseState(File repoDirectory) {
+ this.repoDirectory = repoDirectory;
+ }
+
+ public File getDir() {
+ if (dir == null) {
+ File rebaseApply = new File(repoDirectory, REBASE_APPLY);
+ if (rebaseApply.exists()) {
+ dir = rebaseApply;
+ } else {
+ File rebaseMerge = new File(repoDirectory, REBASE_MERGE);
+ dir = rebaseMerge;
+ }
+ }
+ return dir;
+ }
+
+ public String readFile(String name) throws IOException {
+ return readFile(getDir(), name);
+ }
+
+ public void createFile(String name, String content) throws IOException {
+ createFile(getDir(), name, content);
+ }
+
+ public File getFile(String name) {
+ return new File(getDir(), name);
+ }
+
+ private static String readFile(File directory, String fileName)
+ throws IOException {
+ byte[] content = IO.readFully(new File(directory, fileName));
+ // strip off the last LF
+ int end = content.length;
+ while (0 < end && content[end - 1] == '\n')
+ end--;
+ return RawParseUtils.decode(content, 0, end);
+ }
+
+ private static void createFile(File parentDir, String name,
+ String content)
+ throws IOException {
+ File file = new File(parentDir, name);
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(content.getBytes(Constants.CHARACTER_ENCODING));
+ fos.write('\n');
+ } finally {
+ fos.close();
+ }
+ }
+ }
}