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 import ae.utils.regex; 17 18 import common; 19 import config : config, opts; 20 import custom : parseSpec; 21 22 //alias BuildConfig = DManager.Config.Build; 23 24 final class DiggerManager : DManager 25 { 26 this() 27 { 28 this.config.build = cast().config.build; 29 this.config.local = cast().config.local; 30 this.verifyWorkTree = true; // for commands which don't take BuildOptions, like bisect 31 } 32 33 override void log(string s) 34 { 35 common.log(s); 36 } 37 38 void logProgress(string s) 39 { 40 log((" " ~ s ~ " ").center(70, '-')); 41 } 42 43 override SubmoduleState parseSpec(string spec) 44 { 45 return .parseSpec(spec); 46 } 47 48 override MetaRepository getMetaRepo() 49 { 50 if (!repoDir.exists) 51 log("First run detected.\nPlease be patient, " ~ 52 "cloning everything might take a few minutes...\n"); 53 return super.getMetaRepo(); 54 } 55 56 override string getCallbackCommand() 57 { 58 return escapeShellFileName(thisExePath) ~ " do callback"; 59 } 60 61 string[string] getBaseEnvironment() 62 { 63 return d.baseEnvironment.vars; 64 } 65 66 bool haveUpdate; 67 68 void needUpdate() 69 { 70 if (!haveUpdate) 71 { 72 d.update(); 73 haveUpdate = true; 74 } 75 } 76 } 77 78 DiggerManager d; 79 80 static this() 81 { 82 d = new DiggerManager(); 83 } 84 85 string parseRev(string rev) 86 { 87 auto args = ["log", "--pretty=format:%H"]; 88 89 d.needUpdate(); 90 91 auto metaRepo = d.getMetaRepo(); 92 auto repo = &metaRepo.git(); 93 94 // git's approxidate accepts anything, so a disambiguating prefix is required 95 if (rev.canFind('@') && !rev.canFind("@{")) 96 { 97 auto parts = rev.findSplit("@"); 98 auto at = parts[2].strip(); 99 100 // If this is a named tag, use the date of the tagged commit. 101 try 102 { 103 auto sha1 = metaRepo.getRef("refs/tags/" ~ at); 104 at = repo.query("log", "-1", "--pretty=format:%cI", sha1); 105 } 106 catch (Exception e) {} 107 108 if (at.startsWith("#")) // For the build-all command - skip this many commits 109 args ~= ["--skip", at[1..$]]; 110 else 111 args ~= ["--until", at]; 112 rev = parts[0].strip(); 113 } 114 115 if (rev.empty) 116 rev = "origin/master"; 117 118 try 119 if (metaRepo.getRef("origin/" ~ rev)) 120 return repo.query(args ~ ["-n", "1", "origin/" ~ rev]); 121 catch (Exception e) {} 122 123 try 124 if (metaRepo.getRef(rev)) 125 return repo.query(args ~ ["-n", "1", rev]); 126 catch (Exception e) {} 127 128 if (rev.startsWith("https://github.com")) 129 { 130 auto grep = repo.query("log", "-n", "2", "--pretty=format:%H", "--grep", "^" ~ escapeRE(rev), "origin/master").splitLines(); 131 if (grep.length == 1) 132 return grep[0]; 133 } 134 135 auto pickaxe = repo.query("log", "-n", "3", "--pretty=format:%H", "-S" ~ rev, "origin/master").splitLines(); 136 if (pickaxe.length && pickaxe.length <= 2) // removed <- added 137 return pickaxe[$-1]; // the one where it was added 138 139 throw new Exception("Unknown/ambiguous revision: " ~ rev); 140 }