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 226545
Collapse All | Expand All

(-)a/bugtracking.bridge/nbproject/project.xml (-1 / +1 lines)
Lines 63-69 Link Here
63
                    <build-prerequisite/>
63
                    <build-prerequisite/>
64
                    <compile-dependency/>
64
                    <compile-dependency/>
65
                    <run-dependency>
65
                    <run-dependency>
66
                        <specification-version>1.39</specification-version>
66
                        <specification-version>1.40</specification-version>
67
                    </run-dependency>
67
                    </run-dependency>
68
                </dependency>
68
                </dependency>
69
                <dependency>
69
                <dependency>
(-)a/bugtracking.bridge/src/org/netbeans/modules/bugtracking/vcs/GitHookImpl.java (+6 lines)
Lines 44-49 Link Here
44
44
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.util.Date;
46
import java.util.Date;
47
import java.util.Map;
47
import javax.swing.JPanel;
48
import javax.swing.JPanel;
48
import org.netbeans.modules.versioning.hooks.GitHook;
49
import org.netbeans.modules.versioning.hooks.GitHook;
49
import org.netbeans.modules.versioning.hooks.GitHookContext;
50
import org.netbeans.modules.versioning.hooks.GitHookContext;
Lines 109-113 Link Here
109
    public String getDisplayName() {
110
    public String getDisplayName() {
110
        return name;
111
        return name;
111
    }
112
    }
113
    
114
    @Override
115
    public void afterCommitReplace (GitHookContext originalContext, GitHookContext newContext, Map<String, String> mapping) {
116
        delegate.afterChangesetReplace(newContext.getFiles(), mapping, "GIT");
117
    }
112
118
113
}
119
}
(-)a/git/nbproject/project.xml (-2 / +2 lines)
Lines 20-26 Link Here
20
                    <compile-dependency/>
20
                    <compile-dependency/>
21
                    <run-dependency>
21
                    <run-dependency>
22
                        <release-version>1</release-version>
22
                        <release-version>1</release-version>
23
                        <specification-version>1.7</specification-version>
23
                        <specification-version>1.8</specification-version>
24
                    </run-dependency>
24
                    </run-dependency>
25
                </dependency>
25
                </dependency>
26
                <dependency>
26
                <dependency>
Lines 135-141 Link Here
135
                    <build-prerequisite/>
135
                    <build-prerequisite/>
136
                    <compile-dependency/>
136
                    <compile-dependency/>
137
                    <run-dependency>
137
                    <run-dependency>
138
                        <specification-version>1.37</specification-version>
138
                        <specification-version>1.40</specification-version>
139
                    </run-dependency>
139
                    </run-dependency>
140
                </dependency>
140
                </dependency>
141
                <dependency>
141
                <dependency>
(-)a/git/src/org/netbeans/modules/git/client/GitClient.java (+13 lines)
Lines 56-61 Link Here
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.GitClient.DiffMode;
58
import org.netbeans.libs.git.GitClient.DiffMode;
59
import org.netbeans.libs.git.GitClient.RebaseOperationType;
59
import org.netbeans.libs.git.GitClient.ResetType;
60
import org.netbeans.libs.git.GitClient.ResetType;
60
import org.netbeans.libs.git.GitClientCallback;
61
import org.netbeans.libs.git.GitClientCallback;
61
import org.netbeans.libs.git.GitRepository;
62
import org.netbeans.libs.git.GitRepository;
Lines 63-68 Link Here
63
import org.netbeans.libs.git.GitMergeResult;
64
import org.netbeans.libs.git.GitMergeResult;
64
import org.netbeans.libs.git.GitPullResult;
65
import org.netbeans.libs.git.GitPullResult;
65
import org.netbeans.libs.git.GitPushResult;
66
import org.netbeans.libs.git.GitPushResult;
67
import org.netbeans.libs.git.GitRebaseResult;
66
import org.netbeans.libs.git.GitRemoteConfig;
68
import org.netbeans.libs.git.GitRemoteConfig;
67
import org.netbeans.libs.git.GitRepositoryState;
69
import org.netbeans.libs.git.GitRepositoryState;
68
import org.netbeans.libs.git.GitRevertResult;
70
import org.netbeans.libs.git.GitRevertResult;
Lines 170-175 Link Here
170
            "fetch", //NOI18N - changes available remote heads or tags
172
            "fetch", //NOI18N - changes available remote heads or tags
171
            "merge", //NOI18N // creates a new head
173
            "merge", //NOI18N // creates a new head
172
            "pull", //NOI18N // creates a new head
174
            "pull", //NOI18N // creates a new head
175
            "rebase", //NOI18N // creates new head and branches
173
            "remove", //NOI18N // may change state, e.g. MERGING->MERGED
176
            "remove", //NOI18N // may change state, e.g. MERGING->MERGED
174
            "reset", //NOI18N
177
            "reset", //NOI18N
175
            "removeRemote", //NOI18N - updates remotes
178
            "removeRemote", //NOI18N - updates remotes
Lines 585-590 Link Here
585
        }, "push"); //NOI18N
588
        }, "push"); //NOI18N
586
    }
589
    }
587
    
590
    
591
    public GitRebaseResult rebase (final RebaseOperationType operation, final String upstream, final ProgressMonitor monitor) throws GitException.AuthorizationException, GitException {
592
        return new CommandInvoker().runMethod(new Callable<GitRebaseResult>() {
593
594
            @Override
595
            public GitRebaseResult call () throws Exception {
596
                return delegate.rebase(operation, upstream, monitor);
597
            }
598
        }, "rebase"); //NOI18N
599
    }
600
    
588
    /**
601
    /**
589
     * Schedule cleanup of git repository used by this client
602
     * Schedule cleanup of git repository used by this client
590
     */
603
     */
(-)a/git/src/org/netbeans/modules/git/client/GitProgressSupport.java (-1 / +1 lines)
Lines 189-195 Link Here
189
        return repositoryRoot;
189
        return repositoryRoot;
190
    }
190
    }
