Various fixes for revert/unrevert
authorThomas Zander <thomas.zander@trolltech.com>
Wed, 22 Jul 2009 17:43:23 +0000 (22 20:43 +0300)
committerThomas Zander <thomas.zander@trolltech.com>
Wed, 22 Jul 2009 17:43:23 +0000 (22 20:43 +0300)
src/commands/Revert.cpp
src/commands/UnRevert.cpp
src/hunks/ChangeSet.cpp
tests/parsediff/TestParseDiff.cpp

index 4a1ca17..e5ed03e 100644 (file)
@@ -44,7 +44,7 @@ AbstractCommand::ReturnCodes Revert::run()
 {
     if (! checkInRepository())
         return NotInRepo;
-    moveToRoot( static_cast <RebaseOptions> (CheckFileSystem | PrintError) ); // XXX why is the static cast needed :(
+    moveToRoot(static_cast<RebaseOptions>(CheckFileSystem | PrintError));
 
     CommandLineParser *args = CommandLineParser::instance();
     const bool all = (m_config.contains("all") && !args->contains("interactive")) || args->contains("all");
@@ -138,7 +138,5 @@ QString  Revert::patchFileName()
 }
 
 /*
-    TODO
-    make sure we can revert file-renames too and file adds too
     check how we handle binary patches (i.e. no dataloss)
 */
index b671859..0b47be5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of the vng project
- * Copyright (C) 2008 Thomas Zander <tzander@trolltech.com>
+ * Copyright (C) 2008-2009 Thomas Zander <tzander@trolltech.com>
  * Copyright (C) 2003-2005 David Roundy
  *
  * This program is free software: you can redistribute it and/or modify
@@ -87,7 +87,7 @@ AbstractCommand::ReturnCodes UnRevert::run()
         arguments << "apply" << "--apply" << patchFile.fileName();
         GitRunner runner(git, arguments);
         AbstractCommand::ReturnCodes rc = runner.start(GitRunner::WaitUntilFinished);
-        patchFile.remove();
+        //patchFile.remove();
         if (rc != 0) {
             Logger::error() << "Unreverting failed on one or more patches";
             if (Logger::verbosity() < Logger::Chatty)
@@ -100,6 +100,23 @@ AbstractCommand::ReturnCodes UnRevert::run()
         changeSet.writeDiff(file, all ? ChangeSet::AllHunks : ChangeSet::InvertedUserSelection);
         if (file.size() == 0)
             file.remove();
+
+        arguments.clear();
+        arguments << QLatin1String("update-index") << QLatin1String("--add");
+        for (int i = 0; i < changeSet.count(); ++i) {
+            File file = changeSet.file(i);
+            if ((all || file.renameAcceptance() == Vng::Accepted)
+                    && file.oldFileName() != file.fileName()) {
+                if (!file.oldFileName().isEmpty())
+                    arguments << file.fileName();
+            } else if (all || file.changesAcceptance() == Vng::Accepted) {
+                arguments << file.fileName();
+            }
+        }
+        if (arguments.count() > 2) {
+            runner.setArguments(arguments);
+            runner.start(GitRunner::WaitUntilFinished);
+        }
     }
     Logger::warn() << "Finished unreverting." << endl;
     return Ok;
index 404aebf..de16127 100644 (file)
@@ -352,6 +352,8 @@ bool ChangeSet::hasAllHunks() const
 QList<File> ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff)
 {
     QList<File> filesInDiff;
+    QList<File> newFiles;
+    QList<File> removedFiles;
 
     // parse the output and create objects for each hunk. (note how that can be made multi-threading)
     //  we have to have the filename in the hunk too to allow skipping a whole hunk
@@ -370,8 +372,14 @@ QList<File> ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff)
         if (lineLength == -1 || state == Empty) {
             file.addHunk(hunk);
             hunk = Hunk();
-            if (file.isValid())
-                filesInDiff << file;
+            if (file.isValid()) {
+                if (file.oldFileName().isEmpty())
+                    newFiles << file;
+                else if (file.fileName().isEmpty())
+                    removedFiles << file;
+                else
+                    filesInDiff << file;
+            }
             if (fileToDiff)
                 file = File(*fileToDiff);
             else
@@ -452,6 +460,22 @@ QList<File> ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff)
         }
     }
     git.close();
+
+    // try to find out if there are renames
+    foreach (File removedFile, removedFiles) {
+        foreach (File addedFile, newFiles) {
+            if (!addedFile.sha1().isEmpty() && removedFile.oldSha1() == addedFile.sha1()) {
+                // TODO if this is a partial sha1 we may want to check some of the content
+                newFiles.removeAll(addedFile);
+                addedFile.setOldSha1(removedFile.oldSha1());
+                addedFile.setOldFileName(removedFile.oldFileName());
+                addedFile.setOldProtection(removedFile.oldProtection());
+                filesInDiff << addedFile;
+                break;
+            }
+        }
+    }
+
     return filesInDiff;
 }
 
