1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
Git {
var <>localPath, >url, tag, sha, remoteLatest, tags;
classvar gitIsInstalled;
*isGit { |localPath|
^File.exists(localPath +/+ ".git")
}
*new { |localPath|
^super.new.localPath_(localPath)
}
clone { |url|
this.git([
"clone",
url,
thisProcess.platform.formatPathForCmdLine(localPath)
], false);
this.url = url;
}
pull {
this.git(["pull", "origin", "master"])
}
checkout { |refspec|
this.git(["checkout", refspec])
}
fetch {
tags = remoteLatest = nil;
this.git(["fetch"]);
}
isDirty {
^this.git(["--no-pager diff HEAD --"]).size != 0
}
url {
^url ?? {
url = this.remote;
}
}
branch {
var out = this.git(["rev-parse --abbrev-ref HEAD"]);
^if(out.size > 0) { out } { nil }
}
remote {
// detect origin of repo or nil
// origin https://github.com/supercollider-quarks/MathLib (fetch)
// origin https://github.com/supercollider-quarks/MathLib (push)
// problem: if more than one remote then this will just detect the first
// should favor 'origin' if more than one
var out = this.git(["remote -v"]),
match = out.findRegexp("^[a-zA-Z0-9]+\t([^ ]+) \\(fetch\\)");
if(match.size > 0, {
^match[1][1]
});
^nil
}
remoteAsHttpUrl {
var giturl = this.url;
var hosturl, path;
if(giturl.notNil, {
if(giturl.beginsWith("git@"), {
#hosturl, path = giturl.split($:);
^"https://%/%".format(hosturl.split($@).last, path)
});
if(giturl.beginsWith("git:"), {
^("https:" ++ giturl.copyToEnd(4))
});
^giturl;
});
^nil
}
refspec {
^this.tag ?? { this.sha }
}
tag {
// find what tag is currently checked out
var out, match;
^tag ?? {
out = this.git(["--no-pager log --pretty=format:'%d' --abbrev-commit --date=short -1"]);
match = out.findRegexp("tag: ([^ ,\)]+)");
if(match.size > 0, {
tag = "tags/" ++ match[1][1]
});
tag
}
}
sha {
// find what hash is currently checked out
^sha ?? {
sha = this.git(["rev-parse HEAD"]);
}
}
remoteLatest {
// find what the latest commit on the remote is
^remoteLatest ?? {
remoteLatest = this.git(["rev-parse origin/master"]);
}
}
tags {
var raw;
// all tags
// only includes ones that have been fetched from remote
^tags ?? {
if(thisProcess.platform.name !== 'windows', {
raw = this.git(["for-each-ref --format='%(refname)' --sort=taggerdate refs/tags"]);
}, {
raw = this.git(["for-each-ref --format=%(refname) --sort=taggerdate refs/tags"]);
});
tags = raw.split(Char.nl)
.select({ |t| t.size != 0 })
.reverse()
.collect({ |t| t.copyToEnd(10) });
}
}
shaForTag { |tag|
var out = this.git(["rev-list", tag, "--max-count=1"]);
^out.copyFromStart(39)
}
git { |args, cd=true|
var cmd, result="";
if(cd, {
cmd = ["cd", thisProcess.platform.formatPathForCmdLine(localPath), "&&", "git"];
},{
cmd = ["git"];
});
cmd = (cmd ++ args).join(" ");
// this blocks the app thread
Pipe.callSync(cmd, { |res|
result = res;
}, {
Git.checkForGit();
});
^result;
}
*checkForGit {
var gitFind;
if(gitIsInstalled.isNil) {
if(thisProcess.platform.name !== 'windows') {
gitFind = "which git";
} {
gitFind = "where git";
};
Pipe.callSync(gitFind, {
gitIsInstalled = true;
}, { arg error;
"Quarks requires git to be installed".error;
gitIsInstalled = false;
});
};
^gitIsInstalled
}
}
|