191
191
192
    protected void setProgress (String progressMessage) {
192
    public void setProgress (String progressMessage) {
193
        if (progressHandle != null) {
193
        if (progressHandle != null) {
194
            setProgressMessage(progressHandle, progressMessage == null ? displayName
194
            setProgressMessage(progressHandle, progressMessage == null ? displayName
195
                    : NbBundle.getMessage(GitProgressSupport.class, "LBL_Progress", new Object[] { displayName, progressMessage })); // NOI18N
195
                    : NbBundle.getMessage(GitProgressSupport.class, "LBL_Progress", new Object[] { displayName, progressMessage })); // NOI18N
(-)a/git/src/org/netbeans/modules/git/ui/commit/CommitAction.java (-1 / +1 lines)
Lines 313-319 Link Here
313
            }
313
            }
314
            File[] hookFiles = commitCandidates.toArray(new File[commitCandidates.size()]);
314
            File[] hookFiles = commitCandidates.toArray(new File[commitCandidates.size()]);
315
            LogEntry logEntry = new LogEntry(info.getFullMessage(),
315
            LogEntry logEntry = new LogEntry(info.getFullMessage(),
316
                    info.getAuthor().getName(),
316
                    info.getAuthor().toString(),
317
                    info.getRevision(),
317
                    info.getRevision(),
318
                    new Date(info.getCommitTime()));
318
                    new Date(info.getCommitTime()));
319
319
(-)a/git/src/org/netbeans/modules/git/ui/fetch/PullAction.java (-46 / +186 lines)
Lines 52-73 Link Here
52
import java.util.concurrent.Callable;
52
import java.util.concurrent.Callable;
53
import java.util.logging.Level;
53
import java.util.logging.Level;
54
import java.util.logging.Logger;
54
import java.util.logging.Logger;
55
import javax.swing.JButton;
56
import org.netbeans.libs.git.GitBranch;
57
import org.netbeans.libs.git.GitClient.RebaseOperationType;
55
import org.netbeans.modules.git.client.GitClient;
58
import org.netbeans.modules.git.client.GitClient;
56
import org.netbeans.libs.git.GitException;
59
import org.netbeans.libs.git.GitException;
57
import org.netbeans.libs.git.GitPullResult;
60
import org.netbeans.libs.git.GitMergeResult;
61
import org.netbeans.libs.git.GitRebaseResult;
58
import org.netbeans.libs.git.GitRemoteConfig;
62
import org.netbeans.libs.git.GitRemoteConfig;
63
import org.netbeans.libs.git.GitRevisionInfo;
64
import org.netbeans.libs.git.GitTransportUpdate;
59
import org.netbeans.modules.git.Git;
65
import org.netbeans.modules.git.Git;
60
import org.netbeans.modules.git.client.GitClientExceptionHandler;
66
import org.netbeans.modules.git.client.GitClientExceptionHandler;
61
import org.netbeans.modules.git.client.GitProgressSupport;
67
import org.netbeans.modules.git.client.GitProgressSupport;
62
import org.netbeans.modules.git.ui.actions.GitAction;
68
import org.netbeans.modules.git.ui.actions.GitAction;
63
import org.netbeans.modules.git.ui.actions.SingleRepositoryAction;
69
import org.netbeans.modules.git.ui.actions.SingleRepositoryAction;
64
import org.netbeans.modules.git.ui.merge.MergeRevisionAction;
70
import org.netbeans.modules.git.ui.merge.MergeRevisionAction;
71
import org.netbeans.modules.git.ui.rebase.RebaseAction;
65
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
72
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
66
import org.netbeans.modules.git.utils.GitUtils;
73
import org.netbeans.modules.git.utils.GitUtils;
67
import org.netbeans.modules.versioning.spi.VCSContext;
74
import org.netbeans.modules.versioning.spi.VCSContext;
68
import org.netbeans.modules.versioning.util.Utils;
75
import org.netbeans.modules.versioning.util.Utils;
76
import org.openide.DialogDisplayer;
77
import org.openide.NotifyDescriptor;
69
import org.openide.awt.ActionID;
78
import org.openide.awt.ActionID;
70
import org.openide.awt.ActionRegistration;
79
import org.openide.awt.ActionRegistration;
80
import org.openide.awt.Mnemonics;
71
import org.openide.util.NbBundle;
81
import org.openide.util.NbBundle;
72
import org.openide.util.RequestProcessor.Task;
82
import org.openide.util.RequestProcessor.Task;
73
83
Lines 103-159 Link Here
103
    }
113
    }
104
    
114
    
105
    @NbBundle.Messages({
115
    @NbBundle.Messages({
106
        "# {0} - repository name", "LBL_PullAction.progressName=Pulling - {0}"
116
        "# {0} - repository name", "LBL_PullAction.progressName=Pulling - {0}",
117
        "MSG_PullAction.fetching=fetching remote changes",
118
        "MSG_PullAction.merging=merging remote changes",
119
        "MSG_PullAction.rebasing=rebasing onto fetched head"
107
    })
120
    })
