1 module dsemver.git; 2 3 import std.array : array; 4 import std.process : executeShell; 5 import std.datetime; 6 import std.algorithm.iteration : filter, map, splitter; 7 import std.algorithm.searching : any, canFind, startsWith; 8 import std.algorithm.sorting : sort; 9 import std..string : stripLeft; 10 import std.typecons : nullable, Nullable, tuple; 11 import std.exception : enforce; 12 import std.file : getcwd, chdir; 13 import std.format : format; 14 15 import dsemver.semver; 16 17 struct SheelRslt { 18 const int rslt; 19 string output; 20 } 21 22 private SheelRslt execute(string projectPath, string command) { 23 const cwd = getcwd(); 24 chdir(projectPath); 25 scope(exit) { 26 chdir(cwd); 27 } 28 29 const r = executeShell(command); 30 enforce(r.status == 0, format("'%s' failed in '%s'" 31 ~ "\nWith return code '%s' and msg %s" 32 , command, projectPath, r.status, r.output)); 33 return SheelRslt(r.status, r.output); 34 } 35 36 bool isClean(string projectPath) { 37 enum cmd = "git status --porcelain"; 38 39 const r = execute(projectPath, cmd); 40 41 const m = r.output.splitter("\n").map!(l => l.stripLeft) 42 .any!(l => l.startsWith("M ")); 43 44 return !m; 45 } 46 47 private Nullable!SemVer toSemVer(string sv) { 48 try { 49 SemVer ret = parseSemVer(sv); 50 return nullable(ret); 51 } catch(Exception e) { 52 return Nullable!(SemVer).init; 53 } 54 } 55 56 struct RefSemVer { 57 string gitRef; 58 SemVer semver; 59 } 60 61 RefSemVer[] getTags(string projectPath) { 62 enum cmd = "git for-each-ref --sort=creatordate --format '%(refname)' refs/tags"; 63 const r = execute(projectPath, cmd); 64 65 enum prefix = "refs/tags/"; 66 67 SemVer dummy; 68 69 return r.output.splitter("\n").filter!(l => l.startsWith(prefix)) 70 .map!(v => tuple(v, toSemVer(v[prefix.length .. $]))) 71 .filter!(v => !v[1].isNull()) 72 .map!(v => RefSemVer(v[0], v[1].get())) 73 .array 74 .sort!((a,b) => a.semver > b.semver) 75 .array; 76 } 77 78 void checkoutRef(string projectPath, string tag) { 79 const cmd = format("git checkout %s", tag); 80 const r = execute(projectPath, cmd); 81 }