fix output and be more lazy
[vng.git] / commands / UnRecord.cpp
blob3056abde1fe2d48ab485c70cad09b1d1e45bfa47
1 /*
2 * This file is part of the vng project
3 * Copyright (C) 2008 Thomas Zander <tzander@trolltech.com>
4 * Copyright (C) 2003-2005 David Roundy
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "UnRecord.h"
21 #include "CommandLineParser.h"
22 #include "Interview.h"
23 #include "GitRunner.h"
24 #include "Logger.h"
25 #include "patches/Commit.h"
26 #include "patches/CommitsCursor.h"
28 #include <QDebug>
30 static const CommandLineOption options[] = {
31 {"--from-match PATTERN", "select changes starting with a patch matching PATTERN"},
32 {"--from-patch REGEXP", "select changes starting with a patch matching REGEXP"},
33 //{"--from-tag REGEXP", "select changes starting with a tag matching REGEXP"},
34 {"-n, --last NUMBER", "select the last NUMBER patches"},
35 {"-a, --all", "select all patches till the first branchpoint found"},
36 {"--match PATTERN", "select patches matching PATTERN"},
37 {"-p, --patches REGEXP", "select patches matching REGEXP"},
38 //{"-t REGEXP,--tags REGEXP", "select tags matching REGEXP"},
39 CommandLineLastOption
42 UnRecord::UnRecord()
43 :AbstractCommand("unrecord")
45 CommandLineParser::addOptionDefinitions(options);
48 QString UnRecord::argumentDescription() const
50 return QString();
53 QString UnRecord::commandDescription() const
55 return "UnRecord does the opposite of record in that it makes the changes from\n"
56 "patches active changes again which you may record or revert later. The\n"
57 "working copy itself will not change.\n";
60 AbstractCommand::ReturnCodes UnRecord::run()
62 if (! checkInRepository())
63 return NotInRepo;
64 if (m_config.isEmptyRepo()) {
65 Logger::error() << "Vng failed: Can not run unrecord on a repo without recorded pathes\n";
66 return Disabled;
69 CommandLineParser *args = CommandLineParser::instance();
71 Commit acceptedCommit;
72 int unrecordCount = 0;
73 bool oneAutoAcceptedPatch = false;
74 if (args->contains("all")) {
75 Commit head("HEAD");
76 Commit commit = head.firstCommitInBranch();
77 if (! commit.isValid()) {
78 Logger::error() << "Vng failed: Could not find the branch point, are you sure you are on a branch?\n";
79 return OtherVngError;
81 acceptedCommit = commit;
82 while(true) {
83 unrecordCount++;
84 if (commit == head)
85 break;
86 commit = commit.next();
87 oneAutoAcceptedPatch = true;
90 else { // use a cursor
91 CommitsCursor cursor;
92 cursor.setUseMatcher(true);
93 if (args->contains("last")) {
94 int count = args->optionArgument("last").toInt();
95 for (int i = 0; i < count && cursor.isValid(); i++) {
96 cursor.setResponse(true);
97 cursor.forward();
100 else {
101 Interview interview(cursor, name());
102 interview.setUsePager(shouldUsePager());
103 if (! interview.start()) {
104 Logger::warn() << "unrecord cancelled." << endl;
105 return Ok;
109 Commit commit = cursor.head();
110 while (true) {
111 if (commit.acceptance() == Vng::Rejected) // can't use this one.
112 break;
113 else if (commit.acceptance() == Vng::Accepted)
114 acceptedCommit = commit;
115 if (commit.previousCommitsCount() == 0) // at first commit.
116 break;
117 if (commit.acceptance() == Vng::Undecided) {
118 if (acceptedCommit.isValid()) // already found a 'yes'.
119 break;
120 oneAutoAcceptedPatch = true;
122 commit = commit.previous()[0];
123 if (unrecordCount >= cursor.oldestCommitAltered())
124 break;
125 unrecordCount++;
127 acceptedCommit = commit;
130 if (!acceptedCommit.isValid()) {
131 Logger::warn() << "Ok, if you don't want to unrecord anything, that's fine!\n";
132 return Ok;
134 if (oneAutoAcceptedPatch) {
135 QString answer = Interview::ask(QString("Do you really want to unrecord %1 patches? ").arg(unrecordCount));
136 if (! (answer.startsWith("y") || answer.startsWith("Y")))
137 return Ok;
139 if (dryRun())
140 return Ok;
142 QProcess git;
143 QStringList arguments;
144 arguments << "update-ref" << "HEAD" << acceptedCommit.commitTreeIsm();
145 GitRunner runner(git, arguments);
146 AbstractCommand::ReturnCodes rc = runner.start(GitRunner::WaitUntilFinished);
147 if (rc != Ok) {
148 Logger::error() << "Failed to update the ref, sorry.\n";
149 return rc;
151 // TODO find all files that were added in the commit(s) we just reverted. The files are there, but
152 // vng / git doesn't know about them. So we need to add them explicitly.
154 return Ok;