1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Maik Schreiber and others
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * Maik Schreiber - initial implementation
13 * Laurent Delaigue (Obeo) - use of preferred merge strategy
14 * Stephan Hackstedt <stephan.hackstedt@googlemail.com - Bug 477695
15 *******************************************************************************/
16 package org
.eclipse
.egit
.core
.op
;
18 import java
.text
.MessageFormat
;
19 import java
.util
.List
;
21 import org
.eclipse
.core
.resources
.IWorkspace
;
22 import org
.eclipse
.core
.resources
.IWorkspaceRunnable
;
23 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
24 import org
.eclipse
.core
.runtime
.CoreException
;
25 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
26 import org
.eclipse
.core
.runtime
.SubMonitor
;
27 import org
.eclipse
.core
.runtime
.jobs
.ISchedulingRule
;
28 import org
.eclipse
.egit
.core
.Activator
;
29 import org
.eclipse
.egit
.core
.CommitUtil
;
30 import org
.eclipse
.egit
.core
.internal
.CoreText
;
31 import org
.eclipse
.egit
.core
.internal
.job
.RuleUtil
;
32 import org
.eclipse
.egit
.core
.internal
.util
.ProjectUtil
;
33 import org
.eclipse
.jgit
.api
.Git
;
34 import org
.eclipse
.jgit
.api
.RebaseCommand
;
35 import org
.eclipse
.jgit
.api
.RebaseCommand
.InteractiveHandler
;
36 import org
.eclipse
.jgit
.api
.errors
.GitAPIException
;
37 import org
.eclipse
.jgit
.errors
.IllegalTodoFileModification
;
38 import org
.eclipse
.jgit
.lib
.AbbreviatedObjectId
;
39 import org
.eclipse
.jgit
.lib
.RebaseTodoLine
;
40 import org
.eclipse
.jgit
.lib
.Repository
;
41 import org
.eclipse
.jgit
.merge
.MergeStrategy
;
42 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
43 import org
.eclipse
.team
.core
.TeamException
;
45 /** Squashes multiple commits into one. */
46 public class SquashCommitsOperation
implements IEGitOperation
{
47 private Repository repository
;
49 private List
<RevCommit
> commits
;
51 private InteractiveHandler messageHandler
;
54 * Constructs a new squash commits operation.
57 * the repository to work on
60 * @param messageHandler
61 * handler that will be used to prompt for a commit message
63 public SquashCommitsOperation(Repository repository
,
64 List
<RevCommit
> commits
, InteractiveHandler messageHandler
) {
65 this.repository
= repository
;
66 this.commits
= CommitUtil
.sortCommits(commits
);
67 this.messageHandler
= messageHandler
;
71 public void execute(IProgressMonitor m
) throws CoreException
{
73 IWorkspaceRunnable action
= new IWorkspaceRunnable() {
75 public void run(IProgressMonitor pm
) throws CoreException
{
76 SubMonitor progress
= SubMonitor
.convert(pm
, 2);
78 progress
.subTask(MessageFormat
.format(
79 CoreText
.SquashCommitsOperation_squashing
,
80 Integer
.valueOf(commits
.size())));
82 InteractiveHandler handler
= new InteractiveHandler() {
84 public void prepareSteps(List
<RebaseTodoLine
> steps
) {
85 RevCommit firstCommit
= commits
.get(0);
86 for (RebaseTodoLine step
: steps
) {
87 if (isRelevant(step
.getCommit())) {
89 if (step
.getCommit().prefixCompare(
91 step
.setAction(RebaseTodoLine
.Action
.PICK
);
93 step
.setAction(RebaseTodoLine
.Action
.SQUASH
);
94 } catch (IllegalTodoFileModification e
) {
101 private boolean isRelevant(AbbreviatedObjectId id
) {
102 for (RevCommit commit
: commits
) {
103 if (id
.prefixCompare(commit
) == 0)
110 public String
modifyCommitMessage(String oldMessage
) {
111 return messageHandler
.modifyCommitMessage(oldMessage
);
114 try (Git git
= new Git(repository
)) {
115 RebaseCommand command
= git
.rebase()
116 .setUpstream(commits
.get(0).getParent(0))
117 .runInteractively(handler
)
118 .setOperation(RebaseCommand
.Operation
.BEGIN
);
119 MergeStrategy strategy
= Activator
.getDefault()
120 .getPreferredMergeStrategy();
121 if (strategy
!= null) {
122 command
.setStrategy(strategy
);
125 } catch (GitAPIException e
) {
126 throw new TeamException(e
.getLocalizedMessage(),
131 ProjectUtil
.refreshValidProjects(
132 ProjectUtil
.getValidOpenProjects(repository
),
133 progress
.newChild(1));
136 ResourcesPlugin
.getWorkspace().run(action
, getSchedulingRule(),
137 IWorkspace
.AVOID_UPDATE
, m
);
141 public ISchedulingRule
getSchedulingRule() {
142 return RuleUtil
.getRule(repository
);