1 module repo;
2 
3 import std.array;
4 import std.algorithm;
5 import std.exception;
6 import std.file;
7 import std.parallelism : parallel;
8 import std.path;
9 import std.process;
10 import std.range;
11 import std.regex;
12 import std..string;
13 
14 import ae.sys.file;
15 import ae.sys.d.manager;
16 
17 import common;
18 import config : config, opts;
19 import custom : parseSpec;
20 
21 //alias BuildConfig = DManager.Config.Build;
22 
23 final class DiggerManager : DManager
24 {
25 	this()
26 	{
27 		this.config.build = cast().config.build;
28 		this.config.local = cast().config.local;
29 		this.verifyWorkTree = true;
30 	}
31 
32 	override void log(string s)
33 	{
34 		common.log(s);
35 	}
36 
37 	void logProgress(string s)
38 	{
39 		log((" " ~ s ~ " ").center(70, '-'));
40 	}
41 
42 	override SubmoduleState parseSpec(string spec)
43 	{
44 		return .parseSpec(spec);
45 	}
46 
47 	override MetaRepository getMetaRepo()
48 	{
49 		if (!repoDir.exists)
50 			log("First run detected.\nPlease be patient, " ~
51 				"cloning everything might take a few minutes...\n");
52 		return super.getMetaRepo();
53 	}
54 
55 	override string getCallbackCommand()
56 	{
57 		return escapeShellFileName(thisExePath) ~ " do callback";
58 	}
59 
60 	string[string] getBaseEnvironment()
61 	{
62 		return d.baseEnvironment.vars;
63 	}
64 
65 	bool haveUpdate;
66 
67 	void needUpdate()
68 	{
69 		if (!haveUpdate)
70 		{
71 			d.update();
72 			haveUpdate = true;
73 		}
74 	}
75 }
76 
77 DiggerManager d;
78 
79 static this()
80 {
81 	d = new DiggerManager();
82 }
83 
84 string parseRev(string rev)
85 {
86 	auto args = ["log", "--pretty=format:%H"];
87 
88 	// git's approxidate accepts anything, so a disambiguating prefix is required
89 	if (rev.canFind('@') && !rev.canFind("@{"))
90 	{
91 		auto parts = rev.findSplit("@");
92 		auto at = parts[2].strip();
93 		if (at.startsWith("#")) // For the build-all command - skip this many commits
94 			args ~= ["--skip", at[1..$]];
95 		else
96 			args ~= ["--until", at];
97 		rev = parts[0].strip();
98 	}
99 
100 	if (rev.empty)
101 		rev = "origin/master";
102 
103 	d.needUpdate();
104 
105 	auto metaRepo = d.getMetaRepo();
106 	metaRepo.needRepo();
107 	auto repo = &metaRepo.git;
108 
109 	try
110 		return repo.query(args ~ ["-n", "1", "origin/" ~ rev]);
111 	catch (Exception e)
112 	try
113 		return repo.query(args ~ ["-n", "1", rev]);
114 	catch (Exception e)
115 		{}
116 
117 	auto grep = repo.query("log", "-n", "2", "--pretty=format:%H", "--grep", rev, "origin/master").splitLines();
118 	if (grep.length == 1)
119 		return grep[0];
120 
121 	auto pickaxe = repo.query("log", "-n", "3", "--pretty=format:%H", "-S" ~ rev, "origin/master").splitLines();
122 	if (pickaxe.length && pickaxe.length <= 2) // removed <- added
123 		return pickaxe[$-1];   // the one where it was added
124 
125 	throw new Exception("Unknown/ambiguous revision: " ~ rev);
126 }