Добавлена команда export для экспорта в архив tar.gz файлов указанного состояния снимка, по умолчанию экспортируется текущее состояние снимка

This commit is contained in:
Alexander Zhirov 2025-05-26 02:14:18 +03:00
parent 4301c27ca9
commit 4590ee5fbc
Signed by: alexander
GPG key ID: C8D8BE544A27C511
3 changed files with 72 additions and 11 deletions

View file

@ -12,6 +12,16 @@ int main(string[] args)
.add(new Command("init", "Initializing the repository for storing snapshots")) .add(new Command("init", "Initializing the repository for storing snapshots"))
.add(new Command("status", "Checking the status of tracked files")) .add(new Command("status", "Checking the status of tracked files"))
.add(new Command("diff", "Show changed data")) .add(new Command("diff", "Show changed data"))
.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 Command("create", "Create a new snapshot")
.add(new Option("c", "comment", "Specify comment") .add(new Option("c", "comment", "Specify comment")
.optional .optional
@ -50,7 +60,7 @@ int main(string[] args)
) )
) )
.add(new Command("restore", "Restore to the specified snapshot state") .add(new Command("restore", "Restore to the specified snapshot state")
.add(new Argument("hash", "hash").required) .add(new Argument("snapshot", "Specify snapshot hash").required)
) )
.add(new Option("c", "config", "Сonfiguration file path") .add(new Option("c", "config", "Сonfiguration file path")
.optional .optional
@ -100,7 +110,13 @@ int main(string[] args)
) )
) )
.on("restore", restore => .on("restore", restore =>
snag.restore(restore.arg("hash")) snag.restore(restore.arg("snapshot"))
)
.on("export", e =>
snag.exportSnapshot(
e.arg("path"),
e.option("snapshot", ""),
)
); );
} catch (SnagException e) { } catch (SnagException e) {
e.print(); e.print();

View file

@ -8,6 +8,8 @@ import std.array;
import std.process; import std.process;
import std.algorithm; import std.algorithm;
import std.string; import std.string;
import std.file;
import std.path;
import snag.lib; import snag.lib;
import snag.core.exception; import snag.core.exception;
@ -22,10 +24,9 @@ class Snag {
"git --git-dir=%s --work-tree=%s", "git --git-dir=%s --work-tree=%s",
config.git, config.project config.git, config.project
).split(); ).split();
_config = config; _config = config;
auto currentTime = Clock.currTime(); auto currentTime = Clock.currTime();
_date = format("%02d%03d%02d%02d%02d", _date = format("%02d%03d%02d%02d%02d",
currentTime.year % 100, currentTime.year % 100,
currentTime.dayOfYear, currentTime.dayOfYear,
@ -67,12 +68,10 @@ class Snag {
["status", "--porcelain"], ["status", "--porcelain"],
"An error occurred while checking the file tracking status" "An error occurred while checking the file tracking status"
); );
if (!result.output.length) { if (!result.output.length) {
writeln("The current state of the files is up to date as of the latest snapshot"); writeln("The current state of the files is up to date as of the latest snapshot");
return; return;
} }
writeln("The following list of files requires backup:"); writeln("The following list of files requires backup:");
result.output.split('\n').filter!(e => !e.strip.empty).each!((e) { result.output.split('\n').filter!(e => !e.strip.empty).each!((e) {
writefln("\t/%s", e.strip.split[1]); writefln("\t/%s", e.strip.split[1]);
@ -205,18 +204,20 @@ class Snag {
throw new SnagException( throw new SnagException(
"Invalid snapshot hash provided" "Invalid snapshot hash provided"
); );
auto result = git( auto result = git(
["status", "--porcelain"], ["status", "--porcelain"],
"An error occurred while checking the file tracking status" "An error occurred while checking the file tracking status"
); );
if (result.output.length) {
if (result.output.length)
git( git(
["restore", "."], ["restore", "."],
"Failed to reset file changes state" "Failed to reset file changes state"
); );
git(
["clean", "-fd"],
"Failed to clean untracked files"
);
}
git( git(
["rev-parse", hash], ["rev-parse", hash],
"This snapshot is not available in the archive" "This snapshot is not available in the archive"
@ -239,4 +240,48 @@ class Snag {
} }
writeln("No changes at the moment"); writeln("No changes at the moment");
} }
void exportSnapshot(string path, string hash) {
try {
!path.isDir &&
throw new SnagException(
"Path is not a directory"
);
} catch (Exception e) {
throw new SnagException(
"Failed to verify the archive output directory:\n\t"
~ e.msg
);
}
if (hash.length) {
!isValidHash(hash) &&
throw new SnagException(
"Invalid snapshot hash provided"
);
git(
["rev-parse", hash],
"This snapshot is not available in the archive"
);
} else {
hash = git(
["rev-parse", "--short", "HEAD"],
"Failed to retrieve current snapshot information"
).output.strip('\n');
}
string file = buildPath(
path.absolutePath.buildNormalizedPath,
"%s-%s.tar.gz".format(_date, hash)
);
git(
[
"archive",
"--format=tar.gz",
hash,
"-o",
file
],
"Failed to export snapshot to archive"
);
writeln("Export to archive completed successfully: ", file);
}
} }

View file

@ -1,3 +1,3 @@
module snag.version_; module snag.version_;
enum snagVersion = "0.0.8"; enum snagVersion = "0.0.9";