Skip to content

Commit

Permalink
Identify default git branch when downloading pipelines (#3593)
Browse files Browse the repository at this point in the history
Signed-off-by: Tom Sellman <[email protected]>
  • Loading branch information
tom-seqera committed Oct 8, 2024
1 parent 64bb5a9 commit 9133992
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package nextflow.config

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import static nextflow.Const.DEFAULT_BRANCH
import static nextflow.Const.DEFAULT_MAIN_FILE_NAME
/**
* Models the nextflow config manifest settings
Expand Down Expand Up @@ -52,7 +51,7 @@ class Manifest {


String getDefaultBranch() {
target.defaultBranch ?: DEFAULT_BRANCH
target.defaultBranch
}

String getDescription() {
Expand Down
43 changes: 36 additions & 7 deletions modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ import org.eclipse.jgit.merge.MergeStrategy
@Slf4j
@CompileStatic
class AssetManager {
private static final String REMOTE_REFS_ROOT = "refs/remotes/origin/"
private static final String REMOTE_DEFAULT_HEAD = REMOTE_REFS_ROOT + "HEAD"

/**
* The folder all pipelines scripts are installed
Expand Down Expand Up @@ -422,7 +424,14 @@ class AssetManager {
}

String getDefaultBranch() {
getManifest().getDefaultBranch()
// if specified in manifest, that takes priority
String branch = getManifest().getDefaultBranch()
if( !branch ) {
// otherwise look for a symbolic ref (refs/remotes/origin/HEAD)
Ref remoteHead = git.getRepository().findRef(REMOTE_DEFAULT_HEAD)
branch = remoteHead?.getTarget()?.getName()?.substring(REMOTE_REFS_ROOT.length())
}
return branch ?: DEFAULT_BRANCH
}

@Memoized
Expand Down Expand Up @@ -582,7 +591,7 @@ class AssetManager {
final cloneURL = getGitRepositoryUrl()
log.debug "Pulling $project -- Using remote clone url: ${cloneURL}"

// clone it
// clone it, but don't specify a revision - jgit will checkout the default branch
def clone = Git.cloneRepository()
if( provider.hasCredentials() )
clone.setCredentialsProvider( provider.getGitCredentials() )
Expand All @@ -595,9 +604,25 @@ class AssetManager {
clone.setDepth(deep)
clone.call()

// git cli would automatically create a 'refs/remotes/origin/HEAD' symbolic ref pointing at the remote's
// default branch. jgit doesn't do this, but since it automatically checked out the default branch on clone
// we can create the symbolic ref ourselves using the current head
def head = git.getRepository().findRef(Constants.HEAD)
if( head ) {
def headName = head.isSymbolic()
? Repository.shortenRefName(head.getTarget().getName())
: head.getName()

git.repository.getRefDatabase()
.newUpdate(REMOTE_DEFAULT_HEAD, true)
.link(REMOTE_REFS_ROOT + headName)
} else {
log.debug "Unable to determine default branch of repo ${cloneURL}, symbolic ref not created"
}

// now the default branch is recorded in the repo, explicitly checkout the revision (if specified).
// this also allows 'revision' to be a SHA commit id, which isn't supported by the clone command
if( revision ) {
// use an explicit checkout command *after* the clone instead of cloning a specific branch
// because the clone command does not allow the use of SHA commit id (only branch and tag names)
try { git.checkout() .setName(revision) .call() }
catch ( RefNotFoundException e ) { checkoutRemoteBranch(revision) }
}
Expand Down Expand Up @@ -730,6 +755,10 @@ class AssetManager {
}


private static boolean isRemoteBranch(Ref ref) {
return ref.name.startsWith(REMOTE_REFS_ROOT) && ref.name != REMOTE_DEFAULT_HEAD
}

/**
* @return A list of existing branches and tags names. For example
* <pre>
Expand All @@ -750,7 +779,7 @@ class AssetManager {
def master = getDefaultBranch()

List<String> branches = getBranchList()
.findAll { it.name.startsWith('refs/heads/') || it.name.startsWith('refs/remotes/origin/') }
.findAll { it.name.startsWith('refs/heads/') || isRemoteBranch(it) }
.unique { shortenRefName(it.name) }
.collect { Ref it -> refToString(it,current,master,false,level) }

Expand Down Expand Up @@ -785,7 +814,7 @@ class AssetManager {

Map<String, Ref> remote = checkForUpdates ? git.lsRemote().callAsMap() : null
getBranchList()
.findAll { it.name.startsWith('refs/heads/') || it.name.startsWith('refs/remotes/origin/') }
.findAll { it.name.startsWith('refs/heads/') || isRemoteBranch(it) }
.unique { shortenRefName(it.name) }
.each { Ref it -> branches << refToMap(it,remote) }

Expand Down Expand Up @@ -882,7 +911,7 @@ class AssetManager {

def remote = git.lsRemote().callAsMap()
List<String> branches = getBranchList()
.findAll { it.name.startsWith('refs/heads/') || it.name.startsWith('refs/remotes/origin/') }
.findAll { it.name.startsWith('refs/heads/') || isRemoteBranch(it) }
.unique { shortenRefName(it.name) }
.findAll { Ref ref -> hasRemoteChange(ref,remote) }
.collect { Ref ref -> formatUpdate(remote.get(ref.name),level) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class CmdInfoTest extends Specification {
json.repository == "https://github.com/nextflow-io/hello"
json.localPath == "$tempDir/nextflow-io/hello"
json.manifest.mainScript == 'main.nf'
json.manifest.defaultBranch == 'master'
json.manifest.defaultBranch == null
json.revisions.current == 'master'
json.revisions.master == 'master'
json.revisions.branches.size()>1
Expand All @@ -115,7 +115,7 @@ class CmdInfoTest extends Specification {
json.repository == "https://github.com/nextflow-io/hello"
json.localPath == "$tempDir/nextflow-io/hello"
json.manifest.mainScript == 'main.nf'
json.manifest.defaultBranch == 'master'
json.manifest.defaultBranch == null
json.revisions.current == 'master'
json.revisions.master == 'master'
json.revisions.branches.size()>1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ class AssetManagerTest extends Specification {
then:
holder.getMainScriptName() == 'main.nf'
holder.getHomePage() == 'https://github.com/foo/bar'
holder.manifest.getDefaultBranch() == 'master'
holder.manifest.getDefaultBranch() == null
holder.manifest.getDescription() == null

}
Expand Down
6 changes: 6 additions & 0 deletions tests/checks/main-branch.nf/.checks
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
# run remote pipeline, which has default branch 'main'
#
$NXF_CMD -q run nextflow-io/socks $WITH_DOCKER --out result.txt | tee stdout
[[ `grep 'Launching \`https://github.com/nextflow-io/socks\`' .nextflow.log | grep -c '[main]'` == 1 ]] || false
[[ $? == 0 ]] || exit 1
Empty file modified tests/checks/run.sh
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions tests/main-branch.nf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# noop file to trigger evaluation of the checks/main-branch.nf/.checks test script

0 comments on commit 9133992

Please sign in to comment.