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; }