diff --git a/snapd.json b/snapd.json index d8b0536..3fe8034 100644 --- a/snapd.json +++ b/snapd.json @@ -1,5 +1,14 @@ { - "git": "/var/lib/snapd", - "project": "/", - "email": "user@site.domain" + "git": "/tmp/testgit", + "project": "/home/alexander/Programming/new/dlang/snapd/source", + "email": "user@site.domain", + "user": "snapd", + "presnap": [ + "/usr/bin/ls", + "/usr/local/bin/script.sh" + ], + "postsnap": [ + "/usr/bin/ls", + "/usr/local/bin/script.sh" + ] } diff --git a/source/app.d b/source/app.d index 3ac5b7a..72df7c3 100644 --- a/source/app.d +++ b/source/app.d @@ -2,8 +2,6 @@ import snapd; import commandr; import std.file; -import std.stdio : writeln; - import core.stdc.stdlib : EXIT_SUCCESS, EXIT_FAILURE; private string programName = "snapd"; @@ -11,6 +9,9 @@ private string programName = "snapd"; int main(string[] args) { auto argumets = new Program(programName, snapdVersion) + .add(new Command("init", "Initializing the repository for storing snapshots")) + .add(new Command("status", "Checking the status of tracked files")) + .add(new Command("create", "Create a new backup")) .add(new Option("c", "config", "Сonfiguration file path") .optional .validateEachWith( @@ -31,5 +32,23 @@ int main(string[] args) return EXIT_FAILURE; } + auto snapd = new Snapd(config); + + try { + argumets + .on("init", (init) { + snapd.initialize(); + }) + .on("status", (status) { + snapd.status(); + }) + .on("create", (create) { + snapd.create(); + }); + } catch (SnapdException e) { + e.print(); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/source/snapd/config/config.d b/source/snapd/config/config.d index 5822758..e6d7f8f 100644 --- a/source/snapd/config/config.d +++ b/source/snapd/config/config.d @@ -12,6 +12,7 @@ class SnapdConfig { private string _git; private string _project; private string _email; + private string _user; private bool isValidEmail(string email) { auto emailPattern = ctRegex!r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"; @@ -85,9 +86,22 @@ class SnapdConfig { "Invalid email address provided in the \"email\" parameter:\n\t" ~ _email ); + + if ("user" !in jsonData) + throw new SnapdConfigException( + "The configuration file is missing the \"user\" parameter" + ); + + _user = jsonData["user"].str; + + if (!_user.length) + throw new SnapdConfigException( + "The \"user\" parameter must contain an user name" + ); } @property string git() const { return _git; } @property string project() const { return _project; } @property string email() const { return _email; } + @property string user() const { return _user; } } diff --git a/source/snapd/core/core.d b/source/snapd/core/core.d new file mode 100644 index 0000000..2d285c4 --- /dev/null +++ b/source/snapd/core/core.d @@ -0,0 +1,109 @@ +module snapd.core.core; + +import snapd.config; +import std.format; +import std.stdio; +import std.array; +import std.exception; +import std.process; +import std.algorithm; +import std.string; + +class SnapdException : Exception { + this(string msg, string file = __FILE__, size_t line = __LINE__) { + super(msg, file, line); + } + + void print() { + writeln(msg); + } +} + +class Snapd { + private string[] _baseCommand; + private SnapdConfig _config; + + this(SnapdConfig config) { + _baseCommand = format( + "git --git-dir=%s --work-tree=%s", + config.git, config.project + ).split(); + _config = config; + } + + void initialize() { + auto result = execute(_baseCommand ~ "init"); + if (result.status) + throw new SnapdException( + "A Git repository initialization error occurred:\n" + ~ result.output + ); + + result = execute( + _baseCommand ~ ["config", "user.email", _config.email] + ); + if (result.status) + throw new SnapdException( + "A Git repository initialization error occurred:\n" + ~ result.output + ); + + result = execute( + _baseCommand ~ ["config", "user.name", _config.user] + ); + if (result.status) + throw new SnapdException( + "A Git repository initialization error occurred:\n" + ~ result.output + ); + + writeln( + "The Git repository has been initialized successfully: " + ~ _config.git + ); + } + + void status() { + auto result = execute( + _baseCommand ~ ["status", "--porcelain"] + ); + if (result.status) + throw new SnapdException( + "An error occurred while checking the file tracking status:\n" + ~ result.output + ); + + writeln("The following list of files requires backup:"); + + /** + Цепочка выполняет разбивку по переводу на новую строку, + отсеивает пустые строки, перебирает в цикле имеющиеся строки, + выводит только вторую часть строки (разделенную по пробелу) + */ + result.output.split('\n').filter!(e => !e.strip.empty).each!((e) { + writefln("\t/%s", e.strip.split[1]); + }); + } + + void create() { + auto result = execute( + _baseCommand ~ ["add", "."] + ); + if (result.status) + throw new SnapdException( + "Failed to prepare files for archiving:\n" + ~ result.output + ); + + result = execute( + _baseCommand ~ ["commit", "-m", "test"] + ); + if (result.status) + throw new SnapdException( + "Failed to create a backup:\n" + ~ result.output + ); + + writeln("Backup was created successfully"); + } +} diff --git a/source/snapd/core/package.d b/source/snapd/core/package.d new file mode 100644 index 0000000..ac6ebaf --- /dev/null +++ b/source/snapd/core/package.d @@ -0,0 +1,3 @@ +module snapd.core; + +public import snapd.core.core; diff --git a/source/snapd/package.d b/source/snapd/package.d index 4f5e10f..4360689 100644 --- a/source/snapd/package.d +++ b/source/snapd/package.d @@ -2,3 +2,4 @@ module snapd; public import snapd.version_; public import snapd.config; +public import snapd.core; diff --git a/source/snapd/version_.d b/source/snapd/version_.d index 98d0114..bc63b1b 100644 --- a/source/snapd/version_.d +++ b/source/snapd/version_.d @@ -1,3 +1,3 @@ module snapd.version_; -enum snapdVersion = "0.0.2"; +enum snapdVersion = "0.0.3";