git4idea: Added support for checking locally modified files
[fedora-idea.git] / plugins / git4idea / src / git4idea / update / GitUpdateLocallyModifiedDialog.java
blob9cbee3b9aaeb79b92df653bd66a45c5597bc3e0f
1 package git4idea.update;
3 import com.intellij.openapi.project.Project;
4 import com.intellij.openapi.ui.DialogWrapper;
5 import com.intellij.openapi.vcs.VcsException;
6 import com.intellij.openapi.vfs.VirtualFile;
7 import com.intellij.util.ui.UIUtil;
8 import com.intellij.vcsUtil.VcsUtil;
9 import git4idea.GitUtil;
10 import git4idea.commands.GitHandler;
11 import git4idea.commands.GitSimpleHandler;
12 import git4idea.commands.StringScanner;
13 import git4idea.i18n.GitBundle;
14 import git4idea.ui.GitUIUtil;
16 import javax.swing.*;
17 import java.awt.event.ActionEvent;
18 import java.awt.event.ActionListener;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.concurrent.atomic.AtomicBoolean;
23 /**
24 * The dialog that displays locally modified files during update process
26 public class GitUpdateLocallyModifiedDialog extends DialogWrapper {
27 /**
28 * The rescan button
30 private JButton myRescanButton;
31 /**
32 * The list of files to revert
34 private JList myFilesList;
35 /**
36 * The git root label
38 private JLabel myGitRoot;
39 /**
40 * The root panel
42 private JPanel myRootPanel;
43 /**
44 * The vcs root
46 private VirtualFile myRoot;
47 /**
48 * The collection with locally modified files
50 private List<String> myLocallyModifiedFiles;
52 /**
53 * The constructor
54 * @param project the current project
55 * @param root the vcs root
56 * @param locallyModifiedFiles the collection of locally modified files to use
58 protected GitUpdateLocallyModifiedDialog(final Project project, final VirtualFile root, List<String> locallyModifiedFiles) {
59 super(project, true);
60 myRoot = root;
61 myLocallyModifiedFiles = locallyModifiedFiles;
62 setTitle(GitBundle.getString("update.locally.modified.title"));
63 myGitRoot.setText(myRoot.getPresentableUrl());
64 myFilesList.setModel(new DefaultListModel());
65 setOKButtonText(GitBundle.getString("update.locally.modified.revert"));
66 syncListModel();
67 myRescanButton.addActionListener(new ActionListener() {
68 public void actionPerformed(ActionEvent e) {
69 myLocallyModifiedFiles.clear();
70 try {
71 scanFiles(project, root, myLocallyModifiedFiles);
73 catch (VcsException ex) {
74 GitUIUtil.showOperationError(project, ex, "Checking for locally modified files");
77 });
78 init();
81 /**
82 * Refresh list model according to the current content of the collection
84 private void syncListModel() {
85 DefaultListModel listModel = (DefaultListModel)myFilesList.getModel();
86 listModel.removeAllElements();
87 for(String p : myLocallyModifiedFiles) {
88 listModel.addElement(p);
92 /**
93 * {@inheritDoc}
95 @Override
96 protected JComponent createCenterPanel() {
97 return myRootPanel;
101 * {@inheritDoc}
103 @Override
104 protected String getDimensionServiceKey() {
105 return getClass().getName();
109 * Scan working tree and detect locally modified files
111 * @param project the project to scan
112 * @param root the root to scan
113 * @param files the collection with files
114 * @throws VcsException if there problem with running git or working tree is dirty in unsupported way
116 private static void scanFiles(Project project, VirtualFile root, List<String> files) throws VcsException {
117 String rootPath = root.getPath();
118 GitSimpleHandler h = new GitSimpleHandler(project, root, GitHandler.DIFF);
119 h.addParameters("--name-status");
120 h.setNoSSH(true);
121 h.setStdoutSuppressed(true);
122 StringScanner s = new StringScanner(h.run());
123 while(s.hasMoreData()) {
124 if(s.isEol()) {
125 s.line();
126 continue;
128 if(s.tryConsume("M\t")) {
129 String path = rootPath + "/" + GitUtil.unescapePath(s.line());
130 files.add(path);
131 } else {
132 throw new VcsException("Working tree is dirty in unsupported way: "+s.line());
139 * Show the dialog if needed
141 * @param project the project
142 * @param root the vcs root
143 * @return true if showing is not needed or operation completed successfully
145 public static boolean showIfNeeded(final Project project, final VirtualFile root) {
146 final ArrayList<String> files = new ArrayList<String>();
147 try {
148 scanFiles(project, root, files);
149 final AtomicBoolean rc = new AtomicBoolean(true);
150 if(!files.isEmpty()) {
151 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
152 public void run() {
153 GitUpdateLocallyModifiedDialog d = new GitUpdateLocallyModifiedDialog(project, root, files);
154 d.show();
155 rc.set(d.isOK());
158 if(rc.get()) {
159 if(!files.isEmpty()) {
160 revertFiles(project, root, files);
164 return rc.get();
166 catch (final VcsException e) {
167 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
168 public void run() {
169 GitUIUtil.showOperationError(project, e, "Checking for locally modified files");
172 return false;
177 * Revert files from the list
179 * @param project the project
180 * @param root the vcs root
181 * @param files the files to revert
183 private static void revertFiles(Project project, VirtualFile root, ArrayList<String> files) throws VcsException {
184 GitSimpleHandler h = new GitSimpleHandler(project, root, GitHandler.CHECKOUT);
185 h.endOptions();
186 h.setNoSSH(true);
187 for(String p : files) {
188 h.addRelativePaths(VcsUtil.getFilePath(p));
190 h.run();