Промежуточный набросок для управления правилами
This commit is contained in:
parent
db9a6be9f4
commit
573f1d7d51
6 changed files with 135 additions and 2 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -11,7 +11,7 @@
|
||||||
"name": "Build & Debug DUB project",
|
"name": "Build & Debug DUB project",
|
||||||
"cwd": "${command:dubWorkingDirectory}",
|
"cwd": "${command:dubWorkingDirectory}",
|
||||||
"program": "bin/${command:dubTarget}",
|
"program": "bin/${command:dubTarget}",
|
||||||
"args": ["list"]
|
"args": ["create"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
12
snag.json
12
snag.json
|
@ -10,5 +10,15 @@
|
||||||
"postsnag": [
|
"postsnag": [
|
||||||
"/usr/bin/ls",
|
"/usr/bin/ls",
|
||||||
"/usr/local/bin/script.sh"
|
"/usr/local/bin/script.sh"
|
||||||
]
|
],
|
||||||
|
"rules": {
|
||||||
|
"tracking": [
|
||||||
|
"/etc/systemd/*.conf",
|
||||||
|
"/usr/exit"
|
||||||
|
],
|
||||||
|
"ignore": [
|
||||||
|
"/usr/exit/.gitignore",
|
||||||
|
"/usr/exit/dd"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ int main(string[] args)
|
||||||
.optional
|
.optional
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.add(new Command("retracking", "Tracking rules update"))
|
||||||
.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("import", "Import snapshot from a tar.gz archive")
|
.add(new Command("import", "Import snapshot from a tar.gz archive")
|
||||||
|
@ -160,6 +161,9 @@ int main(string[] args)
|
||||||
i.option("author", ""),
|
i.option("author", ""),
|
||||||
i.option("email", "")
|
i.option("email", "")
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
.on("retracking", e =>
|
||||||
|
(new SnagRules(config)).create()
|
||||||
);
|
);
|
||||||
} catch (SnagException e) {
|
} catch (SnagException e) {
|
||||||
e.print();
|
e.print();
|
||||||
|
|
|
@ -5,6 +5,8 @@ import std.file;
|
||||||
import std.path;
|
import std.path;
|
||||||
import std.string;
|
import std.string;
|
||||||
import snag.lib;
|
import snag.lib;
|
||||||
|
import std.algorithm;
|
||||||
|
import std.array;
|
||||||
|
|
||||||
import snag.config.exception;
|
import snag.config.exception;
|
||||||
|
|
||||||
|
@ -13,6 +15,8 @@ class SnagConfig {
|
||||||
private string _project;
|
private string _project;
|
||||||
private string _email;
|
private string _email;
|
||||||
private string _author;
|
private string _author;
|
||||||
|
private string[] _tracking;
|
||||||
|
private string[] _ignore;
|
||||||
|
|
||||||
this(string configFile) {
|
this(string configFile) {
|
||||||
string jsonText;
|
string jsonText;
|
||||||
|
@ -93,10 +97,34 @@ class SnagConfig {
|
||||||
throw new SnagConfigException(
|
throw new SnagConfigException(
|
||||||
"The \"author\" parameter must contain an author name"
|
"The \"author\" parameter must contain an author name"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ("rules" in jsonData) {
|
||||||
|
if (jsonData["rules"].type != JSONType.object)
|
||||||
|
throw new SnagConfigException(
|
||||||
|
"The \"rules\" parameter must be an object"
|
||||||
|
);
|
||||||
|
auto rules = jsonData["rules"];
|
||||||
|
if ("tracking" in rules) {
|
||||||
|
if (rules["tracking"].type != JSONType.array)
|
||||||
|
throw new SnagConfigException(
|
||||||
|
"The \"tracking\" parameter must be an array containing a set of paths to tracked files"
|
||||||
|
);
|
||||||
|
_tracking = rules["tracking"].array.map!(item => item.str).array;
|
||||||
|
}
|
||||||
|
if ("ignore" in rules) {
|
||||||
|
if (rules["ignore"].type != JSONType.array)
|
||||||
|
throw new SnagConfigException(
|
||||||
|
"The \"ignore\" parameter must contain a gitignore rule"
|
||||||
|
);
|
||||||
|
_ignore = rules["ignore"].array.map!(item => item.str).array;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@property string git() const { return _git; }
|
@property string git() const { return _git; }
|
||||||
@property string project() const { return _project; }
|
@property string project() const { return _project; }
|
||||||
@property string email() const { return _email; }
|
@property string email() const { return _email; }
|
||||||
@property string author() const { return _author; }
|
@property string author() const { return _author; }
|
||||||
|
@property const(string[]) tracking() const { return _tracking; }
|
||||||
|
@property const(string[]) ignore() const { return _ignore; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,3 +2,4 @@ module snag.core;
|
||||||
|
|
||||||
public import snag.core.core;
|
public import snag.core.core;
|
||||||
public import snag.core.exception;
|
public import snag.core.exception;
|
||||||
|
public import snag.core.rules;
|
||||||
|
|
90
source/snag/core/rules.d
Normal file
90
source/snag/core/rules.d
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
module snag.core.rules;
|
||||||
|
|
||||||
|
import snag.config;
|
||||||
|
import snag.core.exception;
|
||||||
|
import std.algorithm;
|
||||||
|
import std.array;
|
||||||
|
import std.path;
|
||||||
|
import std.stdio;
|
||||||
|
import std.string;
|
||||||
|
import std.conv;
|
||||||
|
import std.container;
|
||||||
|
import std.process;
|
||||||
|
|
||||||
|
class SnagRules {
|
||||||
|
private string[] _rules;
|
||||||
|
private SnagConfig _config;
|
||||||
|
private string[] _baseCommand;
|
||||||
|
|
||||||
|
private string[] generateGitignoreRules(string finalPath) {
|
||||||
|
string[] rules;
|
||||||
|
string[] parts = finalPath.split("/").filter!(p => !p.empty).array;
|
||||||
|
|
||||||
|
if (parts.length == 0) return rules;
|
||||||
|
|
||||||
|
rules ~= "/*";
|
||||||
|
rules ~= "!/" ~ parts[0];
|
||||||
|
rules ~= "/" ~ parts[0] ~ "/*";
|
||||||
|
|
||||||
|
if (parts.length > 1) {
|
||||||
|
string currentPath = "/" ~ parts[0];
|
||||||
|
foreach (i; 1 .. parts.length) {
|
||||||
|
currentPath ~= "/" ~ parts[i];
|
||||||
|
rules ~= "!" ~ currentPath;
|
||||||
|
if (i < parts.length.to!int - 1) {
|
||||||
|
rules ~= currentPath ~ "/*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generate() {
|
||||||
|
string[] rules;
|
||||||
|
auto tempRules = new RedBlackTree!string;
|
||||||
|
|
||||||
|
_config.tracking.each!(
|
||||||
|
track => rules ~= generateGitignoreRules(track)
|
||||||
|
);
|
||||||
|
|
||||||
|
rules.each!((rule) {
|
||||||
|
if (rule in tempRules) return;
|
||||||
|
tempRules.insert(rule);
|
||||||
|
_rules ~= rule;
|
||||||
|
});
|
||||||
|
|
||||||
|
_rules ~= _config.ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
this(SnagConfig config) {
|
||||||
|
_config = config;
|
||||||
|
|
||||||
|
_baseCommand = format(
|
||||||
|
"git --git-dir=%s --work-tree=%s",
|
||||||
|
config.git, config.project
|
||||||
|
).split();
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
_rules.each!(rule => file.writeln(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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>
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue