diff --git a/snag.json b/snag.json index 42a6ae2..d8f176b 100644 --- a/snag.json +++ b/snag.json @@ -2,7 +2,7 @@ "git": "/tmp/testgit", "project": "/tmp/test", "email": "user@site.domain", - "user": "snag", + "author": "snag", "presnag": [ "/usr/bin/ls", "/usr/local/bin/script.sh" diff --git a/source/app.d b/source/app.d index 97c24ba..7592ee2 100644 --- a/source/app.d +++ b/source/app.d @@ -11,14 +11,37 @@ int main(string[] args) auto argumets = new Program(programName, snagVersion) .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 Command("list", "List of backups") + .add(new Command("diff", "Show changed data")) + .add(new Command("create", "Create a new snapshot") + .add(new Option("c", "comment", "Specify comment") + .optional + .validateEachWith( + opt => opt.length > 0, + "cannot be empty" + ) + ) + .add(new Option("a", "author", "Specify author") + .optional + .validateEachWith( + opt => opt.length > 0, + "cannot be empty" + ) + ) + .add(new Option("e", "email", "Specify email") + .optional + .validateEachWith( + opt => opt.isValidEmail, + "must contain an email address" + ) + ) + ) + .add(new Command("list", "List of snapshots") .add(new Flag("c", "comment", "Show comment") .name("comment") .optional ) - .add(new Flag("u", "user", "Show user") - .name("user") + .add(new Flag("a", "author", "Show author") + .name("author") .optional ) .add(new Flag("e", "email", "Show email") @@ -33,7 +56,7 @@ int main(string[] args) .optional .validateEachWith( opt => opt.exists && opt.isFile, - "A JSON file path must be provided" + "must specify the path to the JSON file" ) ) .parse(args); @@ -56,16 +79,23 @@ int main(string[] args) .on("init", init => snag.initialize() ) + .on("diff", diff => + snag.diff() + ) .on("status", status => snag.status() ) .on("create", create => - snag.create() + snag.create( + create.option("comment", ""), + create.option("author", ""), + create.option("email", "") + ) ) .on("list", list => snag.list( list.flag("comment"), - list.flag("user"), + list.flag("author"), list.flag("email") ) ) diff --git a/source/snag/config/config.d b/source/snag/config/config.d index 2d25f51..75de340 100644 --- a/source/snag/config/config.d +++ b/source/snag/config/config.d @@ -3,8 +3,8 @@ module snag.config.config; import std.json; import std.file; import std.path; -import std.regex; import std.string; +import snag.lib; import snag.config.exception; @@ -12,12 +12,7 @@ class SnagConfig { 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,}$"; - return !matchFirst(email, emailPattern).empty; - } + private string _author; this(string configFile) { string jsonText; @@ -87,21 +82,21 @@ class SnagConfig { ~ _email ); - if ("user" !in jsonData) + if ("author" !in jsonData) throw new SnagConfigException( - "The configuration file is missing the \"user\" parameter" + "The configuration file is missing the \"author\" parameter" ); - _user = jsonData["user"].str; + _author = jsonData["author"].str; - if (!_user.length) + if (!_author.length) throw new SnagConfigException( - "The \"user\" parameter must contain an user name" + "The \"author\" parameter must contain an author 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; } + @property string author() const { return _author; } } diff --git a/source/snag/core/core.d b/source/snag/core/core.d index 5aae3ec..828563b 100644 --- a/source/snag/core/core.d +++ b/source/snag/core/core.d @@ -8,8 +8,8 @@ import std.array; import std.process; import std.algorithm; import std.string; -import std.regex; +import snag.lib; import snag.core.exception; class Snag { @@ -17,11 +17,6 @@ class Snag { private SnagConfig _config; private string _date; - private bool isValidHash(string hash) { - auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$"; - return !matchFirst(hash, hashPattern).empty; - } - this(SnagConfig config) { _baseCommand = format( "git --git-dir=%s --work-tree=%s", @@ -58,7 +53,7 @@ class Snag { "A Git repository initialization error occurred" ); git( - ["config", "user.name", _config.user], + ["config", "user.name", _config.author], "A Git repository initialization error occurred" ); writeln( @@ -84,7 +79,7 @@ class Snag { }); } - void create() { + void create(string comment, string author, string email) { auto result = git( ["status", "--porcelain"], "An error occurred while checking the file tracking status" @@ -96,11 +91,16 @@ class Snag { "Current file state doesn't need to be archived again" ); + author.length && (environment["GIT_AUTHOR_NAME"] = author); + email.length && (environment["GIT_AUTHOR_EMAIL"] = email); + + string message = comment.length ? comment : "Standard snapshot creation"; + result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]); if (result.status == 128) { // Если это самый первый коммит после инициализации репозитория git(["add", "."], "Failed to prepare files for archiving"); - git(["commit", "-m", "test"], "Failed to create a backup"); + git(["commit", "-m"] ~ message, "Failed to create a backup"); writeln("Backup was created successfully"); return; } else if (result.status != 0) @@ -139,7 +139,7 @@ class Snag { "Failed to prepare files for archiving" ); git( - ["commit", "-m", "test"], + ["commit", "-m"] ~ message, "Failed to create a backup" ); newSnapshot = git( @@ -153,7 +153,7 @@ class Snag { "Failed to prepare files for archiving" ); git( - ["commit", "-m", "test"], + ["commit", "-m"] ~ message, "Failed to create a backup" ); newSnapshot = git( @@ -172,7 +172,7 @@ class Snag { writeln("Backup was created successfully: ", newSnapshot); } - void list(bool comment, bool user, bool email) { + void list(bool comment, bool author, bool email) { string currentSnapshot = git( ["rev-parse", "--short", "HEAD"], "Failed to retrieve current snapshot information" @@ -181,7 +181,7 @@ class Snag { string format = "format:%h\t%ad"; comment && (format ~= "\t%s"); - user && (format ~= "\t%an"); + author && (format ~= "\t%an"); email && (format ~= "\t%ae"); git( @@ -193,7 +193,7 @@ class Snag { ], "Failed to retrieve the list of snapshots" ).output.split('\n').map!(line => line.split('\t')).array.each!(e => - writefln("%s\t%s", + writefln("%s\t%s", currentSnapshot == e[0] ? " >" : "", e.join("\t") ) @@ -227,4 +227,16 @@ class Snag { ); writeln("Backup was restored successfully: ", hash); } + + void diff() { + auto result = git( + ["diff"], + "Failed to retrieve changes" + ); + if (result.output.length) { + result.output.write; + return; + } + writeln("No changes at the moment"); + } } diff --git a/source/snag/lib/lib.d b/source/snag/lib/lib.d new file mode 100644 index 0000000..3277d0e --- /dev/null +++ b/source/snag/lib/lib.d @@ -0,0 +1,13 @@ +module snag.lib.lib; + +import std.regex; + +bool isValidHash(string hash) { + auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$"; + return !matchFirst(hash, hashPattern).empty; +} + +bool isValidEmail(string email) { + auto emailPattern = ctRegex!r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"; + return !matchFirst(email, emailPattern).empty; +} diff --git a/source/snag/lib/package.d b/source/snag/lib/package.d new file mode 100644 index 0000000..46fa21c --- /dev/null +++ b/source/snag/lib/package.d @@ -0,0 +1,3 @@ +module snag.lib; + +public import snag.lib.lib; diff --git a/source/snag/package.d b/source/snag/package.d index 22b28bf..ae8b15d 100644 --- a/source/snag/package.d +++ b/source/snag/package.d @@ -1,5 +1,6 @@ module snag; public import snag.version_; +public import snag.lib; public import snag.config; public import snag.core; diff --git a/source/snag/version_.d b/source/snag/version_.d index 2bdebb8..0c40657 100644 --- a/source/snag/version_.d +++ b/source/snag/version_.d @@ -1,3 +1,3 @@ module snag.version_; -enum snagVersion = "0.0.7"; +enum snagVersion = "0.0.8";