Skip to content

Commit b298fb4

Browse files
authored
Merge pull request #2466 from larsewi/ref-resolution
Resolve repo revisions by full ref name
2 parents 54b9532 + 3571f30 commit b298fb4

1 file changed

Lines changed: 32 additions & 6 deletions

File tree

‎Jenkinsfile‎

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,37 @@ def refspecFor(String rev) {
7070
return "${heads} +refs/pull/${parts[1]}/${parts[2]}:refs/remotes/origin/pr/${parts[1]}"
7171
}
7272

73+
// Resolves rev to the commit to build.
74+
//
75+
// url is the repo to ask.
76+
// rev is what revFor returned: a branch, tag, pull/<n>/merge ref,
77+
// refs/... ref, or commit id.
78+
//
79+
// Returns '' when rev names no ref, as a commit id does.
80+
//
81+
// A bare name is an ls-remote pattern matched against the tail of every ref,
82+
// not a ref name: 'master' also matched core's CFE-159/master, which sorts
83+
// first and so won. Ask for the full ref, refs/heads before refs/tags before
84+
// refs/, and take the first that exists.
85+
def resolveRev(String url, String rev) {
86+
def candidates = rev.startsWith('refs/') ? [rev]
87+
: ["refs/heads/${rev}", "refs/tags/${rev}", "refs/${rev}"]
88+
for (ref in candidates) {
89+
// An annotated tag's own ref names the tag object, its ^{} the commit.
90+
def peeled = "${ref}^{}"
91+
def out = sh(returnStdout: true,
92+
script: "git ls-remote '${url}' '${ref}' '${peeled}'").trim()
93+
def sha = ''
94+
for (line in out.readLines()) {
95+
def parts = line.split()
96+
if (parts[1] == peeled) { return parts[0] }
97+
if (parts[1] == ref) { sha = parts[0] }
98+
}
99+
if (sha) { return sha }
100+
}
101+
return ''
102+
}
103+
73104
// Runs one build in the workspace of the node the caller allocated.
74105
//
75106
// Cleans up after the previous build. Checks out each repo at its commit from
@@ -195,12 +226,7 @@ pipeline {
195226
sshagent(['jenkins-github']) {
196227
repos.each { repo ->
197228
def rev = revs[repo]
198-
// "refs/$rev" as well, so pull/<n>/merge resolves like it does in
199-
// the other jobs. No pipe: it would mask git's own exit status, and
200-
// an unreachable repo would then look like an unresolvable ref.
201-
def out = sh(returnStdout: true, script:
202-
"git ls-remote git@github.com:cfengine/${repo}.git '${rev}' 'refs/${rev}'").trim()
203-
def sha = out ? out.readLines()[0].split()[0] : ''
229+
def sha = resolveRev("git@github.com:cfengine/${repo}.git", rev)
204230
if (!sha) {
205231
// A commit id matches no ref, which is the one case where an
206232
// empty answer is fine.

0 commit comments

Comments
 (0)