Initial commit

This commit is contained in:
Eero Holmala 2023-11-08 22:42:42 +02:00
commit 9e618872d5
6 changed files with 226 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
cleaner.json

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"files.associations": {
"xstring": "cpp",
"filesystem": "cpp",
"chrono": "cpp",
"vector": "cpp",
"iostream": "cpp"
}
}

24
CMakeLists.txt Normal file
View File

@ -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)

25
README.md Normal file
View File

@ -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

14
cleaner.json.example Normal file
View File

@ -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"
]
}

152
main.cpp Normal file
View File

@ -0,0 +1,152 @@
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string>
#include <chrono>
#include <vector>
#include <nlohmann/json.hpp>
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<int> olderThan = std::chrono::duration<int>(0);
void
clear()
{
path = std::filesystem::path();
flags = EMPTY_DIRECTORIES | EMPTY_FILES;
olderThan = std::chrono::duration<int>(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<DirectoryEntry>& entries)
{
for(auto& entry : entries)
{
std::cout << entry.path.string() << "\n";
}
}
std::chrono::duration<int>
parseAge(string age)
{
//TODO (Eero): parse age i.e. 30d
return std::chrono::duration<int>(0);
}
void
parseConfig(std::vector<DirectoryEntry>& 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<string>() << "\n";
// Iterate directories
DirectoryEntry entry = {};
for (auto& element : config["directories"]) {
if(element.is_string())
{
entry.path = std::filesystem::path(element.template get<string>());
entries.push_back(entry);
entry.clear();
continue;
}
entry.path = std::filesystem::path(element["directory"].template get<string>());
//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<DirectoryEntry> 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<double> elapsed_seconds{end - start};
std::cout << "Cleaner finished after " << elapsed_seconds.count() << "s\n";
return 0;
}