snag/source/app.d

249 lines
6.2 KiB
D

import snag;
import commandr;
import std.file;
import std.stdio : writeln;
import core.stdc.stdlib : EXIT_SUCCESS, EXIT_FAILURE;
private string programName = "snag";
int main(string[] args)
{
if (!checkGit()) {
"Using snag requires Git to be installed".writeln;
return EXIT_FAILURE;
}
auto argumets = new Program(programName, snagVersion)
.add(new Command("init", "Initializing the repository for storing snapshots")
.add(new Flag("f", "force", "Initializing a repository with overwriting the existing one")
.name("force")
.optional
)
)
.add(new Command("rules", "Tracking rules")
.add(new Command("update", "Update rules")
.add(new Flag("r", "remove", "Removing from tracking the found ignored files")
.name("remove")
.optional
)
)
.add(new Command("reset", "Reset rules (restores rules to pre-change state)"))
.add(new Command("clear", "Clear rules"))
.add(new Command("save", "Save rules"))
.add(new Command("show", "Show rules")
.add(new Flag("c", "config", "Show rules from the configuration file")
.name("config")
.optional
)
)
)
.add(new Command("status", "Checking the status of tracked files"))
.add(new Command("diff", "Show changed data"))
.add(new Command("size", "Size of snapshots"))
.add(new Command("import", "Import snapshot from a tar.gz archive")
.add(new Argument("archive", "The path to the tar.gz archive file").required)
.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 Flag(null, "no-pre", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-post", "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)
.add(new Option("s", "snapshot", "Specify snapshot hash")
.optional
.validateEachWith(
opt => opt.isValidHash,
"must contain snapshot hash provided"
)
)
)
.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 Flag(null, "no-pre", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-post", "Execution without running post-execution commands")
.name("nopost")
.optional
)
)
.add(new Command("list", "List of snapshots")
.add(new Flag("c", "comment", "Show comment")
.name("comment")
.optional
)
.add(new Flag("a", "author", "Show author")
.name("author")
.optional
)
.add(new Flag("e", "email", "Show email")
.name("email")
.optional
)
)
.add(new Command("restore", "Restore to the specified snapshot state")
.add(new Argument("snapshot", "Specify snapshot hash").required)
.add(new Flag(null, "no-pre", "Execution without running pre-execution commands")
.name("nopre")
.optional
)
.add(new Flag(null, "no-post", "Execution without running post-execution commands")
.name("nopost")
.optional
)
)
.add(new Option("c", "config", "Configuration file path")
.optional
.validateEachWith(
opt => opt.exists && opt.isFile,
"must specify the path to the JSON file"
)
)
.parse(args);
string configFile = argumets.option("config", "snag.json");
SnagConfig config;
try {
config = new SnagConfig(configFile);
} catch (SnagConfigException e) {
e.print();
return EXIT_FAILURE;
}
auto snag = new Snag(config);
try {
argumets
.on("init", init =>
snag.initialize(init.flag("force"))
)
.on("diff", diff =>
snag.diff()
)
.on("size", size =>
snag.size()
)
.on("status", status =>
snag.status()
)
.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"),
list.flag("author"),
list.flag("email")
)
)
.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) {
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
.on("update", update =>
rules.update(update.flag("remove"))
)
.on("reset", reset =>
rules.reset()
)
.on("clear", clear =>
rules.clear()
)
.on("save", clear =>
rules.save()
)
.on("show", show =>
rules.show(show.flag("config"))
);
}
);
} catch (SnagException e) {
e.print();
return EXIT_FAILURE;
} catch (Exception e) {
writeln(
"AN UNEXPECTED ERROR HAS OCCURRED!\n",
"PLEASE REPORT IT TO THE AUTHOR OF THE SNAG: ",
"alexander@zhirov.kz (Alexander Zhirov)\n\n",
e
);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}