108
    public Task pull (File repository, final String target, final List<String> fetchRefSpecs, final String branchToMerge, final String remoteNameToUpdate) {
121
    public Task pull (File repository, final String target, final List<String> fetchRefSpecs, final String branchToMerge, final String remoteNameToUpdate) {
109
        GitProgressSupport supp = new GitProgressSupport() {
122
        GitProgressSupport supp = new GitProgressSupportImpl(fetchRefSpecs, branchToMerge, target, remoteNameToUpdate);
110
            @Override
123
        return supp.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.LBL_PullAction_progressName(repository.getName()));
111
            protected void perform () {
124
    }
112
                final File repository = getRepositoryRoot();
125
113
                LOG.log(Level.FINE, "Pulling {0}/{1} from {2}", new Object[] { fetchRefSpecs, branchToMerge, target }); //NOI18N
126
    private class GitProgressSupportImpl extends GitProgressSupport {
114
                try {
127
115
                    final GitClient client = getClient();
128
        private final List<String> fetchRefSpecs;
116
                    if (remoteNameToUpdate != null) {
129
        private final String branchToMerge;
117
                        GitRemoteConfig config = client.getRemote(remoteNameToUpdate, getProgressMonitor());
130
        private final String target;
131
        private final String remoteNameToUpdate;
132
133
        public GitProgressSupportImpl (List<String> fetchRefSpecs, String branchToMerge, String target, String remoteNameToUpdate) {
134
            this.fetchRefSpecs = fetchRefSpecs;
135
            this.branchToMerge = branchToMerge;
136
            this.target = target;
137
            this.remoteNameToUpdate = remoteNameToUpdate;
138
        }
139
140
        @Override
141
        protected void perform () {
142
            final File repository = getRepositoryRoot();
143
            LOG.log(Level.FINE, "Pulling {0}/{1} from {2}", new Object[] { fetchRefSpecs, branchToMerge, target }); //NOI18N
144
            try {
145
                final GitClient client = getClient();
146
                if (remoteNameToUpdate != null) {
147
                    GitRemoteConfig config = client.getRemote(remoteNameToUpdate, getProgressMonitor());
148
                    if (isCanceled()) {
149
                        return;
150
                    }
151
                    config = FetchAction.prepareConfig(config, remoteNameToUpdate, target, fetchRefSpecs);
152
                    client.setRemote(config, getProgressMonitor());
153
                    if (isCanceled()) {
154
                        return;
155
                    }
156
                }
157
                GitUtils.runWithoutIndexing(new Callable<Void>() {
158
                    @Override
159
                    public Void call () throws Exception {
160
                        setProgress(Bundle.MSG_PullAction_fetching());
161
                        Map<String, GitTransportUpdate> fetchResult = client.fetch(target, fetchRefSpecs, getProgressMonitor());
162
                        FetchUtils.log(fetchResult, getLogger());
118
                        if (isCanceled()) {
163
                        if (isCanceled()) {
119
                            return;
120
                        }
121
                        config = FetchAction.prepareConfig(config, remoteNameToUpdate, target, fetchRefSpecs);
122
                        client.setRemote(config, getProgressMonitor());
123
                        if (isCanceled()) {
124
                            return;
125
                        }
126
                    }
127
                    GitUtils.runWithoutIndexing(new Callable<Void>() {
128
                        @Override
129
                        public Void call () throws Exception {
130
                            boolean cont;
131
                            MergeRevisionAction.MergeResultProcessor mrp = new MergeRevisionAction.MergeResultProcessor(client, repository, branchToMerge, getLogger(), getProgressMonitor());
132
                            do {
133
                                cont = false;
134
                                try {
135
                                    GitPullResult result = client.pull(target, fetchRefSpecs, branchToMerge, getProgressMonitor());
136
                                    FetchUtils.log(result.getFetchResult(), getLogger());
137
                                    mrp.processResult(result.getMergeResult());
138
                                } catch (GitException.CheckoutConflictException ex) {
139
                                    if (LOG.isLoggable(Level.FINE)) {
140
                                        LOG.log(Level.FINE, "Local modifications in WT during merge: {0} - {1}", new Object[] { repository, Arrays.asList(ex.getConflicts()) }); //NOI18N
141
                                    }
142
                                    cont = mrp.resolveLocalChanges(ex.getConflicts());
143
                                }
144
                            } while (cont);
145
                            return null;
164
                            return null;
146
                        }
165
                        }
147
                    }, repository);
166
                        Callable<Void> nextAction = getNextAction();
148
                } catch (GitException ex) {
167
                        if (nextAction != null) {
149
                    GitClientExceptionHandler.notifyException(ex, true);
168
                            nextAction.call();
150
                } finally {
169
                        }
151
                    setDisplayName(NbBundle.getMessage(GitAction.class, "LBL_Progress.RefreshingStatuses")); //NOI18N
170
                        return null;
152
                    Git.getInstance().getFileStatusCache().refreshAllRoots(Collections.<File, Collection<File>>singletonMap(repository, Git.getInstance().getSeenRoots(repository)));
171
                    }
153
                    GitUtils.headChanged(repository);
172
                }, repository);
173
            } catch (GitException ex) {
174
                GitClientExceptionHandler.notifyException(ex, true);
175
            } finally {
176
                setDisplayName(NbBundle.getMessage(GitAction.class, "LBL_Progress.RefreshingStatuses")); //NOI18N
177
                Git.getInstance().getFileStatusCache().refreshAllRoots(Collections.<File, Collection<File>>singletonMap(repository, Git.getInstance().getSeenRoots(repository)));
178
                GitUtils.headChanged(repository);
179
            }
180
        }
181
        
182
        private Callable<Void> getNextAction () {
183
            Callable<Void> nextAction = null;
184
            try {
185
                GitClient client = getClient();
186
                String currentHeadId = null;
187
                String branchId = null;
188
                Map<String, GitBranch> branches = client.getBranches(true, GitUtils.NULL_PROGRESS_MONITOR);
189
                for (Map.Entry<String, GitBranch> e : branches.entrySet()) {
190
                    if (e.getValue().isActive()) {
191
                        currentHeadId = e.getValue().getId();
192
                    }
193
                    if (e.getKey().equals(branchToMerge)) {
194
                        branchId = e.getValue().getId();
195
                    }
154
                }
196
                }
197
                if (branchId == null || currentHeadId == null) {
198
                    nextAction = new Merge(); // just for sure
199
                } else if (!branchId.equals(currentHeadId)) {
200
                    GitRevisionInfo info = client.getCommonAncestor(new String[] { currentHeadId, branchId }, GitUtils.NULL_PROGRESS_MONITOR);
201
                    if (info == null || !(info.getRevision().equals(branchId) || info.getRevision().equals(currentHeadId))) {
202
                        // ask
203
                        return askForNextAction();
204
                    } else if (info.getRevision().equals(currentHeadId)) {
205
                        // FF merge
206
                        nextAction = new Merge();
207
                    }                    
208
                }
209
            } catch (GitException ex) {
210
                LOG.log(Level.INFO, null, ex);
155
            }
211
            }
156
        };
212
            return nextAction;
157
        return supp.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.LBL_PullAction_progressName(repository.getName()));
213
        }
214
215
        @NbBundle.Messages({
216
            "# {0} - branch to merge",
217
            "MSG_PullAction_mergeNeeded_text=A merge commit is needed to synchronize current branch with {0}.\n\n"
218
                + "Do you want to Merge the current branch with {0} or Rebase it onto {0}?",
219
            "LBL_PullAction_mergeNeeded_title=Merge Commit Needed",
220
            "CTL_PullAction_mergeButton_text=&Merge",
221
            "CTL_PullAction_mergeButton_TTtext=Merge the two created heads",
222
            "CTL_PullAction_rebaseButton_text=&Rebase",
223
            "CTL_PullAction_rebaseButton_TTtext=Rebase local changesets onto "
224
            + "the tipmost branch head"
225
        })
226
        private Callable<Void> askForNextAction () {
227
            JButton btnMerge = new JButton();
228
            Mnemonics.setLocalizedText(btnMerge, Bundle.CTL_PullAction_mergeButton_text());
229
            btnMerge.setToolTipText(Bundle.CTL_PullAction_mergeButton_TTtext());
230
            JButton btnRebase = new JButton();
231
            Mnemonics.setLocalizedText(btnRebase, Bundle.CTL_PullAction_rebaseButton_text());
232
            btnRebase.setToolTipText(Bundle.CTL_PullAction_rebaseButton_TTtext());
233
            Object value = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
234
                    Bundle.MSG_PullAction_mergeNeeded_text(branchToMerge),
235
                    Bundle.LBL_PullAction_mergeNeeded_title(),
236
                    NotifyDescriptor.DEFAULT_OPTION,
237
                    NotifyDescriptor.QUESTION_MESSAGE,
238
                    new Object[] { btnMerge, btnRebase, NotifyDescriptor.CANCEL_OPTION },
239
                    btnMerge));
240
            if (value == btnMerge) {
241
                return new Merge();
242
            } else if (value == btnRebase) {
243
                return new Rebase();
244
            }
245
            return null;
246
        }
247
        
248
        private class Merge implements Callable<Void> {
249
250
            @Override
251
            public Void call () throws GitException {
252
                boolean cont;
253
                GitClient client = getClient();
254
                File repository = getRepositoryRoot();
255
                setProgress(Bundle.MSG_PullAction_merging());
256
                do {
257
                    MergeRevisionAction.MergeResultProcessor mrp = new MergeRevisionAction.MergeResultProcessor(client, repository, branchToMerge, getLogger(), getProgressMonitor());
258
                    cont = false;
259
                    try {
260
                        GitMergeResult result = client.merge(branchToMerge, getProgressMonitor());
261
                        mrp.processResult(result);
262
                    } catch (GitException.CheckoutConflictException ex) {
263
                        if (LOG.isLoggable(Level.FINE)) {
264
                            LOG.log(Level.FINE, "Local modifications in WT during merge: {0} - {1}", new Object[] { repository, Arrays.asList(ex.getConflicts()) }); //NOI18N
265
                        }
266
                        cont = mrp.resolveLocalChanges(ex.getConflicts());
267
                    }
268
                } while (cont && !isCanceled());
269
                return null;
270
            }
271
272
        }
