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:
		| @@ -7,47 +7,63 @@ | ||||
| #include "commanddelete.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 limit = 1000; | ||||
|     QVector<FileData> files; | ||||
|     int processedRows = this->dbService->getFiles(files, pattern, 0, limit); | ||||
|     while(processedRows > 0 ) | ||||
|     { | ||||
|         for(FileData &file : files) | ||||
|         { | ||||
|                 QFileInfo fileInfo(file.absPath); | ||||
|                 if(!fileInfo.exists()) | ||||
|                 { | ||||
|                     if(!dryRun) | ||||
|                     { | ||||
|                         if(this->dbService->deleteFile(file.absPath)) | ||||
|                         { | ||||
|                             if(verbose) | ||||
|                             { | ||||
|                                 Logger::info() << "Deleted" << file.absPath << endl; | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             Logger::error()<< "Failed to delete:" << file.absPath << ", exiting." << endl | ||||
|                                              ; | ||||
|                             return 1; | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         Logger::info() << "Would delete " << file.absPath << endl; | ||||
|                     } | ||||
|                 } | ||||
|         } | ||||
| 	int deleted = 0; | ||||
| 	int offset = 0; | ||||
| 	int limit = 1000; | ||||
| 	QVector<FileData> files; | ||||
| 	int processedRows = this->dbService->getFiles(files, pattern, 0, limit); | ||||
| 	while(processedRows > 0 ) | ||||
| 	{ | ||||
| 		for(FileData &file : files) | ||||
| 		{ | ||||
| 			if(onlyDeleted && QFileInfo::exists(file.absPath)) | ||||
| 			{ | ||||
| 				if(verbose) | ||||
| 				{ | ||||
| 					Logger::info() << "Skipping " << file.absPath << " as the file exists on the file system" << endl; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if(!dryRun) | ||||
| 				{ | ||||
| 					if(this->dbService->deleteFile(file.absPath)) | ||||
| 					{ | ||||
| 						if(verbose) | ||||
| 						{ | ||||
| 							Logger::info() << "Deleted" << file.absPath << endl; | ||||
| 						} | ||||
| 						++deleted; | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						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) | ||||
| { | ||||
| @@ -86,42 +102,44 @@ int CommandDelete::removePaths(const QStringList &paths, bool verbose, bool dryR | ||||
|  | ||||
| int CommandDelete::handle(QStringList arguments) | ||||
| { | ||||
|     QCommandLineParser parser; | ||||
|     parser.addOptions({ | ||||
|                           { { "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"}, | ||||
|                           { "pattern", "Only delete files from index matching the pattern, e. g. */.git/*. Only applies to --deleted or standalone.", "pattern" }, | ||||
|                           { "deleted", "Delete all files from the index that don't exist anymore" } | ||||
|                       }); | ||||
| 	QCommandLineParser parser; | ||||
| 	parser.addOptions({ | ||||
| 						  { { "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"}, | ||||
| 						  { "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. Can be restricted by --pattern." } | ||||
| 					  }); | ||||
|  | ||||
|     parser.addHelpOption(); | ||||
|     parser.addPositionalArgument("delete", "Delete paths from the index", "delete [paths...]"); | ||||
| 	parser.addHelpOption(); | ||||
| 	parser.addPositionalArgument("delete", "Delete paths from the index", "delete [paths...]"); | ||||
|  | ||||
|     parser.process(arguments); | ||||
|     bool verbose = parser.isSet("verbose"); | ||||
|     bool dryRun = parser.isSet("dry-run"); | ||||
|     QString pattern = parser.value("pattern"); | ||||
|     if(parser.isSet("deleted")) | ||||
|     { | ||||
| 	parser.process(arguments); | ||||
| 	bool verbose = parser.isSet("verbose"); | ||||
| 	bool dryRun = parser.isSet("dry-run"); | ||||
| 	bool deleted = parser.isSet("deleted"); | ||||
| 	QString pattern = parser.value("pattern"); | ||||
|  | ||||
|         int result = removeNonExistent(verbose, dryRun, pattern); | ||||
|         if(result != 0) | ||||
|         { | ||||
|             return result; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     QStringList files = parser.positionalArguments(); | ||||
|     if(files.length() > 0) | ||||
|     { | ||||
|         int result = removePaths(files, verbose, dryRun); | ||||
|         if(result != 0) | ||||
|         { | ||||
|             return result; | ||||
|         } | ||||
|     } | ||||
| 	if(deleted || ! pattern.isEmpty()) | ||||
| 	{ | ||||
| 		int result = this->remove(pattern, deleted, verbose, dryRun); | ||||
| 		if(result != 0) | ||||
| 		{ | ||||
| 			Logger::error() << "Removal operation did not succeed" << endl; | ||||
| 			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; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -5,12 +5,12 @@ | ||||
| class CommandDelete : public Command | ||||
| { | ||||
| public: | ||||
|     using Command::Command; | ||||
| 	using Command::Command; | ||||
|  | ||||
|     int handle(QStringList arguments) override; | ||||
| 	int handle(QStringList arguments) override; | ||||
| private: | ||||
|     int removeNonExistent(bool verbose, bool dryRun, QString pattern); | ||||
|     int removePaths(const QStringList &paths, bool verbose, bool dryRun); | ||||
| 	int remove(QString pattern, bool onlyDeleted, bool verbose, bool dryRun); | ||||
| 	int removePaths(const QStringList &paths, bool verbose, bool dryRun); | ||||
| }; | ||||
|  | ||||
| #endif // COMMANDDELETE_H | ||||
|   | ||||
		Referens i nytt ärende
	
	Block a user