Compare commits

...

4 commits

6 changed files with 101 additions and 23 deletions

View file

@ -4,12 +4,11 @@
"email": "user@site.domain",
"author": "snag",
"presnag": [
"/usr/bin/ls",
"/usr/local/bin/script.sh"
"echo $(which ls)",
"pwd"
],
"postsnag": [
"/usr/bin/ls",
"/usr/local/bin/script.sh"
"/usr/bin/ls"
],
"rules": {
"tracking": [

View file

@ -63,6 +63,14 @@ int main(string[] args)
"must contain an email address"
)
)
.add(new Flag(null, "no-presnag", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-postsnag", "Execution without running post-execution commands")
.name("nopost")
.optional
)
)
.add(new Command("export", "Export snapshot to a tar.gz archive")
.add(new Argument("path", "Output directory path for the archive").required)
@ -96,6 +104,14 @@ int main(string[] args)
"must contain an email address"
)
)
.add(new Flag(null, "no-presnag", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-postsnag", "Execution without running post-execution commands")
.name("nopost")
.optional
)
)
.add(new Command("list", "List of snapshots")
.add(new Flag("c", "comment", "Show comment")
@ -113,6 +129,14 @@ int main(string[] args)
)
.add(new Command("restore", "Restore to the specified snapshot state")
.add(new Argument("snapshot", "Specify snapshot hash").required)
.add(new Flag(null, "no-presnag", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-postsnag", "Execution without running post-execution commands")
.name("nopost")
.optional
)
)
.add(new Option("c", "config", "Сonfiguration file path")
.optional
@ -147,13 +171,15 @@ int main(string[] args)
.on("status", status =>
snag.status()
)
.on("create", create =>
.on("create", (create) {
create.flag("nopre") || snag.executePreSnag();
snag.create(
create.option("comment", ""),
create.option("author", ""),
create.option("email", "")
)
)
);
create.flag("nopost") || snag.executePostSnag();
})
.on("list", list =>
snag.list(
list.flag("comment"),
@ -161,23 +187,27 @@ int main(string[] args)
list.flag("email")
)
)
.on("restore", restore =>
snag.restore(restore.arg("snapshot"))
)
.on("restore", (restore) {
restore.flag("nopre") || snag.executePreSnag();
snag.restore(restore.arg("snapshot"));
restore.flag("nopost") || snag.executePostSnag();
})
.on("export", e =>
snag.exportSnapshot(
e.arg("path"),
e.option("snapshot", ""),
)
)
.on("import", i =>
.on("import", (i) {
i.flag("nopre") || snag.executePreSnag();
snag.importSnapshot(
i.arg("archive"),
i.option("comment", ""),
i.option("author", ""),
i.option("email", "")
)
)
);
i.flag("nopost") || snag.executePostSnag();
})
.on("rules", (r) {
auto rules = new SnagRules(config);
r

View file

@ -17,6 +17,8 @@ class SnagConfig {
private string _author;
private string[] _tracking;
private string[] _ignore;
private string[] _presnag;
private string[] _postsnag;
this(string configFile) {
string jsonText;
@ -119,6 +121,22 @@ class SnagConfig {
_ignore = rules["ignore"].array.map!(item => item.str).array;
}
}
if ("presnag" in jsonData) {
if (jsonData["presnag"].type != JSONType.array)
throw new SnagConfigException(
"The \"presnag\" parameter must be an array containing a set of commands"
);
_presnag = jsonData["presnag"].array.map!(item => item.str).array;
}
if ("postsnag" in jsonData) {
if (jsonData["postsnag"].type != JSONType.array)
throw new SnagConfigException(
"The \"postsnag\" parameter must be an array containing a set of commands"
);
_postsnag = jsonData["postsnag"].array.map!(item => item.str).array;
}
}
@property string git() const { return _git; }
@ -127,4 +145,6 @@ class SnagConfig {
@property string author() const { return _author; }
@property const(string[]) tracking() const { return _tracking; }
@property const(string[]) ignore() const { return _ignore; }
@property const(string[]) presnag() const { return _presnag; }
@property const(string[]) postsnag() const { return _postsnag; }
}

View file

@ -61,6 +61,32 @@ class Snag {
return formatted && fullStatus.length < 8 ? fullStatus ~ "\t" : fullStatus;
}
void executePreSnag() {
_config.presnag().each!((command) {
auto result = executeShell(command);
result.status && throw new SnagException(
"%s:\n\t%s\n\n%s".format(
"An error occurred during presnag-command execution",
command,
result.output
)
);
});
}
void executePostSnag() {
_config.postsnag().each!((command) {
auto result = executeShell(command);
result.status && throw new SnagException(
"%s:\n\t%s\n\n%s".format(
"An error occurred during postsnag-command execution",
command,
result.output
)
);
});
}
void initialize(bool force) {
auto result = execute(_baseCommand ~ ["rev-parse", "--git-dir"]);
!force && !result.status &&
@ -127,13 +153,18 @@ class Snag {
email.length && (environment["GIT_AUTHOR_EMAIL"] = email);
string message = comment.length ? comment : "Standard snapshot creation";
string newSnapshot;
result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]);
if (result.status == 128) {
// Если это самый первый коммит после инициализации репозитория
git(["add", "."], "Failed to prepare files for archiving");
git(["commit", "-m"] ~ message, "Failed to create a backup");
writeln("Backup was created successfully");
git(["commit", "-m"] ~ message, "Failed to create a snapshot");
newSnapshot = git(
["rev-parse", "--short", "HEAD"],
"Failed to retrieve current snapshot information"
).output.strip('\n');
writeln("Snapshot was created successfully: ", newSnapshot);
return;
} else if (result.status != 0)
throw new SnagException(
@ -157,8 +188,6 @@ class Snag {
"Failed to get the commit list between HEAD and " ~ currentBranch
);
string newSnapshot;
// Если список существует
if (result.output.length) {
// Если коммит не является последним, то необходимо ответвление
@ -173,7 +202,7 @@ class Snag {
);
git(
["commit", "-m"] ~ message,
"Failed to create a backup"
"Failed to create a snapshot"
);
newSnapshot = git(
["rev-parse", "--short", "HEAD"],
@ -187,7 +216,7 @@ class Snag {
);
git(
["commit", "-m"] ~ message,
"Failed to create a backup"
"Failed to create a snapshot"
);
newSnapshot = git(
["rev-parse", "--short", "HEAD"],
@ -202,7 +231,7 @@ class Snag {
"Issue with including the commit into the branch " ~ currentBranch
);
}
writeln("Backup was created successfully: ", newSnapshot);
writeln("Snapshot was created successfully: ", newSnapshot);
}
void list(bool comment, bool author, bool email) {

View file

@ -86,7 +86,7 @@ class SnagRules {
git(
["diff", "--cached", "--name-only"],
"Failed to retrieve the list of files removed from tracking"
).output.split('\n')[0..$-1].each!(
).output.split('\n').filter!(e => !e.strip.empty).each!(
file => git(
["add", "-f", file],
"Failed to restore the file to tracking"
@ -98,7 +98,7 @@ class SnagRules {
git(
["ls-files", "-i", "-c", "--exclude-standard"],
"Failed to get the list of files to remove from tracking"
).output.split('\n')[0..$-1].each!(
).output.split('\n').filter!(e => !e.strip.empty).each!(
file => git(
["rm", "--cached", file],
"Failed to remove file from tracking"

View file

@ -1,3 +1,3 @@
module snag.version_;
enum snagVersion = "0.0.11";
enum snagVersion = "0.0.12";