273
274
        private class Rebase implements Callable<Void> {
275
276
            @Override
277
            public Void call () throws GitException  {
278
                setProgress(Bundle.MSG_PullAction_rebasing());
279
                RebaseOperationType op = RebaseOperationType.BEGIN;
280
                GitClient client = getClient();
281
                File repository = getRepositoryRoot();
282
                String origHead = client.log(GitUtils.HEAD, getProgressMonitor()).getRevision();
283
                RebaseAction.RebaseResultProcessor rrp = new RebaseAction.RebaseResultProcessor(client, repository,
284
                        branchToMerge, branchToMerge, origHead, getProgressSupport());
285
                while (op != null && !isCanceled()) {
286
                    GitRebaseResult result = client.rebase(op, branchToMerge, getProgressMonitor());
287
                    rrp.processResult(result);
288
                    op = rrp.getNextAction();
289
                }
290
                return null;
291
            }
292
        }
293
294
        private GitProgressSupport getProgressSupport () {
295
            return this;
296
        }
158
    }
297
    }
298
    
159
}
299
}
(-)a/git/src/org/netbeans/modules/git/ui/menu/BranchMenu.java (+9 lines)
Lines 51-56 Link Here
51
import org.netbeans.modules.git.ui.branch.CreateBranchAction;
51
import org.netbeans.modules.git.ui.branch.CreateBranchAction;
52
import org.netbeans.modules.git.ui.checkout.SwitchBranchAction;
52
import org.netbeans.modules.git.ui.checkout.SwitchBranchAction;
53
import org.netbeans.modules.git.ui.merge.MergeRevisionAction;
53
import org.netbeans.modules.git.ui.merge.MergeRevisionAction;
54
import org.netbeans.modules.git.ui.rebase.RebaseAction;
54
import org.netbeans.modules.git.ui.tag.CreateTagAction;
55
import org.netbeans.modules.git.ui.tag.CreateTagAction;
55
import org.netbeans.modules.git.ui.tag.ManageTagsAction;
56
import org.netbeans.modules.git.ui.tag.ManageTagsAction;
56
import org.netbeans.modules.versioning.spi.VCSAnnotator.ActionDestination;
57
import org.netbeans.modules.versioning.spi.VCSAnnotator.ActionDestination;
Lines 115-120 Link Here
115
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
116
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
116
            Actions.connect(item, action, false);
117
            Actions.connect(item, action, false);
117
            menu.add(item);
118
            menu.add(item);
119
            
120
            item = new JMenuItem();
121
            action = (Action) SystemAction.get(RebaseAction.class);
122
            Utils.setAcceleratorBindings(Annotator.ACTIONS_PATH_PREFIX, action);
123
            Actions.connect(item, action, false);
124
            menu.add(item);
118
        } else {
125
        } else {
119
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(CreateBranchAction.class), NbBundle.getMessage(CreateBranchAction.class, "LBL_CreateBranchAction_PopupName"), lkp)); //NOI18N
126
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(CreateBranchAction.class), NbBundle.getMessage(CreateBranchAction.class, "LBL_CreateBranchAction_PopupName"), lkp)); //NOI18N
120
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
127
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
Lines 130-135 Link Here
130
            menu.addSeparator();
137
            menu.addSeparator();
131
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(MergeRevisionAction.class), NbBundle.getMessage(MergeRevisionAction.class, "LBL_MergeRevisionAction_PopupName"), lkp)); //NOI18N
138
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(MergeRevisionAction.class), NbBundle.getMessage(MergeRevisionAction.class, "LBL_MergeRevisionAction_PopupName"), lkp)); //NOI18N
132
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
139
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
140
            item = menu.add(SystemActionBridge.createAction(SystemAction.get(RebaseAction.class), NbBundle.getMessage(RebaseAction.class, "LBL_RebaseAction_PopupName"), lkp)); //NOI18N
141
            org.openide.awt.Mnemonics.setLocalizedText(item, item.getText());
133
        }        
142
        }        
134
        return menu;
143
        return menu;
135
    }
144
    }
(-)a/git/src/org/netbeans/modules/git/ui/merge/MergeRevisionAction.java (-3 / +1 lines)
Lines 139-151 Link Here
139
    
139
    
