#include #include #include #include #include "commandupdate.h" #include "logger.h" int CommandUpdate::handle(QStringList arguments) { QCommandLineParser parser; parser.addOptions( {{{"v", "verbose"}, "Print path of the files while updating them"}, {{"n", "dry-run"}, "Only print which files would be updated, don't actually update them"}, {"pattern", "Only consider to update files in the index matching the pattern, e. g. */.git/*.", "pattern"}, {{"d", "delete"}, "If a file does not exist anymore, delete it"}, {{"c", "continue"}, "Continue adding files, don't exit on first error. If this option is not given, looqs will exit asap, but " "it's possible that a few files will still be processed. " "Set -t 1 to avoid this behavior, but processing will be slower."}, {{"a", "all"}, "On error, no files should be updated, even already processed ones"}, {{"t", "threads"}, "Number of threads to use.", "threads"} }); parser.addHelpOption(); parser.addPositionalArgument("update", "Checks files for changes and updates them", "update"); parser.process(arguments); bool keepGoing = parser.isSet("continue"); bool verbose = parser.isSet("verbose"); bool deleteMissing = parser.isSet("delete"); bool dryRun = parser.isSet("dry-run"); QString pattern = parser.value("pattern"); if(parser.isSet("all")) { throw LooqsGeneralException("To be implemented"); } if(parser.isSet("threads")) { QString threadsCount = parser.value("threads"); QThreadPool::globalInstance()->setMaxThreadCount(threadsCount.toInt()); } FileSaver saver(*this->dbService); QVector files; int offset = 0; int limit = 1000; int processedRows = dbService->getFiles(files, pattern, offset, limit); while(processedRows > 0) { QVector filePathsToUpdate; for(FileData &fileData : files) { QFileInfo fileInfo(fileData.absPath); if(fileInfo.exists() && fileInfo.isFile()) { if(fileInfo.lastModified().toSecsSinceEpoch() != fileData.mtime) { if(!dryRun) { filePathsToUpdate.append(fileData.absPath); } else { Logger::info() << "Would update" << fileData.absPath << Qt::endl; } } } else { if(deleteMissing) { if(!dryRun) { if(!this->dbService->deleteFile(fileData.absPath)) { Logger::error() << "Error: Failed to delete" << fileData.absPath << "from databas" << Qt::endl; if(!keepGoing) { return 1; } } if(verbose) { Logger::info() << "Deleted" << fileData.absPath << Qt::endl; } } else { Logger::info() << "Would delete" << fileData.absPath << Qt::endl; } } } } int updatedFilesCount = saver.updateFiles(filePathsToUpdate, keepGoing, verbose); int shouldHaveUpdatedCount = filePathsToUpdate.size(); if(updatedFilesCount != shouldHaveUpdatedCount) { if(!keepGoing) { Logger::error() << "Failed to update all files selected for updating. Updated" << updatedFilesCount << "out of" << shouldHaveUpdatedCount << "selected for upating" << Qt::endl; return 1; } } offset += limit; files.clear(); processedRows = this->dbService->getFiles(files, pattern, offset, limit); } return 0; }