Добавлена новая команда diff для просмотра внесенных изменений на текущий момент.
Добавлена возможность установки комментария, имени автора, электронной почты при создании снимка. Функции проверок через регулярные выражения перенесены в новый модуль lib.
This commit is contained in:
parent
eff4fa2fe6
commit
4301c27ca9
8 changed files with 90 additions and 36 deletions
|
@ -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"
|
||||
|
|
44
source/app.d
44
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")
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
13
source/snag/lib/lib.d
Normal file
13
source/snag/lib/lib.d
Normal file
|
@ -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;
|
||||
}
|
3
source/snag/lib/package.d
Normal file
3
source/snag/lib/package.d
Normal file
|
@ -0,0 +1,3 @@
|
|||
module snag.lib;
|
||||
|
||||
public import snag.lib.lib;
|
|
@ -1,5 +1,6 @@
|
|||
module snag;
|
||||
|
||||
public import snag.version_;
|
||||
public import snag.lib;
|
||||
public import snag.config;
|
||||
public import snag.core;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module snag.version_;
|
||||
|
||||
enum snagVersion = "0.0.7";
|
||||
enum snagVersion = "0.0.8";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue