Допилено
This commit is contained in:
parent
573f1d7d51
commit
bb58bfe030
4 changed files with 154 additions and 25 deletions
|
@ -13,12 +13,12 @@
|
|||
],
|
||||
"rules": {
|
||||
"tracking": [
|
||||
"/etc/systemd/*.conf",
|
||||
"/usr/exit"
|
||||
"/etc/*.conf"
|
||||
],
|
||||
"ignore": [
|
||||
"/usr/exit/.gitignore",
|
||||
"/usr/exit/dd"
|
||||
"/usr/exit/dd",
|
||||
"/file1"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
39
source/app.d
39
source/app.d
|
@ -21,7 +21,23 @@ int main(string[] args)
|
|||
.optional
|
||||
)
|
||||
)
|
||||
.add(new Command("retracking", "Tracking rules update"))
|
||||
.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("import", "Import snapshot from a tar.gz archive")
|
||||
|
@ -162,8 +178,25 @@ int main(string[] args)
|
|||
i.option("email", "")
|
||||
)
|
||||
)
|
||||
.on("retracking", e =>
|
||||
(new SnagRules(config)).create()
|
||||
.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();
|
||||
|
|
|
@ -13,6 +13,7 @@ import std.path;
|
|||
|
||||
import snag.lib;
|
||||
import snag.core.exception;
|
||||
import snag.core.rules;
|
||||
|
||||
class Snag {
|
||||
private string[] _baseCommand;
|
||||
|
@ -44,6 +45,22 @@ class Snag {
|
|||
return result;
|
||||
}
|
||||
|
||||
private string gitStatus(string shortStatus, bool formatted = false) {
|
||||
immutable string[string] statusMap = [
|
||||
"??": "Untracked",
|
||||
"A": "Added",
|
||||
"M": "Modified",
|
||||
"D": "Deleted",
|
||||
"R": "Renamed",
|
||||
"C": "Copied",
|
||||
"U": "Unmerged",
|
||||
"T": "Type changed",
|
||||
"!": "Ignored"
|
||||
];
|
||||
string fullStatus = statusMap.get(shortStatus, shortStatus);
|
||||
return formatted && fullStatus.length < 8 ? fullStatus ~ "\t" : fullStatus;
|
||||
}
|
||||
|
||||
void initialize(bool force) {
|
||||
auto result = execute(_baseCommand ~ ["rev-parse", "--git-dir"]);
|
||||
!force && !result.status &&
|
||||
|
@ -68,6 +85,9 @@ class Snag {
|
|||
["config", "user.name", _config.author],
|
||||
"A Git repository initialization error occurred"
|
||||
);
|
||||
|
||||
(new SnagRules(_config)).create();
|
||||
|
||||
writeln(
|
||||
"The Git repository has been initialized successfully: ",
|
||||
_config.git
|
||||
|
@ -84,9 +104,11 @@ class Snag {
|
|||
return;
|
||||
}
|
||||
writeln("The following list of files requires backup:");
|
||||
result.output.split('\n').filter!(e => !e.strip.empty).each!((e) {
|
||||
writefln("\t/%s", e.strip.split[1]);
|
||||
});
|
||||
result.output.split('\n')[0..$-1].map!(e =>
|
||||
e.strip.split
|
||||
).each!(e =>
|
||||
writefln("\t%s\t/%s", gitStatus(e[0], true), e[1])
|
||||
);
|
||||
}
|
||||
|
||||
void create(string comment, string author, string email) {
|
||||
|
|
|
@ -10,11 +10,23 @@ import std.string;
|
|||
import std.conv;
|
||||
import std.container;
|
||||
import std.process;
|
||||
import std.file;
|
||||
|
||||
class SnagRules {
|
||||
private string[] _rules;
|
||||
private SnagConfig _config;
|
||||
private string[] _baseCommand;
|
||||
private string _gitignore;
|
||||
private string _gitignoreBak;
|
||||
|
||||
private auto git(string[] command, string message, string separator = ":\n\t") {
|
||||
auto result = execute(_baseCommand ~ command);
|
||||
if (result.status)
|
||||
throw new SnagException(
|
||||
message ~ separator ~ result.output.split('\n')[0]
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
private string[] generateGitignoreRules(string finalPath) {
|
||||
string[] rules;
|
||||
|
@ -59,32 +71,94 @@ class SnagRules {
|
|||
|
||||
this(SnagConfig config) {
|
||||
_config = config;
|
||||
_gitignore = config.git.buildPath("info/exclude");
|
||||
_gitignoreBak = _gitignore ~ ".bak";
|
||||
|
||||
_baseCommand = format(
|
||||
"git --git-dir=%s --work-tree=%s",
|
||||
config.git, config.project
|
||||
).split();
|
||||
|
||||
generate();
|
||||
}
|
||||
|
||||
private void restoreUntracked() {
|
||||
git(
|
||||
["diff", "--cached", "--name-only"],
|
||||
"Failed to retrieve the list of files removed from tracking"
|
||||
).output.split('\n')[0..$-1].each!(
|
||||
file => git(
|
||||
["add", "-f", file],
|
||||
"Failed to restore the file to tracking"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void removeUntracked() {
|
||||
git(
|
||||
["ls-files", "-i", "-c", "--exclude-standard"],
|
||||
"Failed to get the list of files to remove from tracking"
|
||||
).output.split('\n')[0..$-1].each!(
|
||||
file => git(
|
||||
["rm", "--cached", file],
|
||||
"Failed to remove file from tracking"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void create() {
|
||||
auto result = execute(_baseCommand ~ ["rev-parse", "--git-dir"]);
|
||||
result.status &&
|
||||
throw new SnagException(
|
||||
"A problem occurred while checking the repository: "
|
||||
~ result.output.strip('\n')
|
||||
);
|
||||
|
||||
generate();
|
||||
|
||||
string gitignore = _config.git.buildPath("info/exclude");
|
||||
|
||||
File file = File(gitignore, "w");
|
||||
|
||||
auto file = File(_gitignore, "w");
|
||||
_rules.each!(rule => file.writeln(rule));
|
||||
file.close();
|
||||
}
|
||||
|
||||
// git ls-files -i -c --exclude-standard -z | xargs -0 git rm --cached
|
||||
|
||||
// git ls-files -i -c --exclude-standard
|
||||
// git rm --cached <path-to-file>
|
||||
void update(bool remove) {
|
||||
if (!_gitignoreBak.exists) {
|
||||
readText(_gitignore).splitLines().equal(_rules) &&
|
||||
throw new SnagException(
|
||||
"Rule configuration is up-to-date and doesn't require updating"
|
||||
);
|
||||
copy(_gitignore, _gitignoreBak);
|
||||
}
|
||||
|
||||
restoreUntracked();
|
||||
create();
|
||||
|
||||
remove && removeUntracked();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
!_gitignoreBak.exists &&
|
||||
throw new SnagException(
|
||||
"No rule changes to reset"
|
||||
);
|
||||
restoreUntracked();
|
||||
rename(_gitignoreBak, _gitignore);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
!readText(_gitignore).splitLines().length &&
|
||||
throw new SnagException(
|
||||
"The configuration has no rules"
|
||||
);
|
||||
!_gitignoreBak.exists && copy(_gitignore, _gitignoreBak);
|
||||
restoreUntracked();
|
||||
File(_gitignore, "w").close();
|
||||
}
|
||||
|
||||
void show(bool config) {
|
||||
if (config)
|
||||
_rules.join('\n').writeln;
|
||||
else
|
||||
readText(_gitignore).write;
|
||||
}
|
||||
|
||||
void save() {
|
||||
if (!_gitignoreBak.exists) {
|
||||
writeln("The rules are up to date");
|
||||
return;
|
||||
}
|
||||
remove(_gitignoreBak);
|
||||
writeln("The rules have been saved");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue