Теперь коммиты создаются корректно, не перекрывают состояния файлов друг друга.

При создании коммитов происходит проверка на наличие последнего коммита в ветке и, если коммит не является последним - то происходит ответвление "текущая дата" + "текущий коммит".
Небольшой рефакторинг.
This commit is contained in:
Alexander Zhirov 2025-05-25 03:32:47 +03:00
parent dd5d57c75b
commit 44f8a2207d
Signed by: alexander
GPG key ID: C8D8BE544A27C511

View file

@ -2,6 +2,7 @@ module snag.core.core;
import snag.config; import snag.config;
import std.format; import std.format;
import std.datetime : Clock;
import std.stdio; import std.stdio;
import std.array; import std.array;
import std.process; import std.process;
@ -14,6 +15,7 @@ import snag.core.exception;
class Snag { class Snag {
private string[] _baseCommand; private string[] _baseCommand;
private SnagConfig _config; private SnagConfig _config;
private string _date;
private bool isValidHash(string hash) { private bool isValidHash(string hash) {
auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$"; auto hashPattern = ctRegex!r"^[a-fA-F0-9]{7}$";
@ -26,6 +28,15 @@ class Snag {
config.git, config.project config.git, config.project
).split(); ).split();
_config = config; _config = config;
auto currentTime = Clock.currTime();
_date = format("%02d%03d%02d%02d%02d",
currentTime.year % 100,
currentTime.dayOfYear,
currentTime.hour,
currentTime.minute,
currentTime.second);
} }
private auto git(string[] command, string message, string separator = ":\n") { private auto git(string[] command, string message, string separator = ":\n") {
@ -51,8 +62,8 @@ class Snag {
"A Git repository initialization error occurred" "A Git repository initialization error occurred"
); );
writeln( writeln(
"The Git repository has been initialized successfully: " "The Git repository has been initialized successfully: ",
~ _config.git _config.git
); );
} }
@ -62,8 +73,12 @@ class Snag {
"An error occurred while checking the file tracking status" "An error occurred while checking the file tracking status"
); );
writeln("The following list of files requires backup:"); if (!result.output.length) {
writeln("The current state of the files is up to date as of the latest snapshot");
return;
}
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]);
}); });
@ -75,6 +90,7 @@ class Snag {
"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)
throw new SnagException( throw new SnagException(
"Current file state doesn't need to be archived again" "Current file state doesn't need to be archived again"
@ -82,6 +98,7 @@ class Snag {
result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]); result = execute(_baseCommand ~ ["rev-parse", "--short", "HEAD"]);
if (result.status == 128) { if (result.status == 128) {
// Если это самый первый коммит после инициализации репозитория
git(["add", "."], "Failed to prepare files for archiving"); git(["add", "."], "Failed to prepare files for archiving");
git(["commit", "-m", "test"], "Failed to create a backup"); git(["commit", "-m", "test"], "Failed to create a backup");
writeln("Backup was created successfully"); writeln("Backup was created successfully");
@ -92,56 +109,76 @@ class Snag {
~ result.output ~ result.output
); );
// Текущий коммит, который был изменен
string currentSnapshot = result.output.strip('\n'); string currentSnapshot = result.output.strip('\n');
git( // Если текущий измененный коммит является последним в ветке - то продолжить коммиты в этой ветке
["checkout", "-b", "mod", currentSnapshot ], string currentBranch = git(
"Failed to create a branch from the current state" ["for-each-ref", "--contains", currentSnapshot, "--format='%(refname:short)'"],
); "Error while getting the current branch"
git( ).output.split('\n')[0].strip('\'');
["add", "."],
"Failed to prepare files for archiving"
);
git(
["commit", "-m", "test"],
"Failed to create a backup"
);
git(
["checkout", "master"],
"Failed to perform intermediate state switching"
);
git(
["rebase", "--onto", "mod", currentSnapshot, "master", "-X", "theirs"],
"Ошибка при rebase"
);
// Получение списка коммитов между текущим и веткой
result = git( result = git(
["rev-parse", "--short", "mod"], ["log", "--oneline", "HEAD.." ~ currentBranch],
"An error occurred while checking the file tracking status" "Failed to get the commit list between HEAD and " ~ currentBranch
); );
string newSnapshot = result.output.strip('\n'); string newSnapshot;
git( // Если список существует
["checkout", newSnapshot], if (result.output.length) {
"Failed to perform intermediate state switching" // Если коммит не является последним, то необходимо ответвление
); string newBranch = "%s-%s".format(_date, currentSnapshot);
git( git(
["branch", "-D", "mod"], ["checkout", "-b", newBranch, currentSnapshot ],
"Error while deleting temporary intermediate snapshot" "Failed to create a branch from the current state"
); );
writeln("Backup was created successfully"); git(
["add", "."],
"Failed to prepare files for archiving"
);
git(
["commit", "-m", "test"],
"Failed to create a backup"
);
newSnapshot = git(
["rev-parse", "--short", "HEAD"],
"Failed to retrieve current snapshot information"
).output.strip('\n');
} else {
// Если коммит является посленим в ветке
git(
["add", "."],
"Failed to prepare files for archiving"
);
git(
["commit", "-m", "test"],
"Failed to create a backup"
);
newSnapshot = git(
["rev-parse", "--short", "HEAD"],
"Failed to retrieve current snapshot information"
).output.strip('\n');
git(
["checkout", currentBranch],
"Failed to perform intermediate state switching"
);
git(
["merge", newSnapshot],
"Issue with including the commit into the branch " ~ currentBranch
);
}
writeln("Backup was created successfully: ", newSnapshot);
} }
void list() { void list() {
auto result = git( string currentSnapshot = git(
["rev-parse", "--short", "HEAD"], ["rev-parse", "--short", "HEAD"],
"Failed to retrieve current snapshot information" "Failed to retrieve current snapshot information"
); ).output.strip('\n');
string current = result.output.strip('\n'); git(
result = git(
[ [
"log", "log",
"--all", "--all",
@ -149,11 +186,8 @@ class Snag {
"--pretty=format:%ad\t%h" "--pretty=format:%ad\t%h"
], ],
"Failed to retrieve the list of snapshots" "Failed to retrieve the list of snapshots"
); ).output.split('\n').map!(line => line.split('\t')).array.each!(e =>
writefln("%s\t%s\t%s", currentSnapshot == e[1] ? " >" : "", e[0], e[1])
result.output.split('\n').map!(line => line.split('\t')).array
.sort!((a, b) => a[0] > b[0]).each!(e =>
writefln("%s\t%s\t%s", current == e[1] ? " >" : "", e[0], e[1])
); );
} }
@ -182,6 +216,6 @@ class Snag {
["checkout", hash], ["checkout", hash],
"Failed to restore the snapshot state " ~ hash "Failed to restore the snapshot state " ~ hash
); );
writeln("Backup was restored successfully"); writeln("Backup was restored successfully: ", hash);
} }
} }