@Override public RebaseResponse extractMessage(Repository repository) throws IOException { List<RebaseTodoLine> rebaseTodoLines = repository.readRebaseTodo(getRebasePath(repository, DONE), false); // the last rebase_todo_line RebaseTodoLine line = rebaseTodoLines.get(rebaseTodoLines.size() - 1); try (RevWalk walk = new RevWalk(repository)) { ObjectReader or = repository.newObjectReader(); RevCommit commitToPick = walk.parseCommit(or.resolve(line.getCommit()).iterator().next()); String oldMessage = commitToPick.getFullMessage(); RebaseResponse response = new RebaseResponse(false, RebaseResponse.Status.INTERACTIVE_EDIT); response.setMessage(oldMessage); return response; } }
public static void updateTodoLog(NotificationService notification, PullRequestKey request, Map<AbbreviatedObjectId, Commit> mappedCommits, List<RebaseTodoLine> steps) { for(int i = 0; i < steps.size(); i++) { RebaseTodoLine step = steps.get(i); if(!mappedCommits.containsKey(step.getCommit())) { notification.sendMessage(request, "Perform " + step.getCommit().toString() + " Action[remove]"); steps.remove(i); i--; continue; } Commit commit = mappedCommits.get(step.getCommit()); if(commit.getState() == State.DELETE) { notification.sendMessage(request, "Perform " + step.getCommit().toString() + " " + " Action[remove]"); steps.remove(i); i--; continue; } try { step.setAction(Action.parse(commit.getState().name().toLowerCase())); } catch (Exception e) { e.printStackTrace(); } notification.sendMessage(request, "Perform " + step.getCommit().toString() + " " + step.getAction()); } }
private void writeTodoFile (Repository repository, List<RebaseTodoLine> steps) throws IOException { File f = new File(repository.getDirectory(), SEQUENCER); if (f.canWrite()) { RebaseTodoFile todoFile = new RebaseTodoFile(repository); todoFile.writeRebaseTodoFile(SEQUENCER + File.separator + SEQUENCER_TODO, steps, false); } }
private List<RebaseTodoLine> readTodoFile (Repository repository) throws IOException { String path = SEQUENCER + File.separator + SEQUENCER_TODO; File f = new File(repository.getDirectory(), path); if (f.canRead()) { RebaseTodoFile todoFile = new RebaseTodoFile(repository); return todoFile.readRebaseTodo(SEQUENCER + File.separator + SEQUENCER_TODO, true); } return Collections.<RebaseTodoLine>emptyList(); }
public static List<RebaseResponse.RebaseTodoLine> loadFrom(List<RebaseTodoLine> lines) { List<RebaseResponse.RebaseTodoLine> rebaseTodoLines = new ArrayList<>(); for (RebaseTodoLine line : lines) { RebaseResponse.RebaseTodoLine rebaseTodoLine = new RebaseResponse.RebaseTodoLine( line.getAction().name(), line.getCommit().name(), line.getShortMessage()); rebaseTodoLines.add(rebaseTodoLine); } return rebaseTodoLines; }
public static List<RebaseTodoLine> parseLines(List<RebaseResponse.RebaseTodoLine> lines) { List<RebaseTodoLine> rebaseTodoLines = new ArrayList<>(); for (RebaseResponse.RebaseTodoLine line : lines) { RebaseTodoLine rebaseTodoLine = new RebaseTodoLine( RebaseTodoLine.Action.valueOf(line.getAction().name()), AbbreviatedObjectId.fromString(line.getCommit()), line.getShortMessage()); rebaseTodoLines.add(rebaseTodoLine); } return rebaseTodoLines; }
@Override protected void run () throws GitException { Repository repository = getRepository(); ObjectId originalCommit = getOriginalCommit(); ObjectId head = getHead(); List<RebaseTodoLine> steps; try { switch (operation) { case BEGIN: // initialize sequencer and cherry-pick steps if there are // more commits to cherry-pick steps = prepareCommand(head); // apply the selected steps applySteps(steps, false); break; case ABORT: // delete the sequencer and reset to the original head if (repository.getRepositoryState() == RepositoryState.CHERRY_PICKING || repository.getRepositoryState() == RepositoryState.CHERRY_PICKING_RESOLVED) { if (originalCommit == null) { // maybe the sequencer is not created in that case simply reset to HEAD originalCommit = head; } } Utils.deleteRecursively(getSequencerFolder()); if (originalCommit != null) { ResetCommand reset = new ResetCommand(repository, getClassFactory(), originalCommit.name(), GitClient.ResetType.HARD, new DelegatingGitProgressMonitor(monitor), listener); reset.execute(); } result = createCustomResult(GitCherryPickResult.CherryPickStatus.ABORTED); break; case QUIT: // used to reset the sequencer only Utils.deleteRecursively(getSequencerFolder()); switch (repository.getRepositoryState()) { case CHERRY_PICKING: // unresolved conflicts result = createResult(CherryPickResult.CONFLICT); break; case CHERRY_PICKING_RESOLVED: result = createCustomResult(GitCherryPickResult.CherryPickStatus.UNCOMMITTED); break; default: result = createCustomResult(GitCherryPickResult.CherryPickStatus.OK); break; } break; case CONTINUE: switch (repository.getRepositoryState()) { case CHERRY_PICKING: // unresolved conflicts, cannot continue result = createResult(CherryPickResult.CONFLICT); break; case CHERRY_PICKING_RESOLVED: // cannot continue without manual commit result = createCustomResult(GitCherryPickResult.CherryPickStatus.UNCOMMITTED); break; default: // read steps from sequencer and apply them // if sequencer is empty this will be a noop steps = readTodoFile(repository); applySteps(steps, true); break; } break; default: throw new IllegalStateException("Unexpected operation " + operation.name()); } } catch (GitAPIException | IOException ex) { throw new GitException(ex); } }
private void applySteps (List<RebaseTodoLine> steps, boolean skipFirstStep) throws GitAPIException, IOException { Repository repository = getRepository(); ObjectReader or = repository.newObjectReader(); CherryPickResult res = null; boolean skipped = false; List<Ref> cherryPickedRefs = new ArrayList<>(); for (Iterator<RebaseTodoLine> it = steps.iterator(); it.hasNext();) { RebaseTodoLine step = it.next(); if (step.getAction() == RebaseTodoLine.Action.PICK) { if (skipFirstStep && !skipped) { it.remove(); writeTodoFile(repository, steps); skipped = true; continue; } Collection<ObjectId> ids = or.resolve(step.getCommit()); if (ids.size() != 1) { throw new JGitInternalException("Could not resolve uniquely the abbreviated object ID"); } org.eclipse.jgit.api.CherryPickCommand command = new Git(repository).cherryPick(); command.include(ids.iterator().next()); if (workAroundStrategyIssue) { command.setStrategy(new FailuresDetectRecurciveStrategy()); } res = command.call(); if (res.getStatus() == CherryPickResult.CherryPickStatus.OK) { it.remove(); writeTodoFile(repository, steps); cherryPickedRefs.addAll(res.getCherryPickedRefs()); } else { break; } } else { it.remove(); } } if (res == null) { result = createCustomResult(GitCherryPickResult.CherryPickStatus.OK, cherryPickedRefs); } else { result = createResult(res, cherryPickedRefs); } if (steps.isEmpty()) { // sequencer no longer needed Utils.deleteRecursively(getSequencerFolder()); } }
@Override public RebaseTodoLine.Action getAction() { return RebaseTodoLine.Action.SQUASH; }
@Override public void prepareSteps(List<RebaseTodoLine> steps) { // does nothing }
@Override public RebaseTodoLine.Action getAction() { return EDIT; }
@Override public RebaseTodoLine.Action getAction() { return RebaseTodoLine.Action.REWORD; }
@Override public void prepareSteps(List<RebaseTodoLine> steps) { updateTodoLog(notification, key, mappedCommits, steps); }
public static void main(String[] args) throws IOException, GitAPIException { try (Repository repository = CookbookHelper.openJGitCookbookRepository()) { // all refs try (Git git = new Git(repository)) { InteractiveHandler handler = new InteractiveHandler() { @Override public void prepareSteps(List<RebaseTodoLine> steps) { // the handler receives the list of commits that are rebased, i.e. the ones on the local branch for(RebaseTodoLine step : steps) { // for each step, you can decide which action should be taken // default is PICK try { // by selecting "EDIT", the rebase will stop and ask you to edit the commit-contents step.setAction(Action.EDIT); } catch (IllegalTodoFileModification e) { throw new IllegalStateException(e); } } } @Override public String modifyCommitMessage(String oldMessage) { return oldMessage; } }; RebaseResult result = git.rebase().setUpstream("origin/master").runInteractively(handler).call(); System.out.println("Rebase had state: " + result.getStatus() + ": " + result.getConflicts()); // because of the "EDIT" in the InteractiveHandler, the rebase was stopped in-between // now you can adjust the commit and continue rebasing with setOperation(RebaseCommand.Operation.CONTINUE) // to use the local changes for the commit or setOperation(RebaseCommand.Operation.SKIP) to skip this // commit (i.e. remove it from the branch!) if(!result.getStatus().isSuccessful()) { // if rebasing stopped or failed, you can get back to the original state by running it with setOperation(RebaseCommand.Operation.ABORT) result = git.rebase().setUpstream("origin/master").runInteractively(handler).setOperation(RebaseCommand.Operation.ABORT).call(); System.out.println("Aborted reabse with state: " + result.getStatus() + ": " + result.getConflicts()); } } } }
RebaseTodoLine.Action getAction();