From 9a7a71bae78853900ff1726ad94ca8c0944ec156 Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Wed, 22 Jul 2009 20:43:23 +0300 Subject: [PATCH] Various fixes for revert/unrevert --- src/commands/Revert.cpp | 4 +--- src/commands/UnRevert.cpp | 21 +++++++++++++++-- src/hunks/ChangeSet.cpp | 29 +++++++++++++++++++++-- tests/parsediff/TestParseDiff.cpp | 48 ++++++++++++++++++++++++--------------- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/commands/Revert.cpp b/src/commands/Revert.cpp index 4a1ca17..e5ed03e 100644 --- a/src/commands/Revert.cpp +++ b/src/commands/Revert.cpp @@ -44,7 +44,7 @@ AbstractCommand::ReturnCodes Revert::run() { if (! checkInRepository()) return NotInRepo; - moveToRoot( static_cast (CheckFileSystem | PrintError) ); // XXX why is the static cast needed :( + moveToRoot(static_cast(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) */ diff --git a/src/commands/UnRevert.cpp b/src/commands/UnRevert.cpp index b671859..0b47be5 100644 --- a/src/commands/UnRevert.cpp +++ b/src/commands/UnRevert.cpp @@ -1,6 +1,6 @@ /* * This file is part of the vng project - * Copyright (C) 2008 Thomas Zander + * Copyright (C) 2008-2009 Thomas Zander * 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; diff --git a/src/hunks/ChangeSet.cpp b/src/hunks/ChangeSet.cpp index 404aebf..de16127 100644 --- a/src/hunks/ChangeSet.cpp +++ b/src/hunks/ChangeSet.cpp @@ -352,6 +352,8 @@ bool ChangeSet::hasAllHunks() const QList ChangeSet::readGitDiff(QIODevice &git, File *fileToDiff) { QList filesInDiff; + QList newFiles; + QList 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 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 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()) { diff --git a/tests/parsediff/TestParseDiff.cpp b/tests/parsediff/TestParseDiff.cpp index 213ec2c..133895d 100644 --- a/tests/parsediff/TestParseDiff.cpp +++ b/tests/parsediff/TestParseDiff.cpp @@ -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) -- 2.11.4.GIT