CommandDelete: Rework deletion logic

Allow deleting files from index which still exist
on the fileystem without passing their path to "qss delete".

Thus: "qss delete --deleted" deletes all files which
don't exist anymore.

Also, fix some bugs in offset calculation.
This commit is contained in:
Albert S. 2020-08-30 18:12:42 +02:00
parent 1455d8ac1b
commit a6f73d724a
2 changed files with 94 additions and 76 deletions

View File

@ -7,47 +7,63 @@
#include "commanddelete.h" #include "commanddelete.h"
#include "logger.h" #include "logger.h"
int CommandDelete::removeNonExistent(bool verbose, bool dryRun, QString pattern) int CommandDelete::remove(QString pattern, bool onlyDeleted, bool verbose, bool dryRun)
{ {
int offset = 0; int deleted = 0;
int limit = 1000; int offset = 0;
QVector<FileData> files; int limit = 1000;
int processedRows = this->dbService->getFiles(files, pattern, 0, limit); QVector<FileData> files;
while(processedRows > 0 ) int processedRows = this->dbService->getFiles(files, pattern, 0, limit);
{ while(processedRows > 0 )
for(FileData &file : files) {
{ for(FileData &file : files)
QFileInfo fileInfo(file.absPath); {
if(!fileInfo.exists()) if(onlyDeleted && QFileInfo::exists(file.absPath))
{ {
if(!dryRun) if(verbose)
{ {
if(this->dbService->deleteFile(file.absPath)) Logger::info() << "Skipping " << file.absPath << " as the file exists on the file system" << endl;
{ }
if(verbose) }
{ else
Logger::info() << "Deleted" << file.absPath << endl; {
} if(!dryRun)
} {
else if(this->dbService->deleteFile(file.absPath))
{ {
Logger::error()<< "Failed to delete:" << file.absPath << ", exiting." << endl if(verbose)
; {
return 1; Logger::info() << "Deleted" << file.absPath << endl;
} }
} ++deleted;
else }
{ else
Logger::info() << "Would delete " << file.absPath << endl; {
} Logger::error()<< "Failed to delete:" << file.absPath << ", exiting." << endl;
} return 1;
} }
}
else
{
Logger::info() << "Would delete " << file.absPath << endl;
}
}
}
if(dryRun)
{
offset += limit;
}
else
{
offset = offset + limit - deleted;
}
files.clear();
processedRows = this->dbService->getFiles(files, pattern, offset, limit);
deleted = 0;
}
return 0;
}
offset += limit;
processedRows = this->dbService->getFiles(files, pattern, offset, limit);
}
return 0;
}
int CommandDelete::removePaths(const QStringList &paths, bool verbose, bool dryRun) int CommandDelete::removePaths(const QStringList &paths, bool verbose, bool dryRun)
{ {
@ -86,42 +102,44 @@ int CommandDelete::removePaths(const QStringList &paths, bool verbose, bool dryR
int CommandDelete::handle(QStringList arguments) int CommandDelete::handle(QStringList arguments)
{ {
QCommandLineParser parser; QCommandLineParser parser;
parser.addOptions({ parser.addOptions({
{ { "v", "verbose" }, "Print path of the files while deleting them" }, { { "v", "verbose" }, "Print path of the files while deleting them" },
{ { "n", "dry-run"}, "Only print which files would be deleted from the database, don't delete them"}, { { "n", "dry-run"}, "Only print which files would be deleted from the database, don't delete them"},
{ "pattern", "Only delete files from index matching the pattern, e. g. */.git/*. Only applies to --deleted or standalone.", "pattern" }, { "pattern", "Only delete files from index matching the pattern, e. g. */.git/*. Can be used to restrict --deleted or standalone.", "pattern" },
{ "deleted", "Delete all files from the index that don't exist anymore" } { "deleted", "Delete all files from the index that don't exist anymore. Can be restricted by --pattern." }
}); });
parser.addHelpOption(); parser.addHelpOption();
parser.addPositionalArgument("delete", "Delete paths from the index", "delete [paths...]"); parser.addPositionalArgument("delete", "Delete paths from the index", "delete [paths...]");
parser.process(arguments); parser.process(arguments);
bool verbose = parser.isSet("verbose"); bool verbose = parser.isSet("verbose");
bool dryRun = parser.isSet("dry-run"); bool dryRun = parser.isSet("dry-run");
QString pattern = parser.value("pattern"); bool deleted = parser.isSet("deleted");
if(parser.isSet("deleted")) QString pattern = parser.value("pattern");
{
int result = removeNonExistent(verbose, dryRun, pattern);
if(result != 0)
{
return result;
}
}
QStringList files = parser.positionalArguments(); if(deleted || ! pattern.isEmpty())
if(files.length() > 0) {
{ int result = this->remove(pattern, deleted, verbose, dryRun);
int result = removePaths(files, verbose, dryRun); if(result != 0)
if(result != 0) {
{ Logger::error() << "Removal operation did not succeed" << endl;
return result; return result;
} }
} }
return 0;
QStringList files = parser.positionalArguments();
if(files.length() > 0)
{
int result = removePaths(files, verbose, dryRun);
if(result != 0)
{
return result;
}
}
return 0;
} }

View File

@ -5,12 +5,12 @@
class CommandDelete : public Command class CommandDelete : public Command
{ {
public: public:
using Command::Command; using Command::Command;
int handle(QStringList arguments) override; int handle(QStringList arguments) override;
private: private:
int removeNonExistent(bool verbose, bool dryRun, QString pattern); int remove(QString pattern, bool onlyDeleted, bool verbose, bool dryRun);
int removePaths(const QStringList &paths, bool verbose, bool dryRun); int removePaths(const QStringList &paths, bool verbose, bool dryRun);
}; };
#endif // COMMANDDELETE_H #endif // COMMANDDELETE_H