140
    public static class MergeResultProcessor extends ResultProcessor {
140
    public static class MergeResultProcessor extends ResultProcessor {
141
141
142
        private final GitClient client;
143
        private final OutputLogger logger;
142
        private final OutputLogger logger;
144
        private final String revision;
143
        private final String revision;
145
        
144
        
146
        public MergeResultProcessor (GitClient client, File repository, String revision, OutputLogger logger, ProgressMonitor pm) {
145
        public MergeResultProcessor (GitClient client, File repository, String revision, OutputLogger logger, ProgressMonitor pm) {
147
            super(client, repository, revision, logger, pm);
146
            super(client, repository, revision, pm);
148
            this.client = client;
149
            this.revision = revision;
147
            this.revision = revision;
150
            this.logger = logger;
148
            this.logger = logger;
151
        }
149
        }
(-)2564a5300f7a (+486 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.git.ui.rebase;
43
44
import java.io.BufferedReader;
45
import java.io.ByteArrayInputStream;
46
import java.io.File;
47
import java.io.FileReader;
48
import java.io.IOException;
49
import java.util.ArrayList;
50
import java.util.Collection;
51
import java.util.Collections;
52
import java.util.Date;
53
import java.util.HashMap;
54
import java.util.List;
55
import java.util.Map;
56
import java.util.concurrent.Callable;
57
import java.util.logging.Level;
58
import java.util.logging.Logger;
59
import javax.swing.JButton;
60
import org.netbeans.libs.git.GitClient.RebaseOperationType;
61
import org.netbeans.libs.git.GitException;
62
import org.netbeans.libs.git.GitRebaseResult;
63
import org.netbeans.libs.git.GitRepositoryState;
64
import org.netbeans.libs.git.GitRevisionInfo;
65
import org.netbeans.libs.git.SearchCriteria;
66
import org.netbeans.libs.git.progress.ProgressMonitor;
67
import org.netbeans.modules.git.Git;
68
import org.netbeans.modules.git.client.GitClient;
69
import org.netbeans.modules.git.client.GitClientExceptionHandler;
70
import org.netbeans.modules.git.client.GitProgressSupport;
71
import org.netbeans.modules.git.ui.actions.GitAction;
72
import org.netbeans.modules.git.ui.actions.SingleRepositoryAction;
73
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsExecutor;
74
import org.netbeans.modules.git.ui.output.OutputLogger;
75
import org.netbeans.modules.git.utils.GitUtils;
76
import org.netbeans.modules.git.utils.ResultProcessor;
77
import org.openide.util.NbBundle;
78
import org.netbeans.modules.git.ui.repository.RepositoryInfo;
79
import org.netbeans.modules.versioning.hooks.GitHook;
80
import org.netbeans.modules.versioning.hooks.GitHookContext;
81
import org.netbeans.modules.versioning.hooks.VCSHooks;
82
import org.netbeans.modules.versioning.spi.VCSContext;
83
import org.netbeans.modules.versioning.util.FileUtils;
84
import org.openide.DialogDisplayer;
85
import org.openide.NotifyDescriptor;
86
import org.openide.awt.ActionID;
87
import org.openide.awt.ActionRegistration;
88
import org.openide.awt.Mnemonics;
89
90
/**
91
 *
92
 * @author Ondrej Vrabec
93
 */
94
@ActionID(id = "org.netbeans.modules.git.ui.rebase.RebaseAction", category = "Git")
95
@ActionRegistration(displayName = "#LBL_RebaseAction_Name")
96
@NbBundle.Messages({
97
    "LBL_RebaseAction_Name=&Rebase...", "LBL_RebaseAction_PopupName=Rebase..."
98
})
99
public class RebaseAction extends SingleRepositoryAction {
100
101
    private static final Logger LOG = Logger.getLogger(RebaseAction.class.getName());
102
    private static final String NETBEANS_REBASE_ORIGHEAD = "netbeans-rebase.orighead"; //NOI18N
103
    private static final String NETBEANS_REBASE_UPSTREAM = "netbeans-rebase.upstream"; //NOI18N
104
    private static final String NETBEANS_REBASE_ONTO = "netbeans-rebase.onto"; //NOI18N
105
    private static final String REBASE_MERGE_DIR = "rebase-merge"; //NOI18N
106
107
    @Override
108
    protected void performAction (File repository, File[] roots, VCSContext context) {
109
        RepositoryInfo info = RepositoryInfo.getInstance(repository);
110
        info.refresh();
111
        rebase(repository, info);
112
    }
113
114
    @NbBundle.Messages({
115
        "# {0} - repository state", "MSG_RebaseAction_rebaseNotAllowed=Rebase is not allowed in this state: {0}",
116
        "CTL_RebaseAction.continueButton.text=C&ontinue",
117
        "CTL_RebaseAction.continueButton.TTtext=Continue the interrupted rebase",
118
        "CTL_RebaseAction.abortButton.text=Abo&rt",
119
        "CTL_RebaseAction.abortButton.TTtext=Abort the interrupted rebase",
120
        "CTL_RebaseAction.skipButton.text=&Skip",
121
        "CTL_RebaseAction.skipButton.TTtext=Skip the current commit and continue the interrupted rebase",
122
        "LBL_Rebase.rebasingState.title=Unfinished Rebase",
123
        "# {0} - repository name", "MSG_Rebase.rebasingState.text=Repository {0} is in the middle of an unfinished rebase.\n"
124
            + "Do you want to continue or abort the unfinished rebase\n"
125
            + "or skip the current commit from the rebase?"
126
    })
127
    private void rebase (File repository, RepositoryInfo info) {
128
        GitRepositoryState state = info.getRepositoryState();
129
        if (state == GitRepositoryState.SAFE) {
130
            // should start
131
        } else if (state == GitRepositoryState.REBASING) {
132
            // abort or continue?
133
            JButton btnContinue = new JButton();
134
            Mnemonics.setLocalizedText(btnContinue, Bundle.CTL_RebaseAction_continueButton_text());
135
            btnContinue.setToolTipText(Bundle.CTL_RebaseAction_continueButton_TTtext());
136
            JButton btnAbort = new JButton();
137
            Mnemonics.setLocalizedText(btnAbort, Bundle.CTL_RebaseAction_abortButton_text());
138
            btnAbort.setToolTipText(Bundle.CTL_RebaseAction_abortButton_TTtext());
139
            JButton btnSkip = new JButton();
140
            Mnemonics.setLocalizedText(btnSkip, Bundle.CTL_RebaseAction_skipButton_text());
141
            btnSkip.setToolTipText(Bundle.CTL_RebaseAction_skipButton_TTtext());
142
            Map<Object, RebaseOperationType> operations = new HashMap<Object, RebaseOperationType>();
143
            operations.put(btnContinue, RebaseOperationType.CONTINUE);
144
            operations.put(btnSkip, RebaseOperationType.SKIP);
145
            operations.put(btnAbort, RebaseOperationType.ABORT);
146
            Object value = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
147
                    Bundle.MSG_Rebase_rebasingState_text(repository.getName()),
148
                    Bundle.LBL_Rebase_rebasingState_title(),
149
                    NotifyDescriptor.YES_NO_CANCEL_OPTION,
150
                    NotifyDescriptor.QUESTION_MESSAGE,
151
                    new Object[] { btnContinue, btnSkip, btnAbort, NotifyDescriptor.CANCEL_OPTION }, 
152
                    btnContinue));
153
            RebaseOperationType op = operations.get(value);
154
            if (op != null) {
155
                finishRebase(repository, op);
156
            }
157
        } else {
158
            GitClientExceptionHandler.annotate(Bundle.MSG_RebaseAction_rebaseNotAllowed(state));
159
        }
160
    }
161
162
    @NbBundle.Messages("MSG_RebaseAction_progress=Rebasing...")
163
    private void finishRebase (final File repository, final RebaseOperationType op) {
164
        GitProgressSupport supp = new GitProgressSupport() {
165
166
            @Override
167
            protected void perform () {
168
                try {
169
                    GitUtils.runWithoutIndexing(new Callable<Void>() {
170
                        @Override
171
                        public Void call () throws Exception {
172
                            String origHead = getRebaseFileContent(repository, NETBEANS_REBASE_ORIGHEAD);
173
                            String onto = getOnto(repository);
174
                            String upstream = getRebaseFileContent(repository, NETBEANS_REBASE_UPSTREAM);
175
                            GitClient client = getClient();
176
                            RebaseResultProcessor rrp = new RebaseResultProcessor(client, repository, onto, upstream, origHead,
177
                                    getProgressSupport());
178
                            RebaseOperationType nextAction = op;
179
                            while (nextAction != null && !isCanceled()) {
180
                                GitRebaseResult result = client.rebase(nextAction, onto, getProgressMonitor());
181
                                rrp.processResult(result);
182
                                nextAction = rrp.getNextAction();
183
                            }
184
                            return null;
185
                        }
186
                    });
187
                } catch (GitException ex) {
188
                    GitClientExceptionHandler.notifyException(ex, true);
189
                } finally {
190
                    setDisplayName(NbBundle.getMessage(GitAction.class, "LBL_Progress.RefreshingStatuses")); //NOI18N
191
                    Git.getInstance().getFileStatusCache().refreshAllRoots(Collections.<File, Collection<File>>singletonMap(repository, Git.getInstance().getSeenRoots(repository)));
192
                    GitUtils.headChanged(repository);
193
                }
194
            }
195
196
            private GitProgressSupport getProgressSupport () {
197
                return this;
198
            }
199
        };
200
        supp.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.MSG_RebaseAction_progress());
201
    }
202
203
    @NbBundle.Messages({
204
        "MSG_RebaseAction.noMergeStrategies=Cannot continue rebase. It was probably started externally but without "
205
            + "the merging algorithm (\"-m\" option) which is the only supported option in the NetBeans IDE.\n"
206
            + "Please use the external tool you started rebase with to finish it."
207
    })
208
    private static String getRebaseFileContent (File repository, String filename) throws GitException {
209
        File rebaseFolder = new File(GitUtils.getGitFolderForRoot(repository), REBASE_MERGE_DIR);
210
        if (rebaseFolder.exists()) {
211
            File file = new File(rebaseFolder, filename);
212
            if (file.canRead()) {
213
                BufferedReader br = null;
214
                try {
215
                    br = new BufferedReader(new FileReader(file));
216
                    return br.readLine();
217
                } catch (IOException ex) {
218
                    LOG.log(Level.FINE, null, ex);
219
                } finally {
220
                    if (br != null) {
221
                        try {
222
                            br.close();
223
                        } catch (IOException ex) {}
224
                    }
225
                }
226
            }
227
        } else {
228
            throw new GitException(Bundle.MSG_RebaseAction_noMergeStrategies());
229
        }
230
        return null;
231
    }
232
233
    private static String getOnto (File repository) throws GitException {
234
        String onto = getRebaseFileContent(repository, NETBEANS_REBASE_ONTO);
235
        if (onto == null) {
236
            onto = getRebaseFileContent(repository, "onto-name"); //NOI18N
237
        }
238
        if (onto == null) {
239
            onto = getRebaseFileContent(repository, "onto_name"); //NOI18N
240
        }
241
        if (onto == null) {
242
            onto = getRebaseFileContent(repository, "onto"); //NOI18N
243
        }
244
        return onto;
245
    }
246
    
247
    public static class RebaseResultProcessor extends ResultProcessor {
248
249
        private final OutputLogger logger;
250
        private final String onto;
251
        private final String origHead;
252
        private final String upstream;
253
        private RebaseOperationType nextAction;
254
        private final GitProgressSupport supp;
255
        
256
        public RebaseResultProcessor (GitClient client, File repository, String onto, String upstream, String origHead,
257
                GitProgressSupport supp) {
258
            super(client, repository, onto, supp.getProgressMonitor());
259
            this.origHead = origHead;
260
            this.onto = onto;
261
            this.upstream = upstream;
262
            this.logger = supp.getLogger();
263
            this.supp = supp;
264
        }
265
        
266
        @NbBundle.Messages({
267
            "# {0} - rebase status", "MSG_RebaseAction.result=Rebase Result: {0}\n",
268
            "# {0} - head commit id", "MSG_RebaseAction.result.aborted=Rebase aborted and the current HEAD reset to {0}\n",
269
            "MSG_RebaseAction.result.conflict=Rebase interrupted because of conflicts in:\n",
270
            "# {0} - head commit id", "MSG_RebaseAction.result.ok=Rebase successfully finished and HEAD now points to {0}:\n",
271
            "# {0} - rebase target revision", "MSG_RebaseAction.result.alreadyUpToDate=HEAD already in sync with {0}"
272
        })
273
        public void processResult (GitRebaseResult result) {
274
            nextAction = null;
275
            StringBuilder sb = new StringBuilder(Bundle.MSG_RebaseAction_result(result.getRebaseStatus().toString()));
276
            GitRevisionInfo info;
277
            try {
278
                info = client.log(GitUtils.HEAD, GitUtils.NULL_PROGRESS_MONITOR);
279
            } catch (GitException ex) {
280
                GitClientExceptionHandler.notifyException(ex, true);
281
                return;
282
            }
283
            persistNBConfig();
284
            switch (result.getRebaseStatus()) {
285
                case ABORTED:
286
                    sb.append(Bundle.MSG_RebaseAction_result_aborted(info.getRevision()));
287
                    GitUtils.printInfo(sb, info);
288
                    break;
289
                case FAILED:
290
                case CONFLICTS:
291
                    if (LOG.isLoggable(Level.FINE)) {
292
                        LOG.log(Level.FINE, "Local modifications in WT during rebase: {0} - {1}", new Object[] { repository, result.getFailures() }); //NOI18N
293
                    }
294
                    try {
295
                        if (resolveLocalChanges(result.getFailures().toArray(new File[result.getFailures().size()]))) {
296
                            nextAction = RebaseOperationType.BEGIN;
297
                        }
298
                    } catch (GitException ex) {
299
                        GitClientExceptionHandler.notifyException(ex, true);
300
                    }
301
                    break;
302
                case NOTHING_TO_COMMIT:
303
                    nextAction = resolveNothingToCommit();
304
                    break;
305
                case FAST_FORWARD:
306
                case OK:
307
                    sb.append(Bundle.MSG_RebaseAction_result_ok(info.getRevision()));
308
                    GitUtils.printInfo(sb, info);
309
                    updatePushHooks();
310
                    break;
311
                case STOPPED:
312
                    sb.append(Bundle.MSG_RebaseAction_result_conflict());
313
                    printConflicts(sb, result.getConflicts());
314
                    nextAction = resolveRebaseConflicts(result.getConflicts());
315
                    break;
316
                case UP_TO_DATE:
317
                    sb.append(Bundle.MSG_RebaseAction_result_alreadyUpToDate(onto));
318
                    break;
319
            }
320
            logger.output(sb.toString());
321
        }
322
323
        public RebaseOperationType getNextAction () {
324
            return nextAction;
325
        }
326
327
        @NbBundle.Messages({
328
            "LBL_RebaseResultProcessor.abortButton.text=&Abort",
329
            "LBL_RebaseResultProcessor.abortButton.TTtext=Abort the interrupted rebase and reset back to the original commit.",
330
            "LBL_RebaseResultProcessor.resolveButton.text=&Resolve",
331
            "LBL_RebaseResultProcessor.resolveButton.TTtext=Files in conflict will be opened in a Resolve Conflict dialog.",
332
            "LBL_RebaseResultProcessor.resolveConflicts=Resolve Conflicts",
333
            "MSG_RebaseResultProcessor.resolveConflicts=Rebase produced unresolved conflicts.\n"
334
                + "You can resolve them manually or review them in the Versioning view\n"
335
                + "or completely abort the rebase.",
336
            "LBL_RebaseResultProcessor.revertButton.text=&Revert",
337
            "LBL_RebaseResultProcessor.revertButton.TTtext=Revert local changes to the state in the HEAD and removes unversioned files.",
338
            "LBL_RebaseResultProcessor.reviewButton.text=Re&view",
339
            "LBL_RebaseResultProcessor.reviewButton.TTtext=Opens the Versioning view and lists the conflicted files.",
340
            "MSG_Rebase.resolving=Resolving conflicts..."
341
        })
342
        private RebaseOperationType resolveRebaseConflicts (Collection<File> conflicts) {
343
            RebaseOperationType action = null;
344
            JButton abort = new JButton();
345
            Mnemonics.setLocalizedText(abort, Bundle.LBL_RebaseResultProcessor_abortButton_text());
346
            abort.setToolTipText(Bundle.LBL_RebaseResultProcessor_abortButton_TTtext());
347
            JButton resolve = new JButton();
348
            Mnemonics.setLocalizedText(resolve, Bundle.LBL_RebaseResultProcessor_resolveButton_text());
349
            resolve.setToolTipText(Bundle.LBL_RebaseResultProcessor_resolveButton_TTtext());
350
            JButton review = new JButton();
351
            Mnemonics.setLocalizedText(review, Bundle.LBL_RebaseResultProcessor_reviewButton_text());
352
            review.setToolTipText(Bundle.LBL_RebaseResultProcessor_reviewButton_TTtext());
353
            Object o = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
354
                    Bundle.MSG_RebaseResultProcessor_resolveConflicts(),
355
                    Bundle.LBL_RebaseResultProcessor_resolveConflicts(),
356
                    NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE,
357
                    new Object[] { resolve, review, abort, NotifyDescriptor.CANCEL_OPTION }, resolve));
358
            if (o == review) {
359
                openInVersioningView(conflicts);
360
            } else if (o == resolve) {
361
                GitProgressSupport supp = new ResolveConflictsExecutor(conflicts.toArray(new File[conflicts.size()]));
362
                supp.start(Git.getInstance().getRequestProcessor(repository), repository, Bundle.MSG_Rebase_resolving());
363
            } else if (o == abort) {
364
                action = RebaseOperationType.ABORT;
365
            }
366
            return action;
367
        }
