ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / plugins / git4idea / src / git4idea / update / GitUpdateLocallyModifiedDialog.java
blobc750d8a06995f86296f9213d8f5b10d984f84a00
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package git4idea.update;
18 import com.intellij.openapi.application.ApplicationNamesInfo;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.ui.DialogWrapper;
21 import com.intellij.openapi.vcs.VcsException;
22 import com.intellij.openapi.vfs.VirtualFile;
23 import com.intellij.util.ui.UIUtil;
24 import com.intellij.vcsUtil.VcsUtil;
25 import git4idea.GitUtil;
26 import git4idea.commands.GitCommand;
27 import git4idea.commands.GitSimpleHandler;
28 import git4idea.commands.StringScanner;
29 import git4idea.i18n.GitBundle;
30 import git4idea.ui.GitUIUtil;
32 import javax.swing.*;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.concurrent.atomic.AtomicBoolean;
39 /**
40 * The dialog that displays locally modified files during update process
42 public class GitUpdateLocallyModifiedDialog extends DialogWrapper {
43 /**
44 * The rescan button
46 private JButton myRescanButton;
47 /**
48 * The list of files to revert
50 private JList myFilesList;
52 private JLabel myDescriptionLabel;
53 /**
54 * The git root label
56 private JLabel myGitRoot;
57 /**
58 * The root panel
60 private JPanel myRootPanel;
61 /**
62 * The collection with locally modified files
64 private List<String> myLocallyModifiedFiles;
66 /**
67 * The constructor
69 * @param project the current project
70 * @param root the vcs root
71 * @param locallyModifiedFiles the collection of locally modified files to use
73 protected GitUpdateLocallyModifiedDialog(final Project project, final VirtualFile root, List<String> locallyModifiedFiles) {
74 super(project, true);
75 myLocallyModifiedFiles = locallyModifiedFiles;
76 setTitle(GitBundle.getString("update.locally.modified.title"));
77 myGitRoot.setText(root.getPresentableUrl());
78 myFilesList.setModel(new DefaultListModel());
79 setOKButtonText(GitBundle.getString("update.locally.modified.revert"));
80 syncListModel();
81 myRescanButton.addActionListener(new ActionListener() {
82 public void actionPerformed(ActionEvent e) {
83 myLocallyModifiedFiles.clear();
84 try {
85 scanFiles(project, root, myLocallyModifiedFiles);
87 catch (VcsException ex) {
88 GitUIUtil.showOperationError(project, ex, "Checking for locally modified files");
91 });
92 myDescriptionLabel
93 .setText(GitBundle.message("update.locally.modified.message", ApplicationNamesInfo.getInstance().getFullProductName()));
94 init();
97 /**
98 * Refresh list model according to the current content of the collection
100 private void syncListModel() {
101 DefaultListModel listModel = (DefaultListModel)myFilesList.getModel();
102 listModel.removeAllElements();
103 for (String p : myLocallyModifiedFiles) {
104 listModel.addElement(p);
109 * {@inheritDoc}
111 @Override
112 protected JComponent createCenterPanel() {
113 return myRootPanel;
117 * {@inheritDoc}
119 @Override
120 protected String getDimensionServiceKey() {
121 return getClass().getName();
125 * Scan working tree and detect locally modified files
127 * @param project the project to scan
128 * @param root the root to scan
129 * @param files the collection with files
130 * @throws VcsException if there problem with running git or working tree is dirty in unsupported way
132 private static void scanFiles(Project project, VirtualFile root, List<String> files) throws VcsException {
133 String rootPath = root.getPath();
134 GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF);
135 h.addParameters("--name-status");
136 h.setNoSSH(true);
137 h.setStdoutSuppressed(true);
138 StringScanner s = new StringScanner(h.run());
139 while (s.hasMoreData()) {
140 if (s.isEol()) {
141 s.line();
142 continue;
144 if (s.tryConsume("M\t")) {
145 String path = rootPath + "/" + GitUtil.unescapePath(s.line());
146 files.add(path);
148 else {
149 throw new VcsException("Working tree is dirty in unsupported way: " + s.line());
156 * Show the dialog if needed
158 * @param project the project
159 * @param root the vcs root
160 * @return true if showing is not needed or operation completed successfully
162 public static boolean showIfNeeded(final Project project, final VirtualFile root) {
163 final ArrayList<String> files = new ArrayList<String>();
164 try {
165 scanFiles(project, root, files);
166 final AtomicBoolean rc = new AtomicBoolean(true);
167 if (!files.isEmpty()) {
168 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
169 public void run() {
170 GitUpdateLocallyModifiedDialog d = new GitUpdateLocallyModifiedDialog(project, root, files);
171 d.show();
172 rc.set(d.isOK());
175 if (rc.get()) {
176 if (!files.isEmpty()) {
177 revertFiles(project, root, files);
181 return rc.get();
183 catch (final VcsException e) {
184 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
185 public void run() {
186 GitUIUtil.showOperationError(project, e, "Checking for locally modified files");
189 return false;
194 * Revert files from the list
196 * @param project the project
197 * @param root the vcs root
198 * @param files the files to revert
200 private static void revertFiles(Project project, VirtualFile root, ArrayList<String> files) throws VcsException {
201 GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CHECKOUT);
202 h.endOptions();
203 h.setNoSSH(true);
204 for (String p : files) {
205 h.addRelativePaths(VcsUtil.getFilePath(p));
207 h.run();