This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 235267
Collapse All | Expand All

(-)a/git/nbproject/project.xml (-1 / +1 lines)
Lines 25-31 Link Here
25
                    <compile-dependency/>
25
                    <compile-dependency/>
26
                    <run-dependency>
26
                    <run-dependency>
27
                        <release-version>1</release-version>
27
                        <release-version>1</release-version>
28
                        <specification-version>1.26</specification-version>
28
                        <specification-version>1.27</specification-version>
29
                    </run-dependency>
29
                    </run-dependency>
30
                </dependency>
30
                </dependency>
31
                <dependency>
31
                <dependency>
(-)a/git/src/org/netbeans/modules/git/client/GitClient.java (+13 lines)
Lines 55-60 Link Here
55
import java.util.logging.Logger;
55
import java.util.logging.Logger;
56
import org.netbeans.libs.git.GitBlameResult;
56
import org.netbeans.libs.git.GitBlameResult;
57
import org.netbeans.libs.git.GitBranch;
57
import org.netbeans.libs.git.GitBranch;
58
import org.netbeans.libs.git.GitCherryPickResult;
59
import org.netbeans.libs.git.GitClient.CherryPickOperation;
58
import org.netbeans.libs.git.GitClient.DiffMode;
60
import org.netbeans.libs.git.GitClient.DiffMode;
59
import org.netbeans.libs.git.GitClient.RebaseOperationType;
61
import org.netbeans.libs.git.GitClient.RebaseOperationType;
60
import org.netbeans.libs.git.GitClient.ResetType;
62
import org.netbeans.libs.git.GitClient.ResetType;
Lines 172-177 Link Here
172
    private static final HashSet<String> NEED_REPOSITORY_REFRESH_COMMANDS = new HashSet<String>(Arrays.asList("add",//NOI18N // may change state, e.g. MERGING->MERGED
174
    private static final HashSet<String> NEED_REPOSITORY_REFRESH_COMMANDS = new HashSet<String>(Arrays.asList("add",//NOI18N // may change state, e.g. MERGING->MERGED
173
            "checkout", //NOI18N
175
            "checkout", //NOI18N
174
            "checkoutRevision", //NOI18N // current head changes
176
            "checkoutRevision", //NOI18N // current head changes
177
            "cherryPick", //NOI18N
175
            "commit", //NOI18N
178
            "commit", //NOI18N
176
            "createBranch", //NOI18N // should refresh set of known branches
179
            "createBranch", //NOI18N // should refresh set of known branches
177
            "createTag", //NOI18N - should refresh set of available tags
180
            "createTag", //NOI18N - should refresh set of available tags
Lines 279-284 Link Here
279
        }, "checkoutRevision", new File[] { repositoryRoot }); //NOI18N
282
        }, "checkoutRevision", new File[] { repositoryRoot }); //NOI18N
280
    }
283
    }
281
284
285
    public GitCherryPickResult cherryPick (final CherryPickOperation op, final String[] revisions, final ProgressMonitor monitor) throws GitException.MissingObjectException, GitException {
286
        return new CommandInvoker().runMethod(new Callable<GitCherryPickResult>() {
287
288
            @Override
289
            public GitCherryPickResult call () throws Exception {
290
                return delegate.cherryPick(op, revisions, monitor);
291
            }
292
        }, "cherryPick", new File[] { repositoryRoot }); //NOI18N
293
    }