368
369
        @NbBundle.Messages({
370
            "LBL_RebaseResultProcessor.nothingToCommit=Nothing to Commit",
371
            "MSG_RebaseResultProcessor.nothingToCommit=No modifications to commit for the current rebase step.\n"
372
                + "Do you want to skip the commit from the rebase and continue?",
373
            "LBL_RebaseResultProcessor.skipButton.text=&Skip",
374
            "LBL_RebaseResultProcessor.skipButton.TTtext=Skip the commit and continue rebase."
375
        })
376
        private RebaseOperationType resolveNothingToCommit () {
377
            RebaseOperationType action = null;
378
            JButton abort = new JButton();
379
            Mnemonics.setLocalizedText(abort, Bundle.LBL_RebaseResultProcessor_abortButton_text());
380
            abort.setToolTipText(Bundle.LBL_RebaseResultProcessor_abortButton_TTtext());
381
            JButton skip = new JButton();
382
            Mnemonics.setLocalizedText(skip, Bundle.LBL_RebaseResultProcessor_skipButton_text());
383
            skip.setToolTipText(Bundle.LBL_RebaseResultProcessor_skipButton_TTtext());
384
            Object o = DialogDisplayer.getDefault().notify(new NotifyDescriptor(
385
                    Bundle.MSG_RebaseResultProcessor_nothingToCommit(),
386
                    Bundle.LBL_RebaseResultProcessor_nothingToCommit(),
387
                    NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE,
388
                    new Object[] { skip, abort, NotifyDescriptor.CANCEL_OPTION }, skip));
389
            if (o == skip) {
390
                action = RebaseOperationType.SKIP;
391
            } else if (o == abort) {
392
                action = RebaseOperationType.ABORT;
393
            }
394
            return action;
395
        }
