docs
[vng.git] / Move.cpp
blobe411ddefee6cdedcfdfa21a6f177130b78bd778a
1 /*
2 * This file is part of the vng project
3 * Copyright (C) 2008 Thomas Zander <tzander@trolltech.com>
4 * Copyright (C) 2002-2004 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/>.
20 #include "Move.h"
21 #include "CommandLineParser.h"
22 #include "Logger.h"
23 #include "GitRunner.h"
24 #include "hunks/File.h"
26 #include <QPair>
28 Move::Move()
29 : AbstractCommand("mv")
31 CommandLineParser::setArgumentDefinition("mv [FILE or DIRECTORY]" );
34 AbstractCommand::ReturnCodes Move::run()
36 if (! checkInRepository())
37 return NotInRepo;
38 moveToRoot();
39 // Move in git is really remove and add. Git will auto detect that being a move.
41 typedef QPair<QString, QString> RenamePair;
43 QList<RenamePair> renamePairs;
44 QStringList files = rebasedArguments();
45 if (files.count() < 2) { // not sure what that would mean...
46 Logger::error() << "Vng failed: you must specify at least two arguments for mv\n";
47 return InvalidOptions;
49 QString target = files.takeLast();
50 QFileInfo path(target);
51 if (files.count() > 1) { // multiple files into a dir.
52 if (! path.isDir()) {
53 Logger::error() << "Vng failed: The target directory '" << target <<
54 "` does not seem to be an existing directory\n";
55 return InvalidOptions;
58 else { // target is a file
59 if(File::fileKnownToGit(path)) {
60 Logger::error() << "Vng failed: The file named '"<< target <<
61 "` already exists in working directory.\n";
62 return InvalidOptions;
65 foreach (QString arg, files) {
66 if (canMoveFile(arg)) {
67 if (files.count() > 1)
68 renamePairs.append(qMakePair(arg, target + QDir::separator() + arg));
69 else
70 renamePairs.append(qMakePair(arg, target));
74 if (dryRun())
75 return Ok;
77 QProcess git;
78 QStringList arguments;
79 arguments << "update-index" << "--add" << "--remove";
80 foreach(RenamePair p, renamePairs) {
81 Logger::debug() << "rename " << p.first << " => " << p.second << endl;
82 if (QFile::rename(p.first, p.second))
83 arguments << p.first << p.second;
84 else
85 Logger::error() << "Vng failed: Could not rename '" << p.first << "` to '" <<
86 p.second << "`, check permissions\n";
89 if (arguments.count() == 3) { // no files!
90 Logger::info() << "Nothing done\n";
91 return Ok;
93 GitRunner runner(git, arguments);
94 return runner.start(GitRunner::WaitUntilFinished);
97 bool Move::canMoveFile(const QString &file)
99 QFileInfo path(file);
100 if (path.exists()) {
101 if (path.isFile()) {
102 bool knownToGit = File::fileKnownToGit(path);
103 if (! knownToGit) {
104 Logger::info() << "Not moving file, its not added in the repository: `" << path.filePath() << "'\n";
105 return false;
107 return true;
109 else if (path.isSymLink())
110 Logger::info() << "Ignoring symbolic link '" << path.filePath() << "'" << endl;
111 else
112 Logger::info() << "Ignoring non-file object '" << path.filePath() << "'" << endl;
114 else
115 Logger::error() << "Can not move non existing' " << path.filePath() << "'" << endl;
116 return false;
119 QString Move::argumentDescription() const
121 return "<FILE or DIRECTORY>";
124 QString Move::commandDescription() const
126 return "Vng mv can be called whenever you want to move files or\n"
127 "directories. Unlike remove, mv actually performs the move itself in your\n"
128 "working copy.\n";