@@ -478,6 +502,7 @@ void ChangeSet::writeDiff(QIODevice &outDevice, ChangeSet::Selection selection)
                 && !file.oldFileName().isEmpty()
                 && file.oldFileName() != file.fileName()) {
             writeRenameDiff(diff, file);
+            continue;
         }
 
         foreach(Hunk hunk, file.hunks()) {
index 213ec2c..133895d 100644 (file)
@@ -18,7 +18,7 @@ void TestParseDiff::testBasis()
         "+++ /dev/null\n"
         "@@ -1,674 +0,0 @@\n"
         "-file content2\n"
-        "\n"
+        " \n"
         "diff --git a/todo b/todo\n"
         "index a4c7321..a0417af 100644\n"
         "--- a/todo\n"
@@ -31,7 +31,19 @@ void TestParseDiff::testBasis()
         "-      query         Query information which is stored by vng.\n"
         "       unpull        Opposite of pull; unsafe if patch is not in remote repository.\n"
         "       obliterate    Delete selected patches from the repository. (UNSAFE!)\n"
-        "       send          Send by email a bundle of one or more patches.\n";
+        "       send          Send by email a bundle of one or more patches.\n"
+        "--- a/README\n"
+        "+++ b/README\n"
+        "@@ -6,8 +6,6 @@ Compiling\n"
+        " To compile this project you need Qt4.4 or later, only the qt-core library is used.\n"
+        " \n"
+        " To generate a makefile call the 'qmake' command in the vng directory.  Make\n"
+        "-sure you call the one from the right Qt release.\n"
+        "-Some linux distros ship this command names 'qmake-qt4'\n"
+        " \n"
+        " After calling qmake, compile the project like you would any other.  This is\n"
+        " platform dependent and could be \"nmake\", \"make\" etc.\n"
+        " \n";
 
     QByteArray bytes(diff);
     QBuffer buffer(&bytes, 0);
@@ -40,28 +52,28 @@ void TestParseDiff::testBasis()
     QCOMPARE(answer.count(), 3);
 
     File file1 = answer[0];
-    QVERIFY(file1.oldFileName().isEmpty());
-    QCOMPARE(file1.fileName(), QByteArray("FOO"));
-    QCOMPARE(file1.sha1(), QString("94a9ed0"));
-    QCOMPARE(file1.oldSha1(), QString("0000000"));
+    QCOMPARE(file1.fileName(), QByteArray("todo"));
+    QCOMPARE(file1.oldFileName(), QByteArray("todo"));
+    QCOMPARE(file1.oldSha1(), QString("a4c7321"));
+    QCOMPARE(file1.sha1(), QString("a0417af"));
     QCOMPARE(file1.protection(), QString("100644"));
     QCOMPARE(file1.hunks().count(), 1);
 
     File file2 = answer[1];
-    QVERIFY(file2.fileName().isEmpty());
-    QCOMPARE(file2.oldFileName(), QByteArray("BAR"));
-    QCOMPARE(file2.oldSha1(), QString("94a9ed0"));
-    QCOMPARE(file2.sha1(), QString("0000000"));
-    QCOMPARE(file2.protection(), QString("100644"));
+    QCOMPARE(file2.oldFileName(), QByteArray("README"));
+    QCOMPARE(file2.fileName(), QByteArray("README"));
+    QCOMPARE(file2.sha1(), QString());
+    QCOMPARE(file2.oldSha1(), QString());
+    QCOMPARE(file2.protection(), QString());
     QCOMPARE(file2.hunks().count(), 1);
 
-    File file3 = answer[2];
-    QCOMPARE(file3.fileName(), QByteArray("todo"));
-    QCOMPARE(file3.oldFileName(), QByteArray("todo"));
-    QCOMPARE(file3.oldSha1(), QString("a4c7321"));
-    QCOMPARE(file3.sha1(), QString("a0417af"));
-    QCOMPARE(file3.protection(), QString("100644"));
-    QCOMPARE(file3.hunks().count(), 1);
+    File renamed = answer.last(); // renamed files go at the end..
+    QCOMPARE(renamed.oldFileName(), QByteArray("BAR"));
+    QCOMPARE(renamed.fileName(), QByteArray("FOO"));
+    QCOMPARE(renamed.sha1(), QString("94a9ed0"));
+    QCOMPARE(renamed.oldSha1(), QString("94a9ed0"));
+    QCOMPARE(renamed.protection(), QString("100644"));
+    QCOMPARE(renamed.hunks().count(), 1);
 }
 
 QTEST_MAIN(TestParseDiff)