294
282
    public void clean(final File[] roots, final ProgressMonitor monitor) throws GitException {
295
    public void clean(final File[] roots, final ProgressMonitor monitor) throws GitException {
283
        new CommandInvoker().runMethod(new Callable<Void>() {
296
        new CommandInvoker().runMethod(new Callable<Void>() {
284
297
(-)a/git/src/org/netbeans/modules/git/ui/branch/Bundle.properties (+1 lines)
Lines 62-64 Link Here
62
62
63
LBL_SetTrackingAction_PopupName=Set Tracked Branch...
63
LBL_SetTrackingAction_PopupName=Set Tracked Branch...
64
SelectTrackedBranchPanel.errorLabel.text=jLabel1
64
SelectTrackedBranchPanel.errorLabel.text=jLabel1
65
CherryPickPanel.jLabel1.text=Select revision to apply (cherry-pick) into HEAD
(-)aaa074f13bd1 (+188 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.git.ui.branch;
44
45
import java.awt.Dialog;
46
import java.awt.EventQueue;
47
import java.beans.PropertyChangeEvent;
48
import java.beans.PropertyChangeListener;
49
import java.io.File;
50
import java.util.logging.Level;
51
import java.util.logging.Logger;
52
import javax.swing.JButton;
53
import org.netbeans.libs.git.GitBranch;
54
import org.netbeans.libs.git.GitException;
55
import org.netbeans.libs.git.GitRevisionInfo;
56
import org.netbeans.libs.git.progress.ProgressMonitor;
57
import org.netbeans.modules.git.Git;
58
import org.netbeans.modules.git.client.GitClient;
59
import org.netbeans.modules.git.ui.repository.RevisionDialogController;
60
import org.netbeans.modules.git.utils.GitUtils;
61
import org.openide.DialogDescriptor;
62
import org.openide.DialogDisplayer;
63
import org.openide.util.HelpCtx;
64
import org.openide.util.NbBundle;
65
import static org.netbeans.modules.git.ui.branch.Bundle.*;
66
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
67
import org.netbeans.modules.versioning.util.Utils;
68
import org.openide.util.Cancellable;
69
import org.openide.util.RequestProcessor;
70
71
/**
72
 *
73
 * @author ondra
74
 */
75
public class CherryPick {
76
    private final CherryPickPanel panel;
77
    private final RevisionDialogController revisionPicker;
78
    private JButton okButton;
79
    private DialogDescriptor dd;
80
    private boolean valid;
81
    private final File repository;
82
    private final RequestProcessor.Task mergedIntoTask;
83
    private String revision;
84
85
    CherryPick (File repository, String initialRevision) {
86
        this.repository = repository;
87
        revisionPicker = new RevisionDialogController(repository, new File[] { repository }, initialRevision);
88
        revisionPicker.setMergingInto(GitUtils.HEAD);
89
        panel = new CherryPickPanel(revisionPicker.getPanel());
90
        mergedIntoTask = Utils.createTask(new MergedIntoTask());
91
    }
92
93
    String getRevision() {
94
        return revisionPicker.getRevision().getCommitId();
95
    }
96
97
    @NbBundle.Messages({
98
        "LBL_CherryPick.OKButton.text=&Apply",
99
        "# {0} - repository name", "LBL_CherryPick.title=Cherry Pick - {0}",
100
    })
101
    boolean showDialog () {
102
        okButton = new JButton(LBL_CherryPick_OKButton_text());
103
        org.openide.awt.Mnemonics.setLocalizedText(okButton, okButton.getText());
104
        dd = new DialogDescriptor(panel, Bundle.LBL_CherryPick_title(repository), true,
105
                new Object[] { okButton, DialogDescriptor.CANCEL_OPTION }, okButton, DialogDescriptor.DEFAULT_ALIGN,
106
                new HelpCtx("org.netbeans.modules.git.ui.branch.CherryPick"), null); //NOI18N
107
        enableRevisionPanel();
108
        revisionPicker.addPropertyChangeListener(new PropertyChangeListener() {
109
            @Override
110
            public void propertyChange (PropertyChangeEvent evt) {
111
                mergedIntoTask.cancel();
112
                if (evt.getPropertyName() == RevisionDialogController.PROP_VALID) {
113
                    boolean v = Boolean.TRUE.equals(evt.getNewValue());
114
                    setValid(v);
115
                    if (v) {
116
                        revision = getRevision();
117
                        mergedIntoTask.schedule(500);
118
                    }
119
                }
120
            }
121
        });
122
        Dialog d = DialogDisplayer.getDefault().createDialog(dd);
123
        d.setVisible(true);
124
        return okButton == dd.getValue();
125
    }
126
    
127
    private void enableRevisionPanel () {
128
        setValid(valid);
129
    }
130
131
    private void setValid (boolean flag) {
132
        this.valid = flag;
133
        okButton.setEnabled(flag);
134
        dd.setValid(flag);
135
        panel.lblError.setVisible(false);
136
    }
137
138
    @NbBundle.Messages({
139
        "# {0} - branch name", "CherryPickPanel.info.merged=Already part of \"{0}\"!"
140
    })
141
    private class MergedIntoTask implements Runnable, Cancellable {
142
143
        private ProgressMonitor.DefaultProgressMonitor pm;
144
        
145
        @Override
146
        public void run () {
147
            pm = new ProgressMonitor.DefaultProgressMonitor();
148
            final GitBranch activeBranch = RepositoryInfo.getInstance(repository).getActiveBranch();
149
            boolean mergedInto = false;
150
            final String rev = revision;
151
            if (activeBranch.getId().equals(rev)) {
152
                mergedInto = true;
153
            } else {
154
                GitClient client = null;
155
                try {
156
                    client = Git.getInstance().getClient(repository);
157
                    GitRevisionInfo ancestor = client.getCommonAncestor(new String[] { revision, GitUtils.HEAD }, pm);
158
                    if (ancestor != null && ancestor.getRevision().equals(rev)) {
159
                        mergedInto = true;
160
                    }
161
                } catch (GitException ex) {
162
                    Logger.getLogger(CherryPick.class.getName()).log(Level.FINE, null, ex);
163
                } finally {
164
                    if (client != null) {
165
                         client.release();
166
                    }
167
                }
168
            }
169
            final boolean merged = mergedInto;
170
            EventQueue.invokeLater(new Runnable() {
171
172
                @Override
173
                public void run () {
174
                    if (rev.equals(revision) && merged) {
175
                        panel.lblError.setText(Bundle.CherryPickPanel_info_merged(activeBranch.getName()));
176
                        panel.lblError.setVisible(true);
177
                    }
178
                }
179
            });
180
        }
181
182
        @Override
183
        public boolean cancel () {
184
            return pm != null && pm.cancel();
185
        }
186
        
187
    }
188
}
(-)aaa074f13bd1 (+367 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.git.ui.branch;
44
45
import java.io.File;
46
import java.util.Arrays;
47
import java.util.Collection;
48
import java.util.Collections;
49
import java.util.HashMap;
50
import java.util.Map;
51
import java.util.concurrent.Callable;
52
import java.util.logging.Logger;
53
import javax.swing.JButton;
54
import org.netbeans.libs.git.GitCherryPickResult;
55
import org.netbeans.libs.git.GitClient.CherryPickOperation;
56
import org.netbeans.libs.git.GitException;
57
import org.netbeans.libs.git.GitRepositoryState;
58
import org.netbeans.libs.git.GitRevisionInfo;
59
import org.netbeans.modules.git.Git;
60
import org.netbeans.modules.git.client.GitClient;
61
import org.netbeans.modules.git.client.GitClientExceptionHandler;
62
import org.netbeans.modules.git.client.GitProgressSupport;
63
import org.netbeans.modules.git.ui.actions.GitAction;
64
import org.netbeans.modules.git.ui.actions.SingleRepositoryAction;
65
import org.netbeans.modules.git.ui.commit.CommitAction;
66
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsExecutor;
67
import org.netbeans.modules.git.ui.output.OutputLogger;
68
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
69
import org.netbeans.modules.git.ui.status.StatusAction;
70
import org.netbeans.modules.git.utils.GitUtils;
71
import org.netbeans.modules.git.utils.ResultProcessor;
72
import org.netbeans.modules.versioning.spi.VCSContext;
73
import org.openide.DialogDisplayer;
74
import org.openide.NotifyDescriptor;
75
import org.openide.awt.ActionID;
76
import org.openide.awt.ActionRegistration;
77
import org.openide.awt.Mnemonics;
78
import org.openide.nodes.AbstractNode;
79
import org.openide.nodes.Children;
80
import org.openide.nodes.Node;
81
import org.openide.util.NbBundle;
82
import org.openide.util.actions.SystemAction;
83
import org.openide.util.lookup.Lookups;
84
85
/**
86
 *
87
 * @author ondra
88
 */
89
@ActionID(id = "org.netbeans.modules.git.ui.branch.CherryPickAction", category = "Git")
90
@ActionRegistration(displayName = "#LBL_CherryPickAction_Name", lazy = false)
91
@NbBundle.Messages({
92
    "LBL_CherryPickAction_Name=C&herry Pick...",
93
    "LBL_CherryPickAction_PopupName=Cherry Pick...",
94
    "CTL_CherryPickAction_continueButton_text=&Continue",
95
    "CTL_CherryPickAction_continueButton_TTtext=Continue in cherry-picking scheduled commits.",
96
    "CTL_CherryPickAction_abortButton_text=&Abort",
97
    "CTL_CherryPickAction_abortButton_TTtext=Abort interrupted cherry-picking and rollback to the original commit.",
98
    "CTL_CherryPickAction_quitButton_text=&Quit",
99
    "CTL_CherryPickAction_quitButton_TTtext=Finish the currently cherry-picked commit but do not apply any other.",
100
    "LBL_CherryPick_cherryPickingState_title=Unfinished Cherry-Pick",
101
    "# {0} - repository name", "MSG_CherryPick_cherryPickingState_text=Repository {0} seems to be in the middle of an unfinished cherry-pick.\n\n"
102
            + "You may continue with applying all scheduled commits\n"
103
            + "or abort and rollback to the state before the cherry-pick started.",
104
    "# {0} - repository name", "MSG_CherryPick_cherryPickingScheduledState_text=Repository {0} seems to be in the middle of an unfinished cherry-pick.\n\n"
105
            + "You may continue with applying all scheduled commits,\n"
106
            + "abort and rollback to the state before the cherry-pick started\n"
107
            + "or quit the cherry-pick and leave the already applied commits.",
108
    "# {0} - repository state", "MSG_CherryPickAction_notAllowed=Cherry picking not allowed in this state: \"{0}\"."
109
})
110
public class CherryPickAction extends SingleRepositoryAction {
111
112
    private static final Logger LOG = Logger.getLogger(CherryPickAction.class.getName());
113
    
114
    public void cherryPick (File repository, String preselectedRevision) {
115
        RepositoryInfo info = RepositoryInfo.getInstance(repository);
116
        info.refresh();
117
        GitRepositoryState state = info.getRepositoryState();
118
        boolean interrupted = isInterrupted(repository, state);
119
        if (state == GitRepositoryState.SAFE && !interrupted) {
120
            CherryPick cherryPick = new CherryPick(repository, preselectedRevision);
121
            if (cherryPick.showDialog()) {
122
                runCherryPick(repository, CherryPickOperation.BEGIN, new String[] { cherryPick.getRevision() });
123
            }
124
        } else if (interrupted) {
125
            // abort or continue?
126
            JButton btnContinue = new JButton();
127
            Mnemonics.setLocalizedText(btnContinue, Bundle.CTL_CherryPickAction_continueButton_text());
128
            btnContinue.setToolTipText(Bundle.CTL_CherryPickAction_continueButton_TTtext());
129
            JButton btnAbort = new JButton();
130
            Mnemonics.setLocalizedText(btnAbort, Bundle.CTL_CherryPickAction_abortButton_text());
131
            btnAbort.setToolTipText(Bundle.CTL_CherryPickAction_abortButton_TTtext());
132
            JButton btnQuit = new JButton();
133
            Mnemonics.setLocalizedText(btnQuit, Bundle.CTL_CherryPickAction_quitButton_text());
134
            btnQuit.setToolTipText(Bundle.CTL_CherryPickAction_quitButton_TTtext());
135
            Map<Object, CherryPickOperation> operations = new HashMap<>();
136
            operations.put(btnContinue, CherryPickOperation.CONTINUE);
137
            operations.put(btnQuit, CherryPickOperation.QUIT);
138
            operations.put(btnAbort, CherryPickOperation.ABORT);
139
            Object[] options = interrupted
140
                    ? new Object[] { btnContinue, btnAbort, btnQuit, NotifyDescriptor.CANCEL_OPTION }
141
                    : new Object[] { btnContinue, btnAbort, NotifyDescriptor.CANCEL_OPTION };
142
            Object value = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
143
                    interrupted
144
                            ? Bundle.MSG_CherryPick_cherryPickingScheduledState_text(repository.getName())
145
                            : Bundle.MSG_CherryPick_cherryPickingState_text(repository.getName()),
146
                    Bundle.LBL_CherryPick_cherryPickingState_title(),
147
                    NotifyDescriptor.YES_NO_CANCEL_OPTION,
148
                    NotifyDescriptor.QUESTION_MESSAGE,
149
                    options, 
150
                    btnContinue));
151
            CherryPickOperation op = operations.get(value);
152
            if (op != null) {
153
                runCherryPick(repository, op, null);
154
            }
155
        } else {
156
            GitClientExceptionHandler.annotate(Bundle.MSG_CherryPickAction_notAllowed(state));
157
        }
158
        
159
    }
160
161
    public void finish (File repository) {
162
        RepositoryInfo info = RepositoryInfo.getInstance(repository);
163
        info.refresh();
164
        if (isInterrupted(repository, info.getRepositoryState())) {
165
            cherryPick(repository, null);
166
        }
167
    }
168
169
    @Override
170
    protected void performAction (File repository, File[] roots, VCSContext context) {
171
        cherryPick(repository, null);
172
    }
173
174
    private boolean isInterrupted (File repository, GitRepositoryState state) {
175
        if (state == GitRepositoryState.CHERRY_PICKING || state == GitRepositoryState.CHERRY_PICKING_RESOLVED) {
176
            return true;
177
        }
178
        File sequencer = new File(GitUtils.getGitFolderForRoot(repository), "sequencer");
179
        String[] fileNames = sequencer.list();
180
        return fileNames != null && Arrays.asList(fileNames).contains("todo");
181
    }
182
183
    @NbBundle.Messages("MSG_CherryPickAction_progress=Cherry Picking...")
184
    private void runCherryPick (final File repository, final CherryPickOperation op, final String[] revisions) {
185
        GitProgressSupport supp = new GitProgressSupport() {
186
187
            @Override
188
            protected void perform () {
189
                try {
190
                    GitUtils.runWithoutIndexing(new Callable<Void>() {
191
                        @Override
192
                        public Void call () throws Exception {
193
                            GitClient client = getClient();
194
                            CherryPickResultProcessor rp = new CherryPickResultProcessor(client, repository, getProgressSupport());
195
                            CherryPickOperation nextAction = op;
196
                            while (nextAction != null && !isCanceled()) {
197
                                GitCherryPickResult result = client.cherryPick(nextAction, revisions, getProgressMonitor());
198
                                rp.processResult(result, nextAction);
199
                                nextAction = rp.getNextAction();
200
                            }
201
                            return null;
202
                        }
203
                    });
204
                } catch (GitException ex) {
205
                    GitClientExceptionHandler.notifyException(ex, true);
206
                } finally {
207
                    setDisplayName(NbBundle.getMessage(GitAction.class, "LBL_Progress.RefreshingStatuses")); //NOI18N
208
                    Git.getInstance().getFileStatusCache().refreshAllRoots(Collections.<File, Collection<File>>singletonMap(repository, Git.getInstance().getSeenRoots(repository)));
209
                    GitUtils.headChanged(repository);
210
                }
211
            }
212
213
            private GitProgressSupport getProgressSupport () {
214
                return this;
215
            }
216
        };
217
        supp.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.MSG_CherryPickAction_progress());
218
    }
219
    
220
    public static class CherryPickResultProcessor extends ResultProcessor {
221
222
        private final OutputLogger logger;
223
        private CherryPickOperation nextAction;
224
        private final GitProgressSupport supp;
225
        
226
        public CherryPickResultProcessor (GitClient client, File repository, GitProgressSupport supp) {
227
            super(client, repository, GitUtils.HEAD, supp.getProgressMonitor());
228
            this.logger = supp.getLogger();
229
            this.supp = supp;
230
        }
231
        
232
        @NbBundle.Messages({
233
            "# {0} - rebase status", "MSG_CherryPickAction.result=Cherry-Pick Result: {0}\n",
234
            "# {0} - head commit id", "MSG_CherryPickAction.result.aborted=Cherry-picking aborted and the current branch reset to {0}\n",
235
            "MSG_CherryPickAction.result.failed=Working tree modifications prevent from cherry-picking:\n",
236
            "MSG_CherryPickAction.result.conflict=Cherry-picking interrupted because of conflicts in:\n",
237
            "MSG_CherryPickAction.result.ok=Cherry-picking successfully finished\n"
238
        })
239
        public void processResult (GitCherryPickResult result, CherryPickOperation currentOp) {
240
            nextAction = null;
241
            StringBuilder sb = new StringBuilder(Bundle.MSG_CherryPickAction_result(result.getCherryPickStatus().toString()));
242
            GitRevisionInfo info = result.getCurrentHead();
243
            switch (result.getCherryPickStatus()) {
244
                case ABORTED:
245
                    sb.append(Bundle.MSG_CherryPickAction_result_aborted(info.getRevision()));
246
                    GitUtils.printInfo(sb, info);
247
                    break;
248
                case FAILED:
249
                    sb.append(Bundle.MSG_CherryPickAction_result_failed());
250
                    printConflicts(logger, sb, result.getFailures());
251
                    try {
252
                        if (resolveLocalChanges(result.getFailures().toArray(new File[result.getFailures().size()]))) {
253
                            nextAction = CherryPickOperation.CONTINUE;
254
                        } else if (currentOp == CherryPickOperation.BEGIN) {
255
                            nextAction = CherryPickOperation.QUIT;
256
                        }
257
                    } catch (GitException ex) {
258
                        GitClientExceptionHandler.notifyException(ex, true);
259
                    }
260
                    break;
261
                case CONFLICTING:
262
                    sb.append(Bundle.MSG_CherryPickAction_result_conflict());
263
                    printConflicts(logger, sb, result.getConflicts());
264
                    nextAction = resolveCherryPickConflicts(result.getConflicts());
265
                    break;
266
                case OK:
267
                    sb.append(Bundle.MSG_CherryPickAction_result_ok());
268
                    break;
269
                case UNCOMMITTED:
270
                    askForCommit();
271
                    break;
272
            }
273
            for (GitRevisionInfo commit : result.getCherryPickedCommits()) {
274
                GitUtils.printInfo(sb, commit);
275
            }
276
            if (sb.length() > 0) {
277
                logger.outputLine(sb.toString());
278
            }
279
        }
280
281
        public CherryPickOperation getNextAction () {
282
            return nextAction;
283
        }
284
285
        @NbBundle.Messages({
286
            "LBL_CherryPickResultProcessor.abortButton.text=&Abort",
287
            "LBL_CherryPickResultProcessor.abortButton.TTtext=Abort the interrupted process and reset back to the original commit.",
288
            "LBL_CherryPickResultProcessor.resolveButton.text=&Resolve",
289
            "LBL_CherryPickResultProcessor.resolveButton.TTtext=Files in conflict will be opened in the Resolve Conflict dialog.",
290
            "LBL_CherryPickResultProcessor.resolveConflicts=Resolve Conflicts",
291
            "MSG_CherryPickResultProcessor.resolveConflicts=Cherry-picking produced unresolved conflicts.\n"
292
                + "You can resolve them manually, review them in the Versioning view\n"
293
                + "or completely abort the process and reset back to the original state.",
294
            "LBL_CherryPickResultProcessor.revertButton.text=&Revert",
295
            "LBL_CherryPickResultProcessor.revertButton.TTtext=Revert local changes to the state in the HEAD and removes unversioned files.",
296
            "LBL_CherryPickResultProcessor.reviewButton.text=Re&view",
297
            "LBL_CherryPickResultProcessor.reviewButton.TTtext=Opens the Versioning view and lists the conflicted files.",
298
            "MSG_CherryPick.resolving=Resolving conflicts..."
299
        })
300
        private CherryPickOperation resolveCherryPickConflicts (Collection<File> conflicts) {
301
            CherryPickOperation action = null;
302
            JButton abort = new JButton();
303
            Mnemonics.setLocalizedText(abort, Bundle.LBL_CherryPickResultProcessor_abortButton_text());
304
            abort.setToolTipText(Bundle.LBL_CherryPickResultProcessor_abortButton_TTtext());
305
            JButton resolve = new JButton();
306
            Mnemonics.setLocalizedText(resolve, Bundle.LBL_CherryPickResultProcessor_resolveButton_text());
307
            resolve.setToolTipText(Bundle.LBL_CherryPickResultProcessor_resolveButton_TTtext());
308
            JButton review = new JButton();
309
            Mnemonics.setLocalizedText(review, Bundle.LBL_CherryPickResultProcessor_reviewButton_text());
310
            review.setToolTipText(Bundle.LBL_CherryPickResultProcessor_reviewButton_TTtext());
311
            Object o = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
312
                    Bundle.MSG_CherryPickResultProcessor_resolveConflicts(),
313
                    Bundle.LBL_CherryPickResultProcessor_resolveConflicts(),
314
                    NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE,
315
                    new Object[] { resolve, review, abort, NotifyDescriptor.CANCEL_OPTION }, resolve));
316
            if (o == review) {
317
                openInVersioningView(conflicts);
318
            } else if (o == resolve) {
319
                GitProgressSupport executor = new ResolveConflictsExecutor(conflicts.toArray(new File[conflicts.size()]));
320
                executor.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.MSG_CherryPick_resolving());
321
            } else if (o == abort) {
322
                action = CherryPickOperation.ABORT;
323
            }
324
            return action;
325
        }
326
327
        @NbBundle.Messages({
328
            "LBL_CherryPickResultProcessor.commit=Commit Required",
329
            "MSG_CherryPickResultProcessor.commit=Commit changes were applied into the current branch\n"
330
                    + "but a manual commit is required to make these changes permanent.\n\n"
331
                + "Do you want to commit the changes now or review them first?",
332
            "LBL_CherryPickResultProcessor.commit.commitButton.text=&Commit",
333
            "LBL_CherryPickResultProcessor.commit.commitButton.TTtext=Opens the commit dialog.",
334
            "LBL_CherryPickResultProcessor.commit.reviewButton.text=&Review",
335
            "LBL_CherryPickResultProcessor.commit.reviewButton.TTtext=Review the changes in the status window."
336
        })
337
        private void askForCommit () {
338
            JButton commit = new JButton();
339
            Mnemonics.setLocalizedText(commit, Bundle.LBL_CherryPickResultProcessor_commit_commitButton_text());
340
            commit.setToolTipText(Bundle.LBL_CherryPickResultProcessor_commit_commitButton_TTtext());
341
            JButton review = new JButton();
342
            Mnemonics.setLocalizedText(review, Bundle.LBL_CherryPickResultProcessor_commit_reviewButton_text());
343
            review.setToolTipText(Bundle.LBL_CherryPickResultProcessor_commit_reviewButton_TTtext());
344
            Object o = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
345
                    Bundle.MSG_CherryPickResultProcessor_commit(),
346
                    Bundle.LBL_CherryPickResultProcessor_commit(),
347
                    NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE,
348
                    new Object[] { commit, review, NotifyDescriptor.CANCEL_OPTION }, commit));
349
            VCSContext context = VCSContext.forNodes(new Node[] {
350
                new AbstractNode(Children.LEAF, Lookups.fixed(repository)) {
351
352
                    @Override
353
                    public String getName () {
354
                        return repository.getName();
355
                    }
356
                }
357
            });
358
            if (o == commit) {
359
                SystemAction.get(CommitAction.class).performAction(context);
360
            } else if (o == review) {
361
                SystemAction.get(StatusAction.class).performContextAction(context);
362
            }
363
        }
364
        
365
    }
366
367
}
(-)aaa074f13bd1 (+77 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8" ?>
2
3
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
4
  <NonVisualComponents>
5
    <Component class="javax.swing.ButtonGroup" name="rbFFOptions">
6
    </Component>
7
  </NonVisualComponents>
8
  <AuxValues>
9
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
10
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
11
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
12
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
13
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
14
    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
15
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
16
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
17
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
18
  </AuxValues>
19
20
  <Layout>
21
    <DimensionLayout dim="0">
22
      <Group type="103" groupAlignment="0" attributes="0">
23
          <Component id="revisionPickerDialog1" alignment="1" max="32767" attributes="0"/>
24
          <Group type="102" attributes="0">
25
              <EmptySpace max="-2" attributes="0"/>
26
              <Group type="103" groupAlignment="0" attributes="0">
27
                  <Group type="102" attributes="0">
28
                      <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
29
                      <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
30
                  </Group>
31
                  <Component id="lblError" max="32767" attributes="0"/>
32
              </Group>
33
              <EmptySpace max="-2" attributes="0"/>
34
          </Group>
35
      </Group>
36
    </DimensionLayout>
37
    <DimensionLayout dim="1">
38
      <Group type="103" groupAlignment="0" attributes="0">
39
          <Group type="102" alignment="0" attributes="0">
40
              <EmptySpace max="-2" attributes="0"/>
41
              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
42
              <EmptySpace max="-2" attributes="0"/>
43
              <Component id="revisionPickerDialog1" max="32767" attributes="0"/>
44
              <EmptySpace max="-2" attributes="0"/>
45
              <Component id="lblError" min="-2" max="-2" attributes="0"/>
46
              <EmptySpace max="-2" attributes="0"/>
47
          </Group>
48
      </Group>
49
    </DimensionLayout>
50
  </Layout>
51
  <SubComponents>
52
    <Component class="org.netbeans.modules.git.ui.repository.RevisionDialog" name="revisionPickerDialog1">
53
      <AuxValues>
54
        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="this.revisionPanel"/>
55
        <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
56
        <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
57
      </AuxValues>
58
    </Component>
59
    <Component class="javax.swing.JLabel" name="jLabel1">
60
      <Properties>
61
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
62
          <ResourceString bundle="org/netbeans/modules/git/ui/branch/Bundle.properties" key="CherryPickPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
63
        </Property>
64
      </Properties>
65
    </Component>
66
    <Component class="javax.swing.JLabel" name="lblError">
67
      <Properties>
68
        <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
69
          <Image iconType="3" name="/org/netbeans/modules/git/resources/icons/info.png"/>
70
        </Property>
71
      </Properties>
72
      <AuxValues>
73
        <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="16"/>
74
      </AuxValues>
75
    </Component>
76
  </SubComponents>
77
</Form>
(-)aaa074f13bd1 (+117 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
43
/*
44
 * MergeRevisionPanel.java
45
 *
46
 * Created on Jan 18, 2011, 10:50:16 AM
47
 */
48
49
package org.netbeans.modules.git.ui.branch;
50
51
import org.netbeans.modules.git.ui.repository.RevisionDialog;
52
53
/**
54
 *
55
 * @author ondra
56
 */
57
public class CherryPickPanel extends javax.swing.JPanel {
58
    private final RevisionDialog revisionPanel;
59
60
    /** Creates new form MergeRevisionPanel */
61
    public CherryPickPanel (RevisionDialog revisionPanel) {
62
        this.revisionPanel = revisionPanel;
63
        initComponents();
64
    }
65
66
    /** This method is called from within the constructor to
67
     * initialize the form.
68
     * WARNING: Do NOT modify this code. The content of this method is
69
     * always regenerated by the Form Editor.
70
     */
71
    @SuppressWarnings("unchecked")
72
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
73
    private void initComponents() {
74
75
        rbFFOptions = new javax.swing.ButtonGroup();
76
        org.netbeans.modules.git.ui.repository.RevisionDialog revisionPickerDialog1 = this.revisionPanel;
77
        jLabel1 = new javax.swing.JLabel();
78
79
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CherryPickPanel.class, "CherryPickPanel.jLabel1.text")); // NOI18N
80
81
        lblError.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/git/resources/icons/info.png"))); // NOI18N
82
83
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
84
        this.setLayout(layout);
85
        layout.setHorizontalGroup(
86
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
87
            .addComponent(revisionPickerDialog1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
88
            .addGroup(layout.createSequentialGroup()
89
                .addContainerGap()
90
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
91
                    .addGroup(layout.createSequentialGroup()
92
                        .addComponent(jLabel1)
93
                        .addGap(0, 0, Short.MAX_VALUE))
94
                    .addComponent(lblError, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
95
                .addContainerGap())
96
        );
97
        layout.setVerticalGroup(
98
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
99
            .addGroup(layout.createSequentialGroup()
100
                .addContainerGap()
101
                .addComponent(jLabel1)
102
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
103
                .addComponent(revisionPickerDialog1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
104
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
105
                .addComponent(lblError)
106
                .addContainerGap())
107
        );
108
    }// </editor-fold>//GEN-END:initComponents
109
110
111
    // Variables declaration - do not modify//GEN-BEGIN:variables
112
    private javax.swing.JLabel jLabel1;
113
    final javax.swing.JLabel lblError = new javax.swing.JLabel();
114
    private javax.swing.ButtonGroup rbFFOptions;
115
    // End of variables declaration//GEN-END:variables
116
117
}
(-)a/git/src/org/netbeans/modules/git/ui/commit/CommitAction.java (-4 / +12 lines)
Lines 80-85 Link Here
80
import org.netbeans.modules.git.ui.commit.GitCommitPanel.GitCommitPanelMerged;
80
import org.netbeans.modules.git.ui.commit.GitCommitPanel.GitCommitPanelMerged;
81
import org.netbeans.modules.git.GitFileNode.GitLocalFileNode;
81
import org.netbeans.modules.git.GitFileNode.GitLocalFileNode;
82
import org.netbeans.modules.git.ui.actions.GitAction;
82
import org.netbeans.modules.git.ui.actions.GitAction;
83
import org.netbeans.modules.git.ui.branch.CherryPickAction;
83
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
84
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
84
import org.netbeans.modules.git.utils.GitUtils;
85
import org.netbeans.modules.git.utils.GitUtils;
85
import org.netbeans.modules.versioning.hooks.GitHook;
86
import org.netbeans.modules.versioning.hooks.GitHook;
Lines 141-147 Link Here
141
            @Override
142
            @Override
142
            public void run() {
143
            public void run() {
143
                
144
                
144
                GitCommitPanel panel = state == GitRepositoryState.MERGING_RESOLVED
145
                GitCommitPanel panel = state == GitRepositoryState.MERGING_RESOLVED || state == GitRepositoryState.CHERRY_PICKING_RESOLVED
145
                        ? GitCommitPanelMerged.create(roots, repository, user, mergeCommitMessage)
146
                        ? GitCommitPanelMerged.create(roots, repository, user, mergeCommitMessage)
146
                        : GitCommitPanel.create(roots, repository, user, isFromGitView(context));
147
                        : GitCommitPanel.create(roots, repository, user, isFromGitView(context));
147
                VCSCommitTable<GitLocalFileNode> table = panel.getCommitTable();
148
                VCSCommitTable<GitLocalFileNode> table = panel.getCommitTable();
Lines 182-188 Link Here
182
183
183
    private String getMergeCommitMessage (File repository, GitRepositoryState state) {
184
    private String getMergeCommitMessage (File repository, GitRepositoryState state) {
184
        String message = null;
185
        String message = null;
185
        if (EnumSet.of(GitRepositoryState.MERGING, GitRepositoryState.MERGING_RESOLVED).contains(state)) {
186
        if (EnumSet.of(GitRepositoryState.MERGING, GitRepositoryState.MERGING_RESOLVED,
187
                GitRepositoryState.CHERRY_PICKING, GitRepositoryState.CHERRY_PICKING_RESOLVED).contains(state)) {
186
            File f = new File(GitUtils.getGitFolderForRoot(repository), "MERGE_MSG"); //NOI18N
188
            File f = new File(GitUtils.getGitFolderForRoot(repository), "MERGE_MSG"); //NOI18N
187
            try {
189
            try {
188
                message = new String(FileUtils.getFileContentsAsByteArray(f), "UTF-8"); //NOI18N
190
                message = new String(FileUtils.getFileContentsAsByteArray(f), "UTF-8"); //NOI18N
Lines 245-250 Link Here
245
                    String origMessage = message;
247
                    String origMessage = message;
246
                    message = beforeCommitHook(commitCandidates, hooks, message);
248
                    message = beforeCommitHook(commitCandidates, hooks, message);
247
249
250
                    GitRepositoryState prevState = RepositoryInfo.getInstance(getRepositoryRoot()).getRepositoryState();
248
                    GitRevisionInfo info = commit(commitCandidates, message, author, commiter, amend);
251
                    GitRevisionInfo info = commit(commitCandidates, message, author, commiter, amend);
249
252
250
                    GitModuleConfig.getDefault().putRecentCommitAuthors(GitCommitParameters.getUserString(author));
253
                    GitModuleConfig.getDefault().putRecentCommitAuthors(GitCommitParameters.getUserString(author));
Lines 256-261 Link Here
256
                        LOG.log(Level.INFO, null, ex);
259
                        LOG.log(Level.INFO, null, ex);
257
                    }
260
                    }
258
                    afterCommitHook(commitCandidates, hooks, info, origMessage);
261
                    afterCommitHook(commitCandidates, hooks, info, origMessage);
262
                    if (prevState == GitRepositoryState.CHERRY_PICKING_RESOLVED) {
263
                        // should continue with cherry-picking
264
                        SystemAction.get(CherryPickAction.class).finish(getRepositoryRoot());
265
                    }
259
266
260
                } catch (GitException ex) {
267
                } catch (GitException ex) {
261
                    GitClientExceptionHandler.notifyException(ex, true);
268
                    GitClientExceptionHandler.notifyException(ex, true);
Lines 348-354 Link Here
348
        private GitRevisionInfo commit (Collection<File> commitCandidates, String message, GitUser author, GitUser commiter, boolean amend) throws GitException {
355
        private GitRevisionInfo commit (Collection<File> commitCandidates, String message, GitUser author, GitUser commiter, boolean amend) throws GitException {
349
            try {
356
            try {
350
                GitRevisionInfo info = getClient().commit(
357
                GitRevisionInfo info = getClient().commit(
351
                        state == GitRepositoryState.MERGING_RESOLVED ? new File[0] : commitCandidates.toArray(new File[commitCandidates.size()]),
358
                        state == GitRepositoryState.MERGING_RESOLVED || state == GitRepositoryState.CHERRY_PICKING_RESOLVED
359
                                ? new File[0] : commitCandidates.toArray(new File[commitCandidates.size()]),
352
                        message, author, commiter, amend, getProgressMonitor());
360
                        message, author, commiter, amend, getProgressMonitor());
353
                printInfo(info);
361
                printInfo(info);
354
                return info;
362
                return info;
Lines 388-394 Link Here
388
        if (!state.canCommit()) {
396
        if (!state.canCommit()) {
389
            commitPermitted = false;
397
            commitPermitted = false;
390
            Map<File, GitStatus> conflicts = Collections.emptyMap();
398
            Map<File, GitStatus> conflicts = Collections.emptyMap();
391
            if (state.equals(GitRepositoryState.MERGING)) {
399
            if (state.equals(GitRepositoryState.MERGING) || state.equals(GitRepositoryState.CHERRY_PICKING)) {
392
                GitClient client = null;
400
                GitClient client = null;
393
                try {
401
                try {
394
                    client = Git.getInstance().getClient(repository);
402
                    client = Git.getInstance().getClient(repository);
(-)a/git/src/org/netbeans/modules/git/ui/history/RepositoryRevision.java (+27 lines)
Lines 67-75 Link Here
67
import org.netbeans.modules.git.Git;
67
import org.netbeans.modules.git.Git;
68
import org.netbeans.modules.git.client.GitClientExceptionHandler;
68
import org.netbeans.modules.git.client.GitClientExceptionHandler;
69
import org.netbeans.modules.git.client.GitProgressSupport;
69
import org.netbeans.modules.git.client.GitProgressSupport;
70
import org.netbeans.modules.git.ui.branch.CherryPickAction;
70
import org.netbeans.modules.git.ui.checkout.CheckoutRevisionAction;
71
import org.netbeans.modules.git.ui.checkout.CheckoutRevisionAction;
71
import org.netbeans.modules.git.ui.checkout.RevertChangesAction;
72
import org.netbeans.modules.git.ui.checkout.RevertChangesAction;
72
import org.netbeans.modules.git.ui.diff.ExportCommitAction;
73
import org.netbeans.modules.git.ui.diff.ExportCommitAction;
74
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
73
import org.netbeans.modules.git.ui.revert.RevertCommitAction;
75
import org.netbeans.modules.git.ui.revert.RevertCommitAction;
74
import org.netbeans.modules.git.ui.tag.CreateTagAction;
76
import org.netbeans.modules.git.ui.tag.CreateTagAction;
75
import org.netbeans.modules.git.utils.GitUtils;
77
import org.netbeans.modules.git.utils.GitUtils;
Lines 232-237 Link Here
232
            }
234
            }
233
        });
235
        });
234
        if (getLog().getParents().length < 2) {
236
        if (getLog().getParents().length < 2) {
237
            if (!isInCurrentBranch()) {
238
                actions.add(new AbstractAction(NbBundle.getMessage(CherryPickAction.class, "LBL_CherryPickAction_PopupName")) { //NOI18N
239
                    @Override
240
                    public void actionPerformed (ActionEvent e) {
241
                        final String revision = getLog().getRevision();
242
                        Utils.post(new Runnable() {
243
244
                            @Override
245
                            public void run () {
246
                                SystemAction.get(CherryPickAction.class).cherryPick(repositoryRoot, revision);
247
                            }
248
                        });
249
                    }
250
                });
251
            }
235
            actions.add(new AbstractAction(NbBundle.getMessage(ExportCommitAction.class, "LBL_ExportCommitAction_PopupName")) { //NOI18N
252
            actions.add(new AbstractAction(NbBundle.getMessage(ExportCommitAction.class, "LBL_ExportCommitAction_PopupName")) { //NOI18N
236
                @Override
253
                @Override
237
                public void actionPerformed (ActionEvent e) {
254
                public void actionPerformed (ActionEvent e) {
Lines 278-283 Link Here
278
        return preferredRevision;
295
        return preferredRevision;
279
    }
296
    }
280
    
297
    
298
    private boolean isInCurrentBranch () {
299
        GitBranch activeBranch = RepositoryInfo.getInstance(repositoryRoot).getActiveBranch();
300
        for (GitBranch b : getLog().getBranches().values()) {
301
            if (activeBranch.getName().equals(b.getName()) || activeBranch.getId().equals(b.getId())) {
302
                return true;
303
            }
304
        }
305
        return false;
306
    }
307
    
281
    public class Event implements Comparable<Event> {
308
    public class Event implements Comparable<Event> {
282
        /**
309
        /**
283
         * The file or folder that this event is about. It may be null if the File cannot be computed.
310
         * The file or folder that this event is about. It may be null if the File cannot be computed.
(-)a/git/src/org/netbeans/modules/git/ui/menu/BranchMenu.java (+9 lines)
Lines 52-57 Link Here
52
import javax.swing.JMenuItem;
52
import javax.swing.JMenuItem;
53
import org.netbeans.libs.git.GitBranch;
53
import org.netbeans.libs.git.GitBranch;
54
import org.netbeans.modules.git.Annotator;
54
import org.netbeans.modules.git.Annotator;
55
import org.netbeans.modules.git.ui.branch.CherryPickAction;
55
import org.netbeans.modules.git.ui.branch.CreateBranchAction;
56
import org.netbeans.modules.git.ui.branch.CreateBranchAction;
56
import org.netbeans.modules.git.ui.branch.SetTrackingAction;
57
import org.netbeans.modules.git.ui.branch.SetTrackingAction;
57
import org.netbeans.modules.git.ui.checkout.AbstractCheckoutAction;
58
import org.netbeans.modules.git.ui.checkout.AbstractCheckoutAction;
Lines 140-145 Link Here
140
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
141
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
141
            Actions.connect(item, action, false);
142
            Actions.connect(item, action, false);
142
            menu.add(item);
143
            menu.add(item);
144
            
145
            item = new JMenuItem();
146
            action = (Action) SystemAction.get(CherryPickAction.class);
147
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
148
            Actions.connect(item, action, false);
149
            menu.add(item);
143
        } else {
150
        } else {
144
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(CreateBranchAction.class), NbBundle.getMessage(CreateBranchAction.class, "LBL_CreateBranchAction_PopupName"), lkp)); //NOI18N
151
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(CreateBranchAction.class), NbBundle.getMessage(CreateBranchAction.class, "LBL_CreateBranchAction_PopupName"), lkp)); //NOI18N
145
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
152
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
Lines 181-186 Link Here
181
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
188
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
182
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(RebaseAction.class), NbBundle.getMessage(RebaseAction.class, "LBL_RebaseAction_PopupName"), lkp)); //NOI18N
189
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(RebaseAction.class), NbBundle.getMessage(RebaseAction.class, "LBL_RebaseAction_PopupName"), lkp)); //NOI18N
183
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
190
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
191
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(CherryPickAction.class), NbBundle.getMessage(CherryPickAction.class, "LBL_CherryPickAction_PopupName"), lkp)); //NOI18N
192
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
184
        }        
193
        }        
185
        return menu;
194
        return menu;
186
    }
195
    }
(-)a/git/src/org/netbeans/modules/git/ui/repository/RevisionInfoPanelController.java (-1 / +5 lines)
Lines 120-127 Link Here
120
        if (!panel.tbAuthor.getText().isEmpty()) {
120
        if (!panel.tbAuthor.getText().isEmpty()) {
121
            panel.tbAuthor.setCaretPosition(0);
121
            panel.tbAuthor.setCaretPosition(0);
122
        }
122
        }
123
        String id = info.getRevision();
124
        if (id.length() > 10) {
125
            id = id.substring(0, 10);
126
        }
123
        if (revision.equals(info.getRevision())) {
127
        if (revision.equals(info.getRevision())) {
124
            panel.tbRevisionId.setText(new StringBuilder(info.getRevision()).append(getMergedStatus(revisionMerged)).toString());
128
            panel.tbRevisionId.setText(new StringBuilder(id).append(getMergedStatus(revisionMerged)).toString());
125
            this.info = new Revision(revision, revision, info.getShortMessage(), info.getFullMessage());
129
            this.info = new Revision(revision, revision, info.getShortMessage(), info.getFullMessage());
126
        } else {
130
        } else {
127
            this.info = new Revision(info.getRevision(), revision, info.getShortMessage(), info.getFullMessage());
131
            this.info = new Revision(info.getRevision(), revision, info.getShortMessage(), info.getFullMessage());
(-)a/git/test/unit/src/org/netbeans/modules/git/GitClientTest.java (+5 lines)
Lines 111-116 Link Here
111
                "catIndexEntry",
111
                "catIndexEntry",
112
                "checkout",
112
                "checkout",
113
                "checkoutRevision",
113
                "checkoutRevision",
114
                "cherryPick",
114
                "clean",
115
                "clean",
115
                "commit",
116
                "commit",
116
                "copyAfter",
117
                "copyAfter",
Lines 227-232 Link Here
227
                "catIndexEntry",
228
                "catIndexEntry",
228
                "checkout",
229
                "checkout",
229
                "checkoutRevision",
230
                "checkoutRevision",
231
                "cherryPick",
230
                "clean",
232
                "clean",
231
                "commit",
233
                "commit",
232
                "copyAfter",
234
                "copyAfter",
Lines 276-281 Link Here
276
        Set<String> expectedMethods = new HashSet<String>(Arrays.asList(
278
        Set<String> expectedMethods = new HashSet<String>(Arrays.asList(
277
                "checkout",
279
                "checkout",
278
                "checkoutRevision",
280
                "checkoutRevision",
281
                "cherryPick",
279
                "commit",
282
                "commit",
280
                "createBranch",
283
                "createBranch",
281
                "createTag",
284
                "createTag",
Lines 330-335 Link Here
330
                "catIndexEntry",
333
                "catIndexEntry",
331
                "checkout",
334
                "checkout",
332
                "checkoutRevision",
335
                "checkoutRevision",
336
                "cherryPick",
333
                "clean",
337
                "clean",
334
                "commit",
338
                "commit",
335
                "copyAfter",
339
                "copyAfter",
Lines 505-510 Link Here
505
                "catIndexEntry",
509
                "catIndexEntry",
506
                "checkout",
510
                "checkout",
507
                "checkoutRevision",
511
                "checkoutRevision",
512
                "cherryPick",
508
                "clean",
513
                "clean",
509
                "commit",
514
                "commit",
510
                "copyAfter",
515
                "copyAfter",

Return to bug 235267