653e9694a694 — Chris Cannam 10 years ago
Use regexes for anchored filenames (i.e. "this file only" and directory); report outcome of ignore to user
5 files changed, 67 insertions(+), 30 deletions(-)

M .hgignore
M src/filestates.cpp
M src/filestates.h
M src/filestatuswidget.cpp
M src/mainwindow.cpp
M .hgignore +2 -0
@@ 21,3 21,5 @@ Makefile.Release
 .DS_Store
 *.pdb
 
+re:^EasyMercurial
+re:^kdiff3

          
M src/filestates.cpp +5 -0
@@ 137,6 137,11 @@ FileStates::State FileStates::stateOf(QS
     return Unknown;
 }
 
+bool FileStates::isKnown(QString file) const
+{
+    return (m_stateMap.contains(file));
+}
+
 FileStates::Activities FileStates::activitiesSupportedBy(State s)
 {
     Activities a;

          
M src/filestates.h +1 -0
@@ 50,6 50,7 @@ public:
     bool isInState(QString file, State s) const;
     QStringList filesInState(State s) const;
     State stateOf(QString file) const;
+    bool isKnown(QString file) const;
 
     enum Activity {
 

          
M src/filestatuswidget.cpp +2 -1
@@ 68,7 68,8 @@ FileStatusWidget::FileStatusWidget(QWidg
     m_actionLabels[FileStates::RedoMerge] = tr("Redo merge");
     m_actionLabels[FileStates::MarkResolved] = tr("Mark conflict as resolved");
     m_actionLabels[FileStates::Ignore] = tr("Ignore...");
-    m_actionLabels[FileStates::UnIgnore] = tr("Stop ignoring...");
+    // Unignore is too difficult in fact, so we just offer to edit the hgignore
+    m_actionLabels[FileStates::UnIgnore] = tr("Edit .hgignore File");
 
     m_descriptions[FileStates::Clean] = tr("You have not changed these files.");
     m_descriptions[FileStates::Modified] = tr("You have changed these files since you last committed them.");

          
M src/mainwindow.cpp +57 -29
@@ 588,6 588,17 @@ void MainWindow::hgEditIgnore()
     m_runner->requestAction(action);
 }
 
+static QString regexEscape(QString filename)
+{
+    return filename
+        .replace(".", "\\.")
+        .replace("[", "\\[")
+        .replace("]", "\\]")
+        .replace("(", "\\(")
+        .replace(")", "\\)")
+        .replace("?", "\\?");
+}
+
 void MainWindow::hgIgnoreFiles(QStringList files)
 {
     if (!QDir(m_workFolderPath).exists() || files.empty()) return;

          
@@ 626,7 637,7 @@ void MainWindow::hgIgnoreFiles(QStringLi
             directory = d;
         }
     }
-    if (dirCount != 1) directory = "";
+    if (dirCount != 1 || directory == ".") directory = "";
 
     HgIgnoreDialog::IgnoreType itype =
         HgIgnoreDialog::confirmIgnore

          
@@ 634,6 645,8 @@ void MainWindow::hgIgnoreFiles(QStringLi
 
     DEBUG << "hgIgnoreFiles: Ignore type is " << itype << endl;
 
+    if (itype == HgIgnoreDialog::IgnoreNothing) return;
+
     // Now, .hgignore can be switched from regex to glob syntax
     // part-way through -- and glob is much simpler for us, so we
     // should do that if it's in regex mode at the end of the file.

          
@@ 673,48 686,63 @@ void MainWindow::hgIgnoreFiles(QStringLi
         out << "syntax: glob" << endl;
     }
 
-    //!!! should we be warning the user which files this will mean
-    //!!! they ignore? -- probably
-
+    QString info = "<qt><h3>" + tr("Ignored files") + "</h3><p>";
+    info += tr("The following lines have been added to the .hgignore file for this working copy:");
+    info += "</p><code>";
+
+    QStringList args;
     if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenSuffixes) {
-        foreach (QString s, suffixes) {
-            out << "*." << s << endl;
-        }
+        args = QStringList::fromSet(suffixes);
     } else if (itype == HgIgnoreDialog::IgnoreGivenFilesOnly) {
-        // The default for glob seems to be to ignore the file
-        // anywhere -- anchor the path to / to make it specific to
-        // this file only
-        //!!! check this!
-        //!!! ... no, it doesn't work. does this mean we need regex syntax?
+        args = files;
+    } else if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenNames) {
+        QSet<QString> names;
         foreach (QString f, files) {
-            out << "/" + f << endl;
+            names << QFileInfo(f).fileName();
         }
-    } else if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenNames) {
-        foreach (QString f, files) {
-            out << QFileInfo(f).fileName() << endl;
+        args = QStringList::fromSet(names);
+    } else if (itype == HgIgnoreDialog::IgnoreWholeDirectory) {
+        args << directory;
+    }
+
+    bool first = true;
+
+    foreach (QString a, args) {
+        QString line;
+        if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenSuffixes) {
+            line = "*." + a;
+        } else if (itype == HgIgnoreDialog::IgnoreGivenFilesOnly) {
+            // Doesn't seem to be possible to do this with a glob,
+            // because the glob is always unanchored and there is no
+            // equivalent of ^ to anchor it
+            line = "re:^" + regexEscape(a);
+        } else if (itype == HgIgnoreDialog::IgnoreAllFilesOfGivenNames) {
+            line = a;
+        } else if (itype == HgIgnoreDialog::IgnoreWholeDirectory) {
+            line = "re:^" + regexEscape(a) + "/";
         }
-    } else if (itype == HgIgnoreDialog::IgnoreWholeDirectory) {
-        out << directory + "/" << endl;
+        if (line != "") {
+            out << line << endl;
+            if (!first) info += "<br>";
+            first = false;
+            info += xmlEncode(line);
+        }
     }
 
     f.close();
     
-
-    //!!! report, and offer to edit .hgignore now
-
-    // (tell the user at least what lines have been added to the
-    // hgignore file and how to edit it)
-    
-    // (also, if the hgignore is not tracked, suggest that they add
-    // it)
-    
+    info += "</code></qt>";
+
+    QMessageBox::information(this, tr("Ignored files"),
+                             info);
+
     hgRefresh();
 }
 
 void MainWindow::hgUnIgnoreFiles(QStringList files)
 {
-    //!!! not implemented yet
-    DEBUG << "MainWindow::hgUnIgnoreFiles: Not implemented" << endl;
+    // Not implemented: edit the .hgignore instead
+    hgEditIgnore();
 }
 
 QString MainWindow::getDiffBinaryName()