From 9e618872d59b47b152bc8b917a9a385d318677a2 Mon Sep 17 00:00:00 2001 From: Eero Holmala Date: Wed, 8 Nov 2023 22:42:42 +0200 Subject: [PATCH] Initial commit --- .gitignore | 2 + .vscode/settings.json | 9 +++ CMakeLists.txt | 24 +++++++ README.md | 25 +++++++ cleaner.json.example | 14 ++++ main.cpp | 152 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 226 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 cleaner.json.example create mode 100644 main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ad7fac --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +cleaner.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..87d983b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "xstring": "cpp", + "filesystem": "cpp", + "chrono": "cpp", + "vector": "cpp", + "iostream": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..453f0a4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.0.0) +project(cleaner VERSION 0.1.0 LANGUAGES C CXX) + +include(CTest) +enable_testing() + +if (MSVC_VERSION GREATER_EQUAL "1900") + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("/std:c++17" _cpp_latest_flag_supported) + if (_cpp_latest_flag_supported) + add_compile_options("/std:c++17") + endif() +endif() + +add_executable(cleaner main.cpp) + +find_package(nlohmann_json 3.2.0 REQUIRED) +target_link_libraries(cleaner PRIVATE nlohmann_json::nlohmann_json) + +set_property(TARGET cleaner PROPERTY CXX_STANDARD 17) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) +include(CPack) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b903610 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Cleaner + +## Features +* Clean up/delete + * empty directories + * empty files + +* Configurable + * individual directory configuration + +* Dead simple + * only one way to run + ```sh + -------------------------- + Cleaner version 0.1 + -------------------------- + Usage: + cleaner + ``` + +## Build From Source + +## Changelog + +WIP \ No newline at end of file diff --git a/cleaner.json.example b/cleaner.json.example new file mode 100644 index 0000000..19c74ed --- /dev/null +++ b/cleaner.json.example @@ -0,0 +1,14 @@ +{ + "version": "0.1", + "directories": [ + { + "directory": "C:/dev/temp", + "rules": { + "empty_directories": true, + "empty_files": true, + "age": "30d" + } + }, + "C:/User/joe/Appdata/local/roaming" + ] +} \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f6c0751 --- /dev/null +++ b/main.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#include + +using std::string; +using json = nlohmann::json; + +const int VERSION_MAJOR = 0; +const int VERSION_MINOR = 1; + +enum Flags { + EMPTY_FILES = 0x1, + EMPTY_DIRECTORIES = 0x2 +}; + +struct DirectoryEntry +{ + std::filesystem::path path; + unsigned char flags = EMPTY_DIRECTORIES | EMPTY_FILES; + std::chrono::duration olderThan = std::chrono::duration(0); + + void + clear() + { + path = std::filesystem::path(); + flags = EMPTY_DIRECTORIES | EMPTY_FILES; + olderThan = std::chrono::duration(0); + } +}; + +string +getVersion() +{ + return std::to_string(VERSION_MAJOR)+"."+std::to_string(VERSION_MINOR); +} + +void +print_usage() +{ + std::cout << "--------------------------\n"<< "Cleaner version " << getVersion() << "\n--------------------------\n"; + std::cout << "\tUsage:\n\t\tcleaner\n"; +} + + +bool +createDefaultConfig() +{ + json config; + config["version"] = getVersion(); + config["directories"][0]["directory"] = "C:/dev/temp"; + config["directories"][0]["rules"]["empty_directories"] = true; + config["directories"][0]["rules"]["empty_files"] = true; + config["directories"][0]["rules"]["age"] = "30d"; + + string output = config.dump(4); + std::ofstream f("cleaner.json"); + if (f.is_open()) + { + f << output << std::endl; + f.close(); + return true; + } + return false; + // Return file handle? +} + +void +cleanEntries(std::vector& entries) +{ + for(auto& entry : entries) + { + std::cout << entry.path.string() << "\n"; + } +} + +std::chrono::duration +parseAge(string age) +{ + //TODO (Eero): parse age i.e. 30d + return std::chrono::duration(0); +} + +void +parseConfig(std::vector& entries) +{ + if(!std::filesystem::exists(std::filesystem::path("./cleaner.json"))) + { + std::cout << "Didn't find cleaner.json. Creating default configuration into cleaner.json.\n"; + // Create cleaner.json + if(!createDefaultConfig()) + { + // Failed to create file for some reason. Exit from function. + return; + } + } + //TODO (Eero): Check version here + std::ifstream f("cleaner.json"); + json config = json::parse(f); + std::cout << "Config version: " << config["version"].template get() << "\n"; + // Iterate directories + DirectoryEntry entry = {}; + for (auto& element : config["directories"]) { + if(element.is_string()) + { + entry.path = std::filesystem::path(element.template get()); + entries.push_back(entry); + entry.clear(); + continue; + } + entry.path = std::filesystem::path(element["directory"].template get()); + //TODO (Eero): Check if rules exists + for(json::iterator it = element["rules"].begin(); it != element["rules"].end();++it) + { + if(it.key() == "empty_directories") + { + entry.flags |= EMPTY_DIRECTORIES; + } + if(it.key() == "empty_files") + { + entry.flags |= EMPTY_FILES; + } + if(it.key() == "age") + { + entry.olderThan = parseAge(it.value()); + } + } + entries.push_back(entry); + entry.clear(); + } +} + +int +main(int argc, char const *argv[]) +{ + if(argc>1){ + print_usage(); + return 0; + } + std::vector entries = {}; + const auto start = std::chrono::steady_clock::now(); + parseConfig(entries); + cleanEntries(entries); + const auto end = std::chrono::steady_clock::now(); + const std::chrono::duration elapsed_seconds{end - start}; + std::cout << "Cleaner finished after " << elapsed_seconds.count() << "s\n"; + return 0; +}