396
397
        private void persistNBConfig () {
398
            if (onto != null && upstream != null && origHead != null) {
399
                File rebaseFolder = new File(GitUtils.getGitFolderForRoot(repository), REBASE_MERGE_DIR);
400
                if (rebaseFolder.canWrite()) {
401
                    try {
402
                        FileUtils.copyStreamToFile(new ByteArrayInputStream(onto.getBytes()), new File(rebaseFolder, NETBEANS_REBASE_ONTO));
403
                        FileUtils.copyStreamToFile(new ByteArrayInputStream(upstream.getBytes()), new File(rebaseFolder, NETBEANS_REBASE_UPSTREAM));
404
                        FileUtils.copyStreamToFile(new ByteArrayInputStream(origHead.getBytes()), new File(rebaseFolder, NETBEANS_REBASE_ORIGHEAD));
405
                    } catch (IOException ex) {
406
                        LOG.log(Level.INFO, null, ex);
407
                    }
408
                }
409
            }
410
        }
411
412
        @NbBundle.Messages("MSG_RebaseAction.updatingHooks=updating push hooks")
413
        private void updatePushHooks () {
414
            if (onto != null && upstream != null && origHead != null) {
415
                Collection<GitHook> hooks = VCSHooks.getInstance().getHooks(GitHook.class);
416
                if (!hooks.isEmpty() && !pm.isCanceled()) {
417
                    supp.setProgress(Bundle.MSG_RebaseAction_updatingHooks());
418
                    try {
419
                        GitHookContext.LogEntry[] originalEntries = getEntries(client, upstream, origHead, pm);
420
                        if (pm.isCanceled()) {
421
                            return;
422
                        }
423
                        GitHookContext.LogEntry[] newEntries = getEntries(client, onto, GitUtils.HEAD, pm);
424
                        if (pm.isCanceled()) {
425
                            return;
426
                        }
427
                        Map<String, String> mapping = findChangesetMapping(originalEntries, newEntries);
428
                        for (GitHook gitHook : hooks) {
429
                            gitHook.afterCommitReplace(
430
                                    new GitHookContext(new File[] { repository }, null, originalEntries),
431
                                    new GitHookContext(new File[] { repository }, null, newEntries),
432
                                    mapping);
433
                        }
434
                    } catch (GitException ex) {
435
                        LOG.log(Level.INFO, null, ex);
436
                    }
437
                }
438
            }
439
        }
440
    }
441
    
442
    private static Map<String, String> findChangesetMapping (GitHookContext.LogEntry[] originalEntries, GitHookContext.LogEntry[] newEntries) {
443
        Map<String, String> mapping = new HashMap<String, String>(originalEntries.length);
444
        for (GitHookContext.LogEntry original : originalEntries) {
445
            boolean found = false;
446
            for (GitHookContext.LogEntry newEntry : newEntries) {
447
                if (original.getChangeset().equals(newEntry.getChangeset()) || (
448
                        original.getDate().equals(newEntry.getDate())
449
                        && original.getAuthor().equals(newEntry.getAuthor())
450
                        && original.getMessage().equals(newEntry.getMessage()))) {
451
                    // is it really the same commit???
452
                    mapping.put(original.getChangeset(), newEntry.getChangeset());
453
                    found = true;
454
                    break;
455
                }
456
            }
457
            if (!found) {
458
                // delete ????
459
                mapping.put(original.getChangeset(), null);
460
            }
461
        }
462
        return mapping;
463
    }
464
    
465
    private static GitHookContext.LogEntry[] getEntries (GitClient client, String revisionFrom, String revisionTo,
466
            ProgressMonitor pm) throws GitException {
467
        SearchCriteria crit = new SearchCriteria();
468
        crit.setRevisionFrom(revisionFrom);
469
        crit.setRevisionTo(revisionTo);
470
        GitRevisionInfo[] log = client.log(crit, pm);
471
        return convertToEntries(log);
472
    }    
473
474
    private static GitHookContext.LogEntry[] convertToEntries (GitRevisionInfo[] messages) {
475
        List<GitHookContext.LogEntry> entries = new ArrayList<GitHookContext.LogEntry>(messages.length);
476
        for (GitRevisionInfo msg : messages) {
477
            entries.add(new GitHookContext.LogEntry(
478
                    msg.getFullMessage(),
479
                    msg.getAuthor().toString(),
480
                    msg.getRevision(),
481
                    new Date(msg.getCommitTime())));
482
        }
483
        return entries.toArray(new GitHookContext.LogEntry[entries.size()]);
484
    }
485
    
486
}
(-)a/git/src/org/netbeans/modules/git/ui/revert/RevertCommitAction.java (-1 / +1 lines)
Lines 136-142 Link Here
136
        private final String revision;
136
        private final String revision;
137
        
137
        
138
        public RevertResultProcessor (GitClient client, File repository, String revision, OutputLogger logger, ProgressMonitor pm) {
138
        public RevertResultProcessor (GitClient client, File repository, String revision, OutputLogger logger, ProgressMonitor pm) {
139
            super(client, repository, revision, logger, pm);
139
            super(client, repository, revision, pm);
140
            this.revision = revision;
140
            this.revision = revision;
141
            this.logger = logger;
141
            this.logger = logger;
142
        }
142
        }
(-)a/git/src/org/netbeans/modules/git/utils/Bundle.properties (-2 / +2 lines)
Lines 46-53 Link Here
46
#ResultProcessor
46
#ResultProcessor
47
LBL_ResultProcessor.resolveButton.text=&Resolve
47
LBL_ResultProcessor.resolveButton.text=&Resolve
48
LBL_ResultProcessor.resolveButton.TTtext=Files in conflict will be opened in a Resolve Conflict dialog.
48
LBL_ResultProcessor.resolveButton.TTtext=Files in conflict will be opened in a Resolve Conflict dialog.
49
LBL_ResultProcessor.resolveConflicts=Merge Conflicts
49
LBL_ResultProcessor.resolveConflicts=Resolve Conflicts
50
MSG_ResultProcessor.resolveConflicts=Merge produced unresolved conflicts.\n\
50
MSG_ResultProcessor.resolveConflicts=Git command produced unresolved conflicts.\n\
51
You can try to resolve them manually or review them in the Versioning view.
51
You can try to resolve them manually or review them in the Versioning view.
52
LBL_ResultProcessor.reviewingConflicts=Review conflicts
52
LBL_ResultProcessor.reviewingConflicts=Review conflicts
53
MSG_ResultProcessor.localModifications = You have local modification in working copy that would result in a checkout conflict.\n\
53
MSG_ResultProcessor.localModifications = You have local modification in working copy that would result in a checkout conflict.\n\
(-)a/git/src/org/netbeans/modules/git/utils/ResultProcessor.java (-8 / +10 lines)
Lines 57-63 Link Here
57
import org.netbeans.modules.git.ui.actions.GitAction;
57
import org.netbeans.modules.git.ui.actions.GitAction;
58
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsAction;
58
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsAction;
59
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsExecutor;
59
import org.netbeans.modules.git.ui.conflicts.ResolveConflictsExecutor;
60
import org.netbeans.modules.git.ui.output.OutputLogger;
61
import org.openide.DialogDisplayer;
60
import org.openide.DialogDisplayer;
62
import org.openide.NotifyDescriptor;
61
import org.openide.NotifyDescriptor;
63
import org.openide.awt.Mnemonics;
62
import org.openide.awt.Mnemonics;
Lines 70-81 Link Here
70
public class ResultProcessor {
69
public class ResultProcessor {
71
70
72
    private static final Logger LOG = Logger.getLogger(ResultProcessor.class.getName());
71
    private static final Logger LOG = Logger.getLogger(ResultProcessor.class.getName());
73
    private final GitClient client;
72
    protected final GitClient client;
74
    private final File repository;
73
    protected final File repository;
75
    private final String revision;
74
    private final String revision;
76
    private final ProgressMonitor pm;
75
    protected final ProgressMonitor pm;
77
76
78
    public ResultProcessor (GitClient client, File repository, String revision, OutputLogger logger, ProgressMonitor pm) {
77
    public ResultProcessor (GitClient client, File repository, String revision, ProgressMonitor pm) {
79
        this.client = client;
78
        this.client = client;
80
        this.repository = repository;
79
        this.repository = repository;
81
        this.revision = revision;
80
        this.revision = revision;
Lines 106-113 Link Here
106
        }
105
        }
107
    }
106
    }
108
107
109
    public boolean resolveLocalChanges (String[] conflicts) throws GitException {
108
    public final boolean resolveLocalChanges (String[] conflicts) throws GitException {
110
        File[] localChanges = getFilesInConflict(conflicts);
109
        return resolveLocalChanges(getFilesInConflict(conflicts));
110
    }
111
        
112
    public final boolean resolveLocalChanges (File[] localChanges) throws GitException {
111
        JButton revert = new JButton();
113
        JButton revert = new JButton();
112
        Mnemonics.setLocalizedText(revert, NbBundle.getMessage(ResultProcessor.class, "LBL_ResultProcessor.revertButton.text")); //NOI18N
114
        Mnemonics.setLocalizedText(revert, NbBundle.getMessage(ResultProcessor.class, "LBL_ResultProcessor.revertButton.text")); //NOI18N
113
        revert.setToolTipText(NbBundle.getMessage(ResultProcessor.class, "LBL_ResultProcessor.revertButton.TTtext")); //NOI18N
115
        revert.setToolTipText(NbBundle.getMessage(ResultProcessor.class, "LBL_ResultProcessor.revertButton.TTtext")); //NOI18N
Lines 140-146 Link Here
140
        return files.toArray(new File[files.size()]);
142
        return files.toArray(new File[files.size()]);
141
    }
143
    }
142
144
143
    private void openInVersioningView (final Collection<File> files) {
145
    protected final void openInVersioningView (final Collection<File> files) {
144
        new GitProgressSupport() {
146
        new GitProgressSupport() {
145
            @Override
147
            @Override
146
            protected void perform () {
148
            protected void perform () {
(-)a/versioning.util/nbproject/project.properties (-1 / +1 lines)
Lines 44-50 Link Here
44
javac.source=1.6
44
javac.source=1.6
45
45
46
javadoc.name=Versioning Support Utilities
46
javadoc.name=Versioning Support Utilities
47
spec.version.base=1.39.0
47
spec.version.base=1.40
48
is.autoload=true
48
is.autoload=true
49
49
50
# Fatal error: Fatal error: class javax.net.SocketFactory not found
50
# Fatal error: Fatal error: class javax.net.SocketFactory not found
(-)a/versioning.util/src/org/netbeans/modules/versioning/hooks/GitHook.java (-2 / +6 lines)
Lines 43-50 Link Here
43
package org.netbeans.modules.versioning.hooks;
43
package org.netbeans.modules.versioning.hooks;
44
44
45
import java.io.IOException;
45
import java.io.IOException;
46
import javax.swing.JPanel;
46
import java.util.Map;
47
import org.netbeans.modules.versioning.hooks.VCSHook;
48
47
49
/**
48
/**
50
 *
49
 *
Lines 68-71 Link Here
68
67
69
    }
68
    }
70
69
70
    public void afterCommitReplace (GitHookContext originalContext, GitHookContext newContext,
71
            Map<String, String> changesetMapping) {
72
        
73
    }
74
71
}
75
}

Return to bug 226545