From 7d027ec2b2dec33b74ae43d64fbe1e77daccfc38 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 15 Jan 2024 17:29:48 +0800 Subject: [PATCH 01/44] Multiple revisions 1st: AssetManager, Cmd Clone Pull Run Signed-off-by: Dr Marco Claudio De La Pierre --- docs/developer/diagrams/nextflow.scm.mmd | 1 + .../main/groovy/nextflow/cli/CmdClone.groovy | 9 ++++---- .../main/groovy/nextflow/cli/CmdPull.groovy | 8 +++---- .../main/groovy/nextflow/cli/CmdRun.groovy | 9 ++++---- .../groovy/nextflow/scm/AssetManager.groovy | 23 ++++++++++++------- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/docs/developer/diagrams/nextflow.scm.mmd b/docs/developer/diagrams/nextflow.scm.mmd index 1c52075372..dff37b2cda 100644 --- a/docs/developer/diagrams/nextflow.scm.mmd +++ b/docs/developer/diagrams/nextflow.scm.mmd @@ -8,6 +8,7 @@ classDiagram class AssetManager { project : String + revision: String localPath : File mainScript : String repositoryProvider : RepositoryProvider diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index 28c1d209c3..51026ae5b2 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -37,7 +37,7 @@ class CmdClone extends CmdBase implements HubOptions { @Parameter(required=true, description = 'name of the project to clone') List args - @Parameter(names='-r', description = 'Revision to clone - It can be a git branch, tag or revision number') + @Parameter(names='-r', description = 'Revision of the project to clone (either a git branch, tag or commit SHA number)') String revision @Parameter(names=['-d','-deep'], description = 'Create a shallow clone of the specified depth') @@ -52,7 +52,8 @@ class CmdClone extends CmdBase implements HubOptions { Plugins.init() // the pipeline name String pipeline = args[0] - final manager = new AssetManager(pipeline, this) + String revisionSuffix = revision ? ':'+revision : '' + final manager = new AssetManager(pipeline, revision, this) // the target directory is the second parameter // otherwise default the current pipeline name @@ -68,9 +69,9 @@ class CmdClone extends CmdBase implements HubOptions { } manager.checkValidRemoteRepo() - print "Cloning ${manager.project}${revision ? ':'+revision:''} ..." + print "Cloning ${manager.project}${revisionSuffix} ..." manager.clone(target, revision, deep) print "\r" - println "${manager.project} cloned to: $target" + println "${manager.project}${revisionSuffix} cloned to: $target" } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy index 24f7d552d4..143e792542 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy @@ -40,7 +40,7 @@ class CmdPull extends CmdBase implements HubOptions { @Parameter(names='-all', description = 'Update all downloaded projects', arity = 0) boolean all - @Parameter(names=['-r','-revision'], description = 'Revision of the project to run (either a git branch, tag or commit SHA number)') + @Parameter(names=['-r','-revision'], description = 'Revision of the project to pull (either a git branch, tag or commit SHA number)') String revision @Parameter(names=['-d','-deep'], description = 'Create a shallow clone of the specified depth') @@ -73,10 +73,10 @@ class CmdPull extends CmdBase implements HubOptions { Plugins.init() list.each { - log.info "Checking $it ..." - def manager = new AssetManager(it, this) + log.info "Checking $it${revision ? ':'+revision : ''} ..." + def manager = new AssetManager(it, revision, this) - def result = manager.download(revision,deep) + def result = manager.download(revision, deep) manager.updateModules() def scriptFile = manager.getScriptFile() diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy index 98b90f5d01..896ee3a9c0 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy @@ -518,22 +518,21 @@ class CmdRun extends CmdBase implements HubOptions { /* * try to look for a pipeline in the repository */ - def manager = new AssetManager(pipelineName, this) + def manager = new AssetManager(pipelineName, revision, this) def repo = manager.getProject() boolean checkForUpdate = true if( !manager.isRunnable() || latest ) { if( offline ) throw new AbortOperationException("Unknown project `$repo` -- NOTE: automatic download from remote repositories is disabled") - log.info "Pulling $repo ..." - def result = manager.download(revision,deep) + log.info "Pulling $repo${revision ? ':'+revision : ''} ..." + def result = manager.download(revision, deep) if( result ) log.info " $result" checkForUpdate = false } - // checkout requested revision + // post download operations try { - manager.checkout(revision) manager.updateModules() final scriptFile = manager.getScriptFile(mainScript) if( checkForUpdate && !offline ) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index a38ec5b2ec..5866cb60cc 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -69,6 +69,12 @@ class AssetManager { */ private String project + /** + * The name of the commit/branch/tag as requested via command line + * This is now a first class attribute of a pipeline + */ + private String revision + /** * Directory where the pipeline is cloned (i.e. downloaded) */ @@ -96,18 +102,18 @@ class AssetManager { * * @param pipeline The pipeline to be managed by this manager e.g. {@code nextflow-io/hello} */ - AssetManager( String pipelineName, HubOptions cliOpts = null) { + AssetManager( String pipelineName, String revisionName = null, HubOptions cliOpts = null) { assert pipelineName // read the default config file (if available) def config = ProviderConfig.getDefault() // build the object - build(pipelineName, config, cliOpts) + build(pipelineName, revisionName, config, cliOpts) } - AssetManager( String pipelineName, Map config ) { + AssetManager( String pipelineName, String revisionName = null, Map config) { assert pipelineName // build the object - build(pipelineName, config) + build(pipelineName, revisionName, config) } /** @@ -119,12 +125,13 @@ class AssetManager { * @return The {@link AssetManager} object itself */ @PackageScope - AssetManager build( String pipelineName, Map config = null, HubOptions cliOpts = null ) { + AssetManager build( String pipelineName, String revisionName = null, Map config = null, HubOptions cliOpts = null ) { this.providerConfigs = ProviderConfig.createFromMap(config) this.project = resolveName(pipelineName) - this.localPath = checkProjectDir(project) + this.revision = revisionName + this.localPath = checkProjectDir(project, revision) this.hub = checkHubProvider(cliOpts) this.provider = createHubProvider(hub) setupCredentials(cliOpts) @@ -176,13 +183,13 @@ class AssetManager { * @return The project dir {@link File} */ @PackageScope - File checkProjectDir(String projectName) { + File checkProjectDir(String projectName, String revision) { if( !isValidProjectName(projectName)) { throw new IllegalArgumentException("Not a valid project name: $projectName") } - new File(root, project) + new File(root, project + (revision ? ':'+revision : '')) } /** From 106e8dfba28bcbc747a8ad200d6b38f941009ec2 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Tue, 16 Jan 2024 15:45:13 +0800 Subject: [PATCH 02/44] removed revision paramter from clone pull run Signed-off-by: Dr Marco Claudio De La Pierre --- .../main/groovy/nextflow/cli/CmdClone.groovy | 2 +- .../main/groovy/nextflow/cli/CmdPull.groovy | 2 +- .../main/groovy/nextflow/cli/CmdRun.groovy | 2 +- .../groovy/nextflow/scm/AssetManager.groovy | 32 ++++++++++--------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index 51026ae5b2..3b4551195c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -70,7 +70,7 @@ class CmdClone extends CmdBase implements HubOptions { manager.checkValidRemoteRepo() print "Cloning ${manager.project}${revisionSuffix} ..." - manager.clone(target, revision, deep) + manager.clone(target, deep) print "\r" println "${manager.project}${revisionSuffix} cloned to: $target" } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy index 143e792542..025d4bab49 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy @@ -76,7 +76,7 @@ class CmdPull extends CmdBase implements HubOptions { log.info "Checking $it${revision ? ':'+revision : ''} ..." def manager = new AssetManager(it, revision, this) - def result = manager.download(revision, deep) + def result = manager.download(deep) manager.updateModules() def scriptFile = manager.getScriptFile() diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy index 896ee3a9c0..b19946b593 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy @@ -526,7 +526,7 @@ class CmdRun extends CmdBase implements HubOptions { if( offline ) throw new AbortOperationException("Unknown project `$repo` -- NOTE: automatic download from remote repositories is disabled") log.info "Pulling $repo${revision ? ':'+revision : ''} ..." - def result = manager.download(revision, deep) + def result = manager.download(deep) if( result ) log.info " $result" checkForUpdate = false diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 5866cb60cc..ac1b4334a6 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -100,7 +100,8 @@ class AssetManager { /** * Create a new asset manager with the specified pipeline name * - * @param pipeline The pipeline to be managed by this manager e.g. {@code nextflow-io/hello} + * @param pipelineName The pipeline to be managed by this manager e.g. {@code nextflow-io/hello} + * @param revision Revision ID for the selected pipeline (git branch, tag or commit SHA number) */ AssetManager( String pipelineName, String revisionName = null, HubOptions cliOpts = null) { assert pipelineName @@ -120,6 +121,7 @@ class AssetManager { * Build the asset manager internal data structure * * @param pipelineName A project name or a project repository Git URL + * @param revisionName Revision ID for the selected pipeline (git branch, tag or commit SHA number) * @param config A {@link Map} holding the configuration properties defined in the {@link ProviderConfig#DEFAULT_SCM_FILE} file * @param cliOpts User credentials provided on the command line. See {@link HubOptions} trait * @return The {@link AssetManager} object itself @@ -180,6 +182,7 @@ class AssetManager { * and return the directory where the project is stored locally * * @param projectName A project name matching the pattern {@code owner/project} + * @param revision Revision ID for the selected pipeline (git branch, tag or commit SHA number) * @return The project dir {@link File} */ @PackageScope @@ -374,7 +377,8 @@ class AssetManager { return this } - AssetManager checkValidRemoteRepo(String revision=null) { + // TODO MARCO: refactor init of revision in provider + AssetManager checkValidRemoteRepo() { // Configure the git provider to use the required revision as source for all needed remote resources: // - config if present in repo (nextflow.config by default) // - main script (main.nf by default) @@ -576,19 +580,18 @@ class AssetManager { /** * Download a pipeline from a remote Github repository * - * @param revision The revision to download * @result A message representing the operation result */ - String download(String revision=null, Integer deep=null) { + String download(Integer deep=null) { assert project /* - * if the pipeline already exists locally pull it from the remote repo + * if the pipeline does not exists locally pull it from the remote repo */ if( !localPath.exists() ) { localPath.parentFile.mkdirs() // make sure it contains a valid repository - checkValidRemoteRepo(revision) + checkValidRemoteRepo() final cloneURL = getGitRepositoryUrl() log.debug "Pulling $project -- Using remote clone url: ${cloneURL}" @@ -610,14 +613,14 @@ class AssetManager { // 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) } + catch ( RefNotFoundException e ) { checkoutRemoteBranch() } } // return status message return "downloaded from ${cloneURL}" } - log.debug "Pull pipeline $project -- Using local path: $localPath" + log.debug "Pulling $project -- Using local path: $localPath" // verify that is clean if( !isClean() ) @@ -635,7 +638,7 @@ class AssetManager { * Try to checkout it from a remote branch and return */ catch ( RefNotFoundException e ) { - final ref = checkoutRemoteBranch(revision) + final ref = checkoutRemoteBranch() final commitId = ref?.getObjectId() return commitId ? "checked out at ${commitId.name()}" @@ -673,13 +676,12 @@ class AssetManager { * Clone a pipeline from a remote pipeline repository to the specified folder * * @param directory The folder when the pipeline will be cloned - * @param revision The revision to be cloned. It can be a branch, tag, or git revision number */ - void clone(File directory, String revision = null, Integer deep=null) { + void clone(File directory, Integer deep=null) { def clone = Git.cloneRepository() def uri = getGitRepositoryUrl() - log.debug "Clone project `$project` -- Using remote URI: ${uri} into: $directory" + log.debug "Cloning `$project` -- Using remote URI: ${uri} into: $directory" if( !uri ) throw new AbortOperationException("Cannot find the specified project: $project") @@ -936,13 +938,13 @@ class AssetManager { git.checkout().setName(revision) .call() } catch( RefNotFoundException e ) { - checkoutRemoteBranch(revision) + checkoutRemoteBranch() } } - protected Ref checkoutRemoteBranch( String revision ) { + protected Ref checkoutRemoteBranch() { try { def fetch = git.fetch() @@ -1008,7 +1010,7 @@ class AssetManager { if( provider.hasCredentials() ) update.setCredentialsProvider( provider.getGitCredentials() ) def updatedList = update.call() - log.debug "Update submodules $updatedList" + log.debug "Updating submodules $updatedList" } protected String getRemoteCommitId(RevisionInfo rev) { From 0a9e6f807fffcfc2e8b9b4db89991deb6856723b Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Tue, 16 Jan 2024 15:45:24 +0800 Subject: [PATCH 03/44] updated unit tests for AssetManager Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/scm/AssetManagerTest.groovy | 76 +++++-------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy index e17022f58a..66784fd5bf 100644 --- a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy @@ -184,15 +184,15 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/hello', "v1.2", [providers: [github: [auth: token]]]) when: - manager.download("v1.2") + manager.download() then: - folder.resolve('nextflow-io/hello/.git').isDirectory() + folder.resolve('nextflow-io/hello:v1.2/.git').isDirectory() when: - manager.download("v1.2") + manager.download() then: noExceptionThrown() } @@ -204,15 +204,15 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/hello', "6b9515aba6c7efc6a9b3f273ce116fc0c224bf68", [providers: [github: [auth: token]]]) when: - manager.download("6b9515aba6c7efc6a9b3f273ce116fc0c224bf68") + manager.download() then: - folder.resolve('nextflow-io/hello/.git').isDirectory() + folder.resolve('nextflow-io/hello:6b9515aba6c7efc6a9b3f273ce116fc0c224bf68/.git').isDirectory() when: - def result = manager.download("6b9515aba6c7efc6a9b3f273ce116fc0c224bf68") + def result = manager.download() then: noExceptionThrown() result == "Already-up-to-date" @@ -227,35 +227,12 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) - - when: - manager.download("mybranch") - then: - folder.resolve('nextflow-io/hello/.git').isDirectory() + def manager = new AssetManager().build('nextflow-io/hello', "mybranch", [providers: [github: [auth: token]]]) when: - manager.download("mybranch") - then: - noExceptionThrown() - } - - // First clone a repo with a tag, then forget to include the -r argument - // when you execute nextflow. - // Note that while the download will work, execution will fail subsequently - // at a separate check - this just tests that we don't fail because of a detached head. - @Requires({System.getenv('NXF_GITHUB_ACCESS_TOKEN')}) - def testPullTagThenBranch() { - - given: - def folder = tempDir.getRoot() - def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) - - when: - manager.download("v1.2") + manager.download() then: - folder.resolve('nextflow-io/hello/.git').isDirectory() + folder.resolve('nextflow-io/hello:mybranch/.git').isDirectory() when: manager.download() @@ -551,19 +528,14 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/nf-test-branch', [providers: [github: [auth: token]]]) - - when: - manager.download("dev") - then: - folder.resolve('nextflow-io/nf-test-branch/.git').isDirectory() - and: - folder.resolve('nextflow-io/nf-test-branch/workflow.nf').text == "println 'Hello'\n" + def manager = new AssetManager().build('nextflow-io/nf-test-branch', "dev", [providers: [github: [auth: token]]]) when: manager.download() then: - noExceptionThrown() + folder.resolve('nextflow-io/nf-test-branch:dev/.git').isDirectory() + and: + folder.resolve('nextflow-io/nf-test-branch:dev/workflow.nf').text == "println 'Hello'\n" } @Requires({System.getenv('NXF_GITHUB_ACCESS_TOKEN')}) @@ -571,13 +543,12 @@ class AssetManagerTest extends Specification { given: def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/nf-test-branch', [providers: [github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/nf-test-branch', 'dev', [providers: [github: [auth: token]]]) expect: - manager.checkValidRemoteRepo('dev') + manager.checkValidRemoteRepo() and: manager.getMainScriptName() == 'workflow.nf' - } @Requires({System.getenv('NXF_GITHUB_ACCESS_TOKEN')}) @@ -586,19 +557,14 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/nf-test-branch', [providers: [github: [auth: token]]]) - - when: - manager.download("v0.1") - then: - folder.resolve('nextflow-io/nf-test-branch/.git').isDirectory() - and: - folder.resolve('nextflow-io/nf-test-branch/workflow.nf').text == "println 'Hello'\n" + def manager = new AssetManager().build('nextflow-io/nf-test-branch', "v0.1", [providers: [github: [auth: token]]]) when: manager.download() then: - noExceptionThrown() + folder.resolve('nextflow-io/nf-test-branch:v0.1/.git').isDirectory() + and: + folder.resolve('nextflow-io/nf-test-branch:v0.1/workflow.nf').text == "println 'Hello'\n" } } From 5a9b159d09658926b0bc959faa7e8b703aed33c4 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Tue, 16 Jan 2024 16:28:45 +0800 Subject: [PATCH 04/44] AssetManager provider.revision assigned at AssetManager object creation Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index ac1b4334a6..344133a03b 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -136,6 +136,7 @@ class AssetManager { this.localPath = checkProjectDir(project, revision) this.hub = checkHubProvider(cliOpts) this.provider = createHubProvider(hub) + this.provider.setRevision(revision) setupCredentials(cliOpts) validateProjectDir() @@ -377,12 +378,8 @@ class AssetManager { return this } - // TODO MARCO: refactor init of revision in provider AssetManager checkValidRemoteRepo() { - // Configure the git provider to use the required revision as source for all needed remote resources: - // - config if present in repo (nextflow.config by default) - // - main script (main.nf by default) - provider.revision = revision + // Check that the remote git provider contains the main script file (main.nf by default) final scriptName = getMainScriptName() provider.validateFor(scriptName) return this From 94d34f3bd41f370e4674dc0680d567ef23be4c20 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Tue, 16 Jan 2024 21:11:27 +0800 Subject: [PATCH 05/44] Codespell typo in changelog Signed-off-by: Dr Marco Claudio De La Pierre --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 6b2be1e2ef..5eafa10eff 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,7 +4,7 @@ NEXTFLOW CHANGE-LOG - Fix bug with Fusion symlink resolution (#4593) [f28c9e48] - Fix Fusion symlinks when publishing files (#4348) [1fa5878a] - Fix Inspect command fails with Singularity [25883df3] -- Fix Allow the use of error build-in function in onComplete handler (#4458) [ci fast] [4be10cd3] +- Fix Allow the use of error built-in function in onComplete handler (#4458) [ci fast] [4be10cd3] - Fix Harden regular expression to used to strip secrets in logs (#4563) [ci fast] [0102d4d6] - Fix custom notification template [40980bcb] - Fix container environment with special chars (#4594) [f4e00601] From 4744774bf29c403994d4b45b707ae8c90a926f01 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Tue, 16 Jan 2024 21:37:51 +0800 Subject: [PATCH 06/44] AssetManager: removed checkout method Signed-off-by: Dr Marco Claudio De La Pierre --- .../groovy/nextflow/scm/AssetManager.groovy | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 344133a03b..6d2a1c7214 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -909,37 +909,6 @@ class AssetManager { return result } - /** - * Checkout a specific revision - * @param revision The revision to be checked out - */ - void checkout( String revision = null ) { - assert localPath - - def current = getCurrentRevision() - if( current != defaultBranch ) { - if( !revision ) { - throw new AbortOperationException("Project `$project` is currently stickied on revision: $current -- you need to explicitly specify a revision with the option `-r` in order to use it") - } - } - if( !revision || revision == current ) { - // nothing to do - return - } - - // verify that is clean - if( !isClean() ) - throw new AbortOperationException("Project `$project` contains uncommitted changes -- Cannot switch to revision: $revision") - - try { - git.checkout().setName(revision) .call() - } - catch( RefNotFoundException e ) { - checkoutRemoteBranch() - } - - } - protected Ref checkoutRemoteBranch() { From 08718ef0fe8c66bfd90a1fccca3113ae23824c5a Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 17 Jan 2024 12:02:01 +0800 Subject: [PATCH 07/44] assetmanager: fixed build signature, and unit tests Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 4 ++-- .../src/test/groovy/nextflow/cli/CmdInfoTest.groovy | 3 ++- .../src/test/groovy/nextflow/scm/AssetManagerTest.groovy | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 6d2a1c7214..ecf85b881d 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -111,7 +111,7 @@ class AssetManager { build(pipelineName, revisionName, config, cliOpts) } - AssetManager( String pipelineName, String revisionName = null, Map config) { + AssetManager( String pipelineName, String revisionName, Map config) { assert pipelineName // build the object build(pipelineName, revisionName, config) @@ -127,7 +127,7 @@ class AssetManager { * @return The {@link AssetManager} object itself */ @PackageScope - AssetManager build( String pipelineName, String revisionName = null, Map config = null, HubOptions cliOpts = null ) { + AssetManager build( String pipelineName, String revisionName, Map config = null, HubOptions cliOpts = null ) { this.providerConfigs = ProviderConfig.createFromMap(config) diff --git a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy index 3ec57a2427..1ad1d73e3a 100644 --- a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy @@ -45,8 +45,9 @@ class CmdInfoTest extends Specification { def setupSpec() { tempDir = Files.createTempDirectory('test') AssetManager.root = tempDir.toFile() + String revision = null def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/hello', revision, [providers: [github: [auth: token]]]) // download the project manager.download() } diff --git a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy index 66784fd5bf..a1f796bd56 100644 --- a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy @@ -162,8 +162,9 @@ class AssetManagerTest extends Specification { given: def folder = tempDir.getRoot() + String revision = null def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers: [github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/hello', revision, [providers: [github: [auth: token]]]) when: manager.download() @@ -246,8 +247,9 @@ class AssetManagerTest extends Specification { given: def dir = tempDir.getRoot() + String revision = null def token = System.getenv('NXF_GITHUB_ACCESS_TOKEN') - def manager = new AssetManager().build('nextflow-io/hello', [providers:[github: [auth: token]]]) + def manager = new AssetManager().build('nextflow-io/hello', revision, [providers:[github: [auth: token]]]) when: manager.clone(dir.toFile()) From 242a600d98116f6a8c6f822f63e813bb2d298153 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 17 Jan 2024 12:07:53 +0800 Subject: [PATCH 08/44] assetmanager: one more build signature fix Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index ecf85b881d..faf5ec1497 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -127,7 +127,7 @@ class AssetManager { * @return The {@link AssetManager} object itself */ @PackageScope - AssetManager build( String pipelineName, String revisionName, Map config = null, HubOptions cliOpts = null ) { + AssetManager build( String pipelineName, String revisionName = null, Map config = null, HubOptions cliOpts = null ) { this.providerConfigs = ProviderConfig.createFromMap(config) From 35ad1e9931c02385c1f67595211ee97fa671a17d Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 17 Jan 2024 17:17:14 +0800 Subject: [PATCH 09/44] AssetManager: fix for multi revs in find() method Signed-off-by: Dr Marco Claudio De La Pierre --- .../groovy/nextflow/scm/AssetManager.groovy | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index faf5ec1497..55ac8aa622 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -131,7 +131,7 @@ class AssetManager { this.providerConfigs = ProviderConfig.createFromMap(config) - this.project = resolveName(pipelineName) + this.project = resolveName(pipelineName, revisionName) this.revision = revisionName this.localPath = checkProjectDir(project, revision) this.hub = checkHubProvider(cliOpts) @@ -253,7 +253,7 @@ class AssetManager { * @param name A project name or URL e.g. {@code cbcrg/foo} or {@code https://github.com/cbcrg/foo.git} * @return The fully qualified project name e.g. {@code cbcrg/foo} */ - String resolveName( String name ) { + String resolveName( String name, String revision = null ) { assert name // @@ -295,7 +295,7 @@ class AssetManager { name = parts[0] } - def qualifiedName = find(name) + def qualifiedName = find(name, revision) if( !qualifiedName ) { return "$DEFAULT_ORGANIZATION/$name".toString() } @@ -550,16 +550,19 @@ class AssetManager { return result } - static protected def find( String name ) { + static protected def find( String name, String revision = null ) { def exact = [] def partial = [] list().each { def items = it.split('/') - if( items[1] == name ) - exact << it - else if( items[1].startsWith(name ) ) - partial << it + def itemsRev = items[1].tokenize(':') + if( (!revision && !itemsRev[1]) || (revision && itemsRev[1] == revision) ) { + if( itemsRev[0] == name ) + exact << it.tokenize(':')[0] + else if( itemsRev[0].startsWith(name ) ) + partial << it.tokenize(':')[0] + } } def list = exact ?: partial From 463b6f169cfa140de49126a1edbf1b824855df51 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 17 Jan 2024 17:48:10 +0800 Subject: [PATCH 10/44] Multiple revisions: added for Cmds Drop, View, Config, Info Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/cli/CmdConfig.groovy | 5 ++++- .../nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy | 9 ++++++--- .../nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy | 7 +++++-- .../nextflow/src/main/groovy/nextflow/cli/CmdView.groovy | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdConfig.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdConfig.groovy index 29b874198b..c47ec4cd0f 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdConfig.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdConfig.groovy @@ -44,6 +44,9 @@ class CmdConfig extends CmdBase { @Parameter(description = 'project name') List args = [] + @Parameter(names=['-r','-revision'], description = 'Revision of the project (either a git branch, tag or commit SHA number)') + String revision + @Parameter(names=['-a','-show-profiles'], description = 'Show all configuration profiles') boolean showAllProfiles @@ -182,7 +185,7 @@ class CmdConfig extends CmdBase { return file.parent ?: Paths.get('/') } - final manager = new AssetManager(path) + final manager = new AssetManager(path, revision) manager.isLocal() ? manager.localPath.toPath() : manager.configFile?.parent } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index dd36368854..c611d41326 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -39,6 +39,9 @@ class CmdDrop extends CmdBase { @Parameter(required=true, description = 'name of the project to drop') List args + @Parameter(names=['-r','-revision'], description = 'Revision of the project to drop (either a git branch, tag or commit SHA number)') + String revision + @Parameter(names='-f', description = 'Delete the repository without taking care of local changes') boolean force @@ -48,15 +51,15 @@ class CmdDrop extends CmdBase { @Override void run() { Plugins.init() - def manager = new AssetManager(args[0]) + def manager = new AssetManager(args[0], revision) if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${args[0]}") + throw new AbortOperationException("No match found for: ${args[0]}${revision ? ':'+revision : ''}") } if( this.force || manager.isClean() ) { manager.close() if( !manager.localPath.deleteDir() ) - throw new AbortOperationException("Unable to delete project `${manager.project}` -- Check access permissions for path: ${manager.localPath}") + throw new AbortOperationException("Unable to delete project `${manager.project}${revision ? ':'+revision : ''}` -- Check access permissions for path: ${manager.localPath}") return } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index e679d1fcd5..96995f58d5 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -50,6 +50,9 @@ class CmdInfo extends CmdBase { @Parameter(description = 'project name') List args + @Parameter(names=['-r','-revision'], description = 'Revision of the project (either a git branch, tag or commit SHA number)') + String revision + @Parameter(names='-d',description = 'Show detailed information', arity = 0) boolean detailed @@ -75,9 +78,9 @@ class CmdInfo extends CmdBase { } Plugins.init() - final manager = new AssetManager(args[0]) + final manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project `${args[0]}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? ':'+revision : ''}`") if( !format || format == 'text' ) { printText(manager,level) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy index d38befaf07..14d2addc5b 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy @@ -42,6 +42,9 @@ class CmdView extends CmdBase { @Parameter(description = 'project name', required = true) List args = [] + @Parameter(names=['-r','-revision'], description = 'Revision of the project (either a git branch, tag or commit SHA number)') + String revision + @Parameter(names = '-q', description = 'Hide header line', arity = 0) boolean quiet @@ -51,9 +54,9 @@ class CmdView extends CmdBase { @Override void run() { Plugins.init() - def manager = new AssetManager(args[0]) + def manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project name `${args[0]}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? ':'+revision : ''}`") if( all ) { if( !quiet ) From 2d3273e63ae074093837e7c1f83e1842861b1b43 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 17 Jan 2024 17:53:01 +0800 Subject: [PATCH 11/44] minor fixes to log outputs in CmdRun Signed-off-by: Dr Marco Claudio De La Pierre --- modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy index b19946b593..c3667ad52e 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy @@ -524,7 +524,7 @@ class CmdRun extends CmdBase implements HubOptions { boolean checkForUpdate = true if( !manager.isRunnable() || latest ) { if( offline ) - throw new AbortOperationException("Unknown project `$repo` -- NOTE: automatic download from remote repositories is disabled") + throw new AbortOperationException("Unknown project `$repo${revision ? ':'+revision : ''}` -- NOTE: automatic download from remote repositories is disabled") log.info "Pulling $repo${revision ? ':'+revision : ''} ..." def result = manager.download(deep) if( result ) @@ -544,7 +544,7 @@ class CmdRun extends CmdBase implements HubOptions { throw e } catch( Exception e ) { - throw new AbortOperationException("Unknown error accessing project `$repo` -- Repository may be corrupted: ${manager.localPath}", e) + throw new AbortOperationException("Unknown error accessing project `$repo${revision ? ':'+revision : ''}` -- Repository may be corrupted: ${manager.localPath}", e) } } From d2e5ffeee69f2b684f3554ac88abebe4fc8ee73c Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 18 Jan 2024 12:09:07 +0800 Subject: [PATCH 12/44] AssetManager: documented new localPath schema Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 55ac8aa622..afd9498e83 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -77,6 +77,7 @@ class AssetManager { /** * Directory where the pipeline is cloned (i.e. downloaded) + * New schema: root//: */ private File localPath @@ -550,6 +551,7 @@ class AssetManager { return result } + // updated for new localPath schema (see localPath declaration at top of this class file) static protected def find( String name, String revision = null ) { def exact = [] def partial = [] From 60c3c5ea7a3e597df3c25ef9cc009e28af308fd0 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 18 Jan 2024 12:56:10 +0800 Subject: [PATCH 13/44] K8sDriverLauncher : added revision support Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/k8s/K8sDriverLauncher.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/k8s/K8sDriverLauncher.groovy b/modules/nextflow/src/main/groovy/nextflow/k8s/K8sDriverLauncher.groovy index 2debcfc83d..c3c1483673 100644 --- a/modules/nextflow/src/main/groovy/nextflow/k8s/K8sDriverLauncher.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/k8s/K8sDriverLauncher.groovy @@ -270,7 +270,7 @@ class K8sDriverLauncher { if( !interactive && !pipelineName.startsWith('/') && !cmd.remoteProfile && !cmd.runRemoteConfig ) { // -- check and parse project remote config Plugins.init() - final pipelineConfig = new AssetManager(pipelineName, cmd) .getConfigFile() + final pipelineConfig = new AssetManager(pipelineName, cmd.revision, cmd) .getConfigFile() builder.setUserConfigFiles(pipelineConfig) } From 4bf1e371846ac90247daeb61a9b0950284387e79 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 18 Jan 2024 14:26:19 +0800 Subject: [PATCH 14/44] updates to AssetManagerTest Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/scm/AssetManagerTest.groovy | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy index a1f796bd56..9a2773a40b 100644 --- a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy @@ -110,6 +110,7 @@ class AssetManagerTest extends Specification { def folder = tempDir.getRoot() folder.resolve('cbcrg/pipe1').mkdirs() folder.resolve('cbcrg/pipe2').mkdirs() + folder.resolve('cbcrg/pipe2:v2').mkdirs() folder.resolve('ncbi/blast').mkdirs() def manager = new AssetManager() @@ -119,6 +120,11 @@ class AssetManagerTest extends Specification { then: result == 'x/y' + when: + result = manager.resolveName('x/y', 'v2') + then: + result == 'x/y' + when: result = manager.resolveName('blast') then: @@ -144,6 +150,11 @@ class AssetManagerTest extends Specification { then: thrown(AbortOperationException) + when: + result = manager.resolveName('pipe2', 'v2') + then: + result == 'cbcrg/pipe2' + when: result = manager.resolveName('../blast/script.nf') then: @@ -172,10 +183,10 @@ class AssetManagerTest extends Specification { folder.resolve('nextflow-io/hello/.git').isDirectory() when: - manager.download() + def result = manager.download() then: noExceptionThrown() - + result == "Already-up-to-date" } @@ -193,9 +204,10 @@ class AssetManagerTest extends Specification { folder.resolve('nextflow-io/hello:v1.2/.git').isDirectory() when: - manager.download() + def result = manager.download() then: noExceptionThrown() + result == "Already-up-to-date" } // The hashes used here are NOT associated with tags. @@ -236,9 +248,10 @@ class AssetManagerTest extends Specification { folder.resolve('nextflow-io/hello:mybranch/.git').isDirectory() when: - manager.download() + def result = manager.download() then: noExceptionThrown() + result == "Already-up-to-date" } From 7e3211119601da69bd86891048d3112105221fa8 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 18 Jan 2024 15:19:49 +0800 Subject: [PATCH 15/44] edit to AssetManagerTest, git.pull for TAGS does not output result of operation Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/test/groovy/nextflow/scm/AssetManagerTest.groovy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy index 9a2773a40b..d53da2b52a 100644 --- a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy @@ -204,10 +204,9 @@ class AssetManagerTest extends Specification { folder.resolve('nextflow-io/hello:v1.2/.git').isDirectory() when: - def result = manager.download() + manager.download() then: noExceptionThrown() - result == "Already-up-to-date" } // The hashes used here are NOT associated with tags. From 3b2d461a7688d00fa30fa76b4b5272620f482e88 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 18 Jan 2024 15:53:16 +0800 Subject: [PATCH 16/44] minor fix in GitlabRepositoryProvider: using DEFAULT_BRANCH instead of "master" Signed-off-by: Dr Marco Claudio De La Pierre --- .../main/groovy/nextflow/scm/GitlabRepositoryProvider.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/GitlabRepositoryProvider.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/GitlabRepositoryProvider.groovy index d03123333a..a8b35d429c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/GitlabRepositoryProvider.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/GitlabRepositoryProvider.groovy @@ -18,6 +18,7 @@ package nextflow.scm import groovy.util.logging.Slf4j +import static nextflow.Const.DEFAULT_BRANCH /** * Implements a repository provider for GitHub service * @@ -59,8 +60,8 @@ class GitlabRepositoryProvider extends RepositoryProvider { String getDefaultBranch() { def result = invokeAndParseResponse(getEndpointUrl()) ?. default_branch if( !result ) { - log.debug "Unable to fetch repo default branch. Using `master` branch -- See https://gitlab.com/gitlab-com/support-forum/issues/1655#note_26132691" - return 'master' + log.debug "Unable to fetch repo default branch. Using `${DEFAULT_BRANCH}` branch -- See https://gitlab.com/gitlab-com/support-forum/issues/1655#note_26132691" + return DEFAULT_BRANCH } return result } From 2e6461e76af6d1087095edad020a74f1b2a71816 Mon Sep 17 00:00:00 2001 From: Ben Sherman Date: Tue, 23 Jan 2024 11:48:08 -0600 Subject: [PATCH 17/44] Minor edits Signed-off-by: Ben Sherman --- docs/developer/diagrams/nextflow.scm.mmd | 2 +- .../main/groovy/nextflow/cli/CmdDrop.groovy | 2 +- .../groovy/nextflow/scm/AssetManager.groovy | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/developer/diagrams/nextflow.scm.mmd b/docs/developer/diagrams/nextflow.scm.mmd index dff37b2cda..a512e36a75 100644 --- a/docs/developer/diagrams/nextflow.scm.mmd +++ b/docs/developer/diagrams/nextflow.scm.mmd @@ -8,7 +8,7 @@ classDiagram class AssetManager { project : String - revision: String + revision : String localPath : File mainScript : String repositoryProvider : RepositoryProvider diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index c611d41326..61451a2b67 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -53,7 +53,7 @@ class CmdDrop extends CmdBase { Plugins.init() def manager = new AssetManager(args[0], revision) if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${args[0]}${revision ? ':'+revision : ''}") + throw new AbortOperationException("No match found for: ${manager.project}${revision ? ':'+revision : ''}") } if( this.force || manager.isClean() ) { diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index afd9498e83..6c88386171 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -77,7 +77,8 @@ class AssetManager { /** * Directory where the pipeline is cloned (i.e. downloaded) - * New schema: root//: + * + * Schema: $NXF_ASSETS//[:] */ private File localPath @@ -104,36 +105,36 @@ class AssetManager { * @param pipelineName The pipeline to be managed by this manager e.g. {@code nextflow-io/hello} * @param revision Revision ID for the selected pipeline (git branch, tag or commit SHA number) */ - AssetManager( String pipelineName, String revisionName = null, HubOptions cliOpts = null) { + AssetManager( String pipelineName, String revision = null, HubOptions cliOpts = null) { assert pipelineName // read the default config file (if available) def config = ProviderConfig.getDefault() // build the object - build(pipelineName, revisionName, config, cliOpts) + build(pipelineName, revision, config, cliOpts) } - AssetManager( String pipelineName, String revisionName, Map config) { + AssetManager( String pipelineName, String revision, Map config) { assert pipelineName // build the object - build(pipelineName, revisionName, config) + build(pipelineName, revision, config) } /** * Build the asset manager internal data structure * * @param pipelineName A project name or a project repository Git URL - * @param revisionName Revision ID for the selected pipeline (git branch, tag or commit SHA number) + * @param revision Revision ID for the selected pipeline (git branch, tag or commit SHA number) * @param config A {@link Map} holding the configuration properties defined in the {@link ProviderConfig#DEFAULT_SCM_FILE} file * @param cliOpts User credentials provided on the command line. See {@link HubOptions} trait * @return The {@link AssetManager} object itself */ @PackageScope - AssetManager build( String pipelineName, String revisionName = null, Map config = null, HubOptions cliOpts = null ) { + AssetManager build( String pipelineName, String revision = null, Map config = null, HubOptions cliOpts = null ) { this.providerConfigs = ProviderConfig.createFromMap(config) - this.project = resolveName(pipelineName, revisionName) - this.revision = revisionName + this.project = resolveName(pipelineName, revision) + this.revision = revision this.localPath = checkProjectDir(project, revision) this.hub = checkHubProvider(cliOpts) this.provider = createHubProvider(hub) @@ -683,7 +684,7 @@ class AssetManager { def clone = Git.cloneRepository() def uri = getGitRepositoryUrl() - log.debug "Cloning `$project` -- Using remote URI: ${uri} into: $directory" + log.debug "Cloning `${project}` from ${uri} into ${directory}" if( !uri ) throw new AbortOperationException("Cannot find the specified project: $project") @@ -914,7 +915,6 @@ class AssetManager { return result } - protected Ref checkoutRemoteBranch() { try { From b3f141dd27a0afd303c636b2da27368558f49458 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Wed, 28 Feb 2024 06:13:44 +0000 Subject: [PATCH 18/44] parametrised revision delimiter Signed-off-by: Dr Marco De La Pierre --- .../src/main/groovy/nextflow/cli/CmdClone.groovy | 5 ++++- .../src/main/groovy/nextflow/cli/CmdDrop.groovy | 6 ++++-- .../src/main/groovy/nextflow/cli/CmdInfo.groovy | 4 +++- .../src/main/groovy/nextflow/cli/CmdPull.groovy | 5 ++++- .../src/main/groovy/nextflow/cli/CmdRun.groovy | 7 ++++--- .../src/main/groovy/nextflow/cli/CmdView.groovy | 4 +++- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 10 ++++++---- 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index a1cc15188f..3901f76e40 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -15,6 +15,9 @@ */ package nextflow.cli + +import static nextflow.scm.AssetManager.revisionDelim + import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic @@ -52,7 +55,7 @@ class CmdClone extends CmdBase implements HubOptions { Plugins.init() // the pipeline name String pipeline = args[0] - String revisionSuffix = revision ? ':'+revision : '' + String revisionSuffix = revision ? revisionDelim + revision : '' final manager = new AssetManager(pipeline, revision, this) // the target directory is the second parameter diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index 553a8ea723..54b7683e8f 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -16,6 +16,8 @@ package nextflow.cli +import static nextflow.scm.AssetManager.revisionDelim + import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic @@ -53,13 +55,13 @@ class CmdDrop extends CmdBase { Plugins.init() def manager = new AssetManager(args[0], revision) if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${manager.project}${revision ? ':'+revision : ''}") + throw new AbortOperationException("No match found for: ${manager.project}${revision ? revisionDelim + revision : ''}") } if( this.force || manager.isClean() ) { manager.close() if( !manager.localPath.deleteDir() ) - throw new AbortOperationException("Unable to delete project `${manager.project}${revision ? ':'+revision : ''}` -- Check access permissions for path: ${manager.localPath}") + throw new AbortOperationException("Unable to delete project `${manager.project}${revision ? revisionDelim + revision : ''}` -- Check access permissions for path: ${manager.localPath}") return } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index 5c6110adb5..89985c3af8 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -16,6 +16,8 @@ package nextflow.cli +import static nextflow.scm.AssetManager.revisionDelim + import java.lang.management.ManagementFactory import java.nio.file.spi.FileSystemProvider @@ -80,7 +82,7 @@ class CmdInfo extends CmdBase { Plugins.init() final manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project `${args[0]}${revision ? ':'+revision : ''}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") if( !format || format == 'text' ) { printText(manager,level) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy index 80cba9d588..988d4ea085 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy @@ -15,6 +15,9 @@ */ package nextflow.cli + +import static nextflow.scm.AssetManager.revisionDelim + import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic @@ -73,7 +76,7 @@ class CmdPull extends CmdBase implements HubOptions { Plugins.init() list.each { - log.info "Checking $it${revision ? ':'+revision : ''} ..." + log.info "Checking $it${revision ? revisionDelim + revision : ''} ..." def manager = new AssetManager(it, revision, this) def result = manager.download(deep) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy index f0736c29a5..2424f1d75e 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy @@ -18,6 +18,7 @@ package nextflow.cli import static org.fusesource.jansi.Ansi.* +import static nextflow.scm.AssetManager.revisionDelim import java.nio.file.NoSuchFileException import java.nio.file.Path @@ -579,8 +580,8 @@ class CmdRun extends CmdBase implements HubOptions { boolean checkForUpdate = true if( !manager.isRunnable() || latest ) { if( offline ) - throw new AbortOperationException("Unknown project `$repo${revision ? ':'+revision : ''}` -- NOTE: automatic download from remote repositories is disabled") - log.info "Pulling $repo${revision ? ':'+revision : ''} ..." + throw new AbortOperationException("Unknown project `$repo${revision ? revisionDelim + revision : ''}` -- NOTE: automatic download from remote repositories is disabled") + log.info "Pulling $repo${revision ? revisionDelim + revision : ''} ..." def result = manager.download(deep) if( result ) log.info " $result" @@ -599,7 +600,7 @@ class CmdRun extends CmdBase implements HubOptions { throw e } catch( Exception e ) { - throw new AbortOperationException("Unknown error accessing project `$repo${revision ? ':'+revision : ''}` -- Repository may be corrupted: ${manager.localPath}", e) + throw new AbortOperationException("Unknown error accessing project `$repo${revision ? revisionDelim + revision : ''}` -- Repository may be corrupted: ${manager.localPath}", e) } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy index 8ef0dc9cff..42901f5f70 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy @@ -16,6 +16,8 @@ package nextflow.cli +import static nextflow.scm.AssetManager.revisionDelim + import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic @@ -56,7 +58,7 @@ class CmdView extends CmdBase { Plugins.init() def manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project `${args[0]}${revision ? ':'+revision : ''}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") if( all ) { if( !quiet ) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 80fec899eb..c9b0ee32d1 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -62,6 +62,8 @@ class AssetManager { @PackageScope static File root = DEFAULT_ROOT + static public final String revisionDelim = ':' + /** * The pipeline name. It must be in the form {@code username/repo} where 'username' * is a valid user name or organisation account, while 'repo' is the repository name @@ -133,12 +135,12 @@ class AssetManager { this.providerConfigs = ProviderConfig.createFromMap(config) - this.project = resolveName(pipelineName, revision) this.revision = revision - this.localPath = checkProjectDir(project, revision) + this.project = resolveName(pipelineName, this.revision) + this.localPath = checkProjectDir(project, this.revision) this.hub = checkHubProvider(cliOpts) this.provider = createHubProvider(hub) - this.provider.setRevision(revision) + this.provider.setRevision(this.revision) setupCredentials(cliOpts) validateProjectDir() @@ -195,7 +197,7 @@ class AssetManager { throw new IllegalArgumentException("Not a valid project name: $projectName") } - new File(root, project + (revision ? ':'+revision : '')) + new File(root, project + (revision ? revisionDelim + revision : '')) } /** From 6706bd9a99a75dc169ad06774da16d0dca8ffa5c Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Wed, 28 Feb 2024 07:39:06 +0000 Subject: [PATCH 19/44] nf pull: option to list or not revs for each project Signed-off-by: Dr Marco De La Pierre --- .../src/main/groovy/nextflow/cli/CmdList.groovy | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 5b08be249a..068706af37 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -16,6 +16,9 @@ package nextflow.cli +import static nextflow.scm.AssetManager.revisionDelim + +import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -33,6 +36,9 @@ class CmdList extends CmdBase { static final public NAME = 'list' + @Parameter(names=['-r','-revisions'], description = 'For each project, also list revisions') + Boolean revisions + @Override final String getName() { NAME } @@ -45,7 +51,11 @@ class CmdList extends CmdBase { return } + if (revisions) { all.each { println it } + } else { + all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) }.unique().each{println it} + } } } From e62f543cf75557f6f79805c7d5c1c0b40e4a92bb Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Wed, 28 Feb 2024 14:46:34 +0000 Subject: [PATCH 20/44] nicer output for nf list -r Signed-off-by: Dr Marco De La Pierre --- .../nextflow/src/main/groovy/nextflow/cli/CmdList.groovy | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 068706af37..7ce21dd96a 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -52,9 +52,13 @@ class CmdList extends CmdBase { } if (revisions) { - all.each { println it } + all.collect{ it.tokenize(revisionDelim) } + .groupBy{ it[0] } + .each{ println it.value[0][0] ; it.value.each{ y -> println ( y.size()==1 ? ' (default)' : ' ' + y[1] ) } } } else { - all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) }.unique().each{println it} + all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) } + .unique() + .each{println it} } } From bd198778907f0f808b47387c2095f432c40a6740 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 29 Feb 2024 02:37:21 +0000 Subject: [PATCH 21/44] minor edit to CmdList Signed-off-by: Dr Marco De La Pierre --- modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 7ce21dd96a..54d175fb74 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -36,7 +36,7 @@ class CmdList extends CmdBase { static final public NAME = 'list' - @Parameter(names=['-r','-revisions'], description = 'For each project, also list revisions') + @Parameter(names=['-a','-all-revisions'], description = 'For each project, also list revisions') Boolean revisions @Override @@ -58,7 +58,7 @@ class CmdList extends CmdBase { } else { all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) } .unique() - .each{println it} + .each{ println it } } } From c0268af0f94f2ff9824609b7660f7b3dcc415c02 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 29 Feb 2024 03:12:54 +0000 Subject: [PATCH 22/44] AssetManager: adding listRevisions method (work in progress) Signed-off-by: Dr Marco De La Pierre --- .../groovy/nextflow/scm/AssetManager.groovy | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index c9b0ee32d1..a91d5516ec 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -554,6 +554,30 @@ class AssetManager { return result } + /** + * @return The list of available revisions for a given AssetManager project + */ + static List listRevisions( String project ) { + log.debug "Listing revisions for project: $project" + + def result = new LinkedList() + + if( !root.exists() ) + return result + + def proj = project.tokenize('/').toList() + root.eachDir { File org -> + org.eachDir { File it -> + String itOrg = org.getName().toString() ; + String itName = it.getName().toString().tokenize(revisionDelim)[0] ; + Boolean matches = ( itOrg == proj[0] && itName == proj[1] ) + result << ( matches ? "${org.getName()}/${it.getName()}".toString() : null ) + } + } + + return result + } + // updated for new localPath schema (see localPath declaration at top of this class file) static protected def find( String name, String revision = null ) { def exact = [] From aae2afc17eb2fa616596ce4e54bac749edc99990 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 29 Feb 2024 11:26:08 +0800 Subject: [PATCH 23/44] small tune to CmdList Signed-off-by: Dr Marco Claudio De La Pierre --- modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 54d175fb74..1c2926070a 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -54,7 +54,7 @@ class CmdList extends CmdBase { if (revisions) { all.collect{ it.tokenize(revisionDelim) } .groupBy{ it[0] } - .each{ println it.value[0][0] ; it.value.each{ y -> println ( y.size()==1 ? ' (default)' : ' ' + y[1] ) } } + .each{ println ' ' + it.value[0][0] ; it.value.each{ y -> println ( y.size()==1 ? ' (default)' : ' ' + y[1] ) } } } else { all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) } .unique() From 268ec7978013bfbceaaabc4d56f1ebc699d8c29a Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 29 Feb 2024 18:02:39 +0800 Subject: [PATCH 24/44] minor tweak to CmdList Signed-off-by: Dr Marco Claudio De La Pierre --- modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 1c2926070a..4f80670dd3 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -58,7 +58,7 @@ class CmdList extends CmdBase { } else { all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) } .unique() - .each{ println it } + .each{ println ' ' + it } } } From ac8d75521bf62818143f63f56bb9e4338106aa54 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 29 Feb 2024 18:03:34 +0800 Subject: [PATCH 25/44] AssetManager: listRevisions method now working Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index a91d5516ec..f8c6b54855 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -555,7 +555,7 @@ class AssetManager { } /** - * @return The list of available revisions for a given AssetManager project + * @return The list of available revisions for a given project name */ static List listRevisions( String project ) { log.debug "Listing revisions for project: $project" @@ -565,13 +565,9 @@ class AssetManager { if( !root.exists() ) return result - def proj = project.tokenize('/').toList() - root.eachDir { File org -> - org.eachDir { File it -> - String itOrg = org.getName().toString() ; - String itName = it.getName().toString().tokenize(revisionDelim)[0] ; - Boolean matches = ( itOrg == proj[0] && itName == proj[1] ) - result << ( matches ? "${org.getName()}/${it.getName()}".toString() : null ) + list().each { + if( it.tokenize(revisionDelim)[0] == project ) { + result << it } } From 70c8bcccfce9fe30299b3993080b769cd85a33ad Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Thu, 29 Feb 2024 18:06:03 +0800 Subject: [PATCH 26/44] CmdDrop option to drop all revisions of given project Signed-off-by: Dr Marco Claudio De La Pierre --- .../main/groovy/nextflow/cli/CmdDrop.groovy | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index 54b7683e8f..9a4ab616fb 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -44,6 +44,9 @@ class CmdDrop extends CmdBase { @Parameter(names=['-r','-revision'], description = 'Revision of the project to drop (either a git branch, tag or commit SHA number)') String revision + @Parameter(names=['-a','-all-revisions'], description = 'For specified project, drop all revisions') + Boolean allrevisions + @Parameter(names='-f', description = 'Delete the repository without taking care of local changes') boolean force @@ -53,18 +56,33 @@ class CmdDrop extends CmdBase { @Override void run() { Plugins.init() - def manager = new AssetManager(args[0], revision) - if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${manager.project}${revision ? revisionDelim + revision : ''}") + + List dropList = [] + if ( allrevisions ) { + AssetManager.listRevisions(args[0]).each { + dropList << new AssetManager(it.tokenize(revisionDelim)[0], it.tokenize(revisionDelim)[1]) + } + } else { + dropList << new AssetManager(args[0], revision) } - if( this.force || manager.isClean() ) { - manager.close() - if( !manager.localPath.deleteDir() ) - throw new AbortOperationException("Unable to delete project `${manager.project}${revision ? revisionDelim + revision : ''}` -- Check access permissions for path: ${manager.localPath}") - return + if ( !dropList ) { + throw new AbortOperationException("No revisions found for specified project: ${args[0]}") } - throw new AbortOperationException("Local project repository contains uncommitted changes -- won't drop it") + dropList.each { manager -> + if( !manager.localPath.exists() ) { + throw new AbortOperationException("No match found for: ${manager.project}${manager.revision ? revisionDelim + manager.revision : ''}") + } + + if( this.force || manager.isClean() ) { + manager.close() + if( !manager.localPath.deleteDir() ) + throw new AbortOperationException("Unable to delete project `${manager.project}${manager.revision ? revisionDelim + manager.revision : ''}` -- Check access permissions for path: ${manager.localPath}") + return + } + + throw new AbortOperationException("Local project repository contains uncommitted changes -- won't drop it") + } } } From 8bcd717e8f0253a1288adbda8f621f80014f40f7 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 11:55:52 +0100 Subject: [PATCH 27/44] AssetManagerTest: added test for method listRevisions Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/scm/AssetManagerTest.groovy | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy index 068c20dc9c..6531f84c21 100644 --- a/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/scm/AssetManagerTest.groovy @@ -103,6 +103,32 @@ class AssetManagerTest extends Specification { } + def testListRevisions() { + given: + def folder = tempDir.getRoot() + folder.resolve('cbcrg/pipe1').mkdirs() + folder.resolve('cbcrg/pipe2').mkdirs() + folder.resolve('cbcrg/pipe2:v2').mkdirs() + folder.resolve('cbcrg/pipe3:v3').mkdirs() + + def manager = new AssetManager() + + when: + def list = manager.listRevisions('cbcrg/pipe1') + then: + list == ['cbcrg/pipe1'] + + when: + list = manager.listRevisions('cbcrg/pipe3') + then: + list == ['cbcrg/pipe3:v3'] + + when: + list = manager.listRevisions('cbcrg/pipe2') + then: + list == ['cbcrg/pipe2', 'cbcrg/pipe2:v2'] + } + def testResolveName() { From 4616e7f6577f14fd1969c3e8f298c79788e3a419 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 12:00:35 +0100 Subject: [PATCH 28/44] docs - cli: add -a options for list and drop Signed-off-by: Dr Marco Claudio De La Pierre --- docs/cli.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/cli.md b/docs/cli.md index 119c23ea75..f566e59c62 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -535,6 +535,9 @@ The `drop` command is used to remove the projects which have been downloaded int **Options** +`-a, -all-revisions` +: For specified project, drop all revisions. + `-f` : Delete the repository without taking care of local changes. @@ -878,6 +881,9 @@ The `list` commands prints a list of the projects which are already downloaded i **Options** +`-a, -all-revisions` +: For each project, also list revisions. + `-h, -help` : Print the command usage. From e4b9d78b278775648b650ddf3a2d29d41204344b Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 12:08:08 +0100 Subject: [PATCH 29/44] docs - cli: add/update -r option for relevant commands Signed-off-by: Dr Marco Claudio De La Pierre --- docs/cli.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index f566e59c62..14a8f460b2 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -366,7 +366,7 @@ The `clone` command downloads a pipeline from a Git-hosting platform into the *c : Service hub where the project is hosted. Options: `gitlab` or `bitbucket`. `-r` (`master`) -: Revision to clone - It can be a git branch, tag, or revision number. +: Revision of the project to clone (either a git branch, tag or commit SHA number). `-user` : Private repository user name. @@ -415,6 +415,9 @@ The `config` command is used for printing the project's configuration i.e. the ` `-properties` : Print config using Java properties notation. +`-r, -revision` +: Revision of the project (either a git branch, tag or commit SHA number). + `-a, -show-profiles` : Show all configuration profiles. @@ -544,6 +547,9 @@ The `drop` command is used to remove the projects which have been downloaded int `-h, -help` : Print the command usage. +`-r, -revision` +: Revision of the project to drop (either a git branch, tag or commit SHA number). + **Examples** Drop the `nextflow-io/hello` project. @@ -1078,7 +1084,7 @@ The `pull` command downloads a pipeline from a Git-hosting platform into the glo : Service hub where the project is hosted. Options: `gitlab` or `bitbucket` `-r, -revision` -: Revision of the project to run (either a git branch, tag or commit hash). +: Revision of the project to pull (either a git branch, tag or commit SHA number). : When passing a git tag or branch, the `workflow.revision` and `workflow.commitId` fields are populated. When passing only the commit hash, `workflow.revision` is not defined. `-user` @@ -1221,7 +1227,7 @@ The `run` command is used to execute a local pipeline script or remote pipeline : Execute the script using the cached results, useful to continue executions that was stopped by an error. `-r, -revision` -: Revision of the project to run (either a git branch, tag or commit hash). +: Revision of the project to run (either a git branch, tag or commit SHA number). : When passing a git tag or branch, the `workflow.revision` and `workflow.commitId` fields are populated. When passing only the commit hash, `workflow.revision` is not defined. `-stub-run, -stub` @@ -1430,6 +1436,9 @@ The `view` command is used to inspect the pipelines that are already stored in t `-q` : Hide header line. +`-r, -revision` +: Revision of the project (either a git branch, tag or commit SHA number). + **Examples** Viewing the contents of a downloaded pipeline. From 958955a6fa78db3e3fa6b68f901053c944659292 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 13:50:36 +0100 Subject: [PATCH 30/44] CmdInfo: now also prints info on pulled revisions Signed-off-by: Dr Marco Claudio De La Pierre --- docs/cli.md | 3 ++ .../main/groovy/nextflow/cli/CmdDrop.groovy | 3 +- .../main/groovy/nextflow/cli/CmdInfo.groovy | 3 ++ .../groovy/nextflow/scm/AssetManager.groovy | 44 +++++++++++++------ 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index 14a8f460b2..ca7caf2a6e 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -691,6 +691,9 @@ If no run name or session id is provided, it will clean the latest run. `-o` (`text`) : Output format, either `text`, `json` or `yaml`. +`-r, -revision` +: Revision of the project (either a git branch, tag or commit SHA number). + **Examples** Display Nextflow runtime and system info: diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index 9a4ab616fb..f30811d0ab 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -59,7 +59,8 @@ class CmdDrop extends CmdBase { List dropList = [] if ( allrevisions ) { - AssetManager.listRevisions(args[0]).each { + def referenceManager = new AssetManager(args[0]) + referenceManager.listRevisions().each { dropList << new AssetManager(it.tokenize(revisionDelim)[0], it.tokenize(revisionDelim)[1]) } } else { diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index 89985c3af8..2b3dea1ebe 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -104,7 +104,9 @@ class CmdInfo extends CmdBase { protected printText(AssetManager manager, int level) { final manifest = manager.getManifest() + def printedRevision = manager.revision ?: manager.getDefaultBranch() out.println " project name: ${manager.project}" + out.println " revision : ${printedRevision}" out.println " repository : ${manager.repositoryUrl}" out.println " local path : ${manager.localPath}" out.println " main script : ${manager.mainScriptName}" @@ -142,6 +144,7 @@ class CmdInfo extends CmdBase { protected Map createMap(AssetManager manager) { def result = [:] result.projectName = manager.project + result.revision = manager.revision ?: manager.getDefaultBranch() result.repository = manager.repositoryUrl result.localPath = manager.localPath?.toString() result.manifest = manager.manifest.toMap() diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index f8c6b54855..26ee50124c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -314,6 +314,8 @@ class AssetManager { String getProject() { project } + String getRevision() { revision } + String getHub() { hub } @PackageScope @@ -557,8 +559,8 @@ class AssetManager { /** * @return The list of available revisions for a given project name */ - static List listRevisions( String project ) { - log.debug "Listing revisions for project: $project" + List listRevisions( String projectName = project ) { + log.debug "Listing revisions for project: $projectName" def result = new LinkedList() @@ -566,7 +568,7 @@ class AssetManager { return result list().each { - if( it.tokenize(revisionDelim)[0] == project ) { + if( it.tokenize(revisionDelim)[0] == projectName ) { result << it } } @@ -744,6 +746,18 @@ class AssetManager { names.get( head.objectId ) ?: head.objectId.name() } + /** + * @return The name of all currently pulled revisions for a given project, i.e. locally available + * + * If revision is null, default is assumed + */ + List getPulledRevisions() { + return listRevisions().collect{ + it -> String y = it.tokenize(revisionDelim)[1] + it = ( y != null ? y : getDefaultBranch() ) + } + } + RevisionInfo getCurrentRevisionAndName() { Ref head = git.getRepository().findRef(Constants.HEAD); if( !head ) @@ -771,30 +785,32 @@ class AssetManager { /** * @return A list of existing branches and tags names. For example *
-     *     * master (default)
-     *       patch-x
-     *       v1.0 (t)
-     *       v1.1 (t)
+     *     * P master (default)
+     *         patch-x
+     *         v1.0 (t)
+     *         v1.1 (t)
      * 
* - * The star character on the left highlight the current revision, the string {@code (default)} - * ticks that it is the default working branch (usually the master branch), while the string {@code (t)} - * shows that the revision is a git tag (instead of a branch) + * The star character on the left highlights the selected revision, + * the character {@code P} on the left indicates the revision is pulled locally, + * the string {@code (default)} ticks that it is the default working branch, + * while the string {@code (t)} shows that the revision is a git tag (instead of a branch) */ @Deprecated List getRevisions(int level) { def current = getCurrentRevision() def master = getDefaultBranch() + def pulled = getPulledRevisions() List branches = getBranchList() .findAll { it.name.startsWith('refs/heads/') || it.name.startsWith('refs/remotes/origin/') } .unique { shortenRefName(it.name) } - .collect { Ref it -> refToString(it,current,master,false,level) } + .collect { Ref it -> refToString(it,current,master,pulled,false,level) } List tags = getTagList() .findAll { it.name.startsWith('refs/tags/') } - .collect { refToString(it,current,master,true,level) } + .collect { refToString(it,current,master,pulled,true,level) } def result = new ArrayList(branches.size() + tags.size()) result.addAll(branches) @@ -834,6 +850,7 @@ class AssetManager { result.current = current // current branch name result.master = master // master branch name + result.pulled = getPulledRevisions() // list of pulled revisions result.branches = branches // collection of branches result.tags = tags // collect of tags return result @@ -868,11 +885,12 @@ class AssetManager { return human ? obj.name.substring(0,10) : obj.name } - protected String refToString(Ref ref, String current, String master, boolean tag, int level ) { + protected String refToString(Ref ref, String current, String master, List pulled, boolean tag, int level ) { def result = new StringBuilder() def name = shortenRefName(ref.name) result << (name == current ? '*' : ' ') + result << (name in pulled ? ' P' : ' ') if( level ) { def peel = git.getRepository().peel(ref) From f220e98cfb3a97e7d31e0cc856ac8c338c7d5cba Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 14:07:03 +0100 Subject: [PATCH 31/44] CmdInfo made smarter when non only non default revisions pulled Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/cli/CmdInfo.groovy | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index 2b3dea1ebe..a1476ecc20 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -80,9 +80,15 @@ class CmdInfo extends CmdBase { } Plugins.init() - final manager = new AssetManager(args[0], revision) - if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") + def manager = new AssetManager(args[0], revision) + if( !manager.isLocal() ) { + if ( manager.listRevisions() && !revision ) { + manager = new AssetManager(args[0], manager.getPulledRevisions()[0]) + } + else { + throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") + } + } if( !format || format == 'text' ) { printText(manager,level) From 2ad9a24e5ab0286d55c076263b3719269364287b Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 20:28:32 +0100 Subject: [PATCH 32/44] CmdInfoTest updated Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/test/groovy/nextflow/cli/CmdInfoTest.groovy | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy index e9217bf4c9..e885519525 100644 --- a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy @@ -67,11 +67,12 @@ class CmdInfoTest extends Specification { then: screen.contains(" project name: nextflow-io/hello") + screen.contains(" revision : master") screen.contains(" repository : https://github.com/nextflow-io/hello") screen.contains(" local path : $tempDir/nextflow-io/hello" ) screen.contains(" main script : main.nf") screen.contains(" revisions : ") - screen.contains(" * master (default)") + screen.contains(" * P master (default)") } def 'should print json info' () { @@ -87,12 +88,15 @@ class CmdInfoTest extends Specification { then: json.projectName == "nextflow-io/hello" + json.revision == "master" json.repository == "https://github.com/nextflow-io/hello" json.localPath == "$tempDir/nextflow-io/hello" json.manifest.mainScript == 'main.nf' json.manifest.defaultBranch == 'master' json.revisions.current == 'master' json.revisions.master == 'master' + json.revisions.pulled.size()>1 + json.revisions.pulled.any { it == 'master' } json.revisions.branches.size()>1 json.revisions.branches.any { it.name == 'master' } json.revisions.tags.size()>1 @@ -113,12 +117,15 @@ class CmdInfoTest extends Specification { then: json.projectName == "nextflow-io/hello" + json.revision == "master" json.repository == "https://github.com/nextflow-io/hello" json.localPath == "$tempDir/nextflow-io/hello" json.manifest.mainScript == 'main.nf' json.manifest.defaultBranch == 'master' json.revisions.current == 'master' json.revisions.master == 'master' + json.revisions.pulled.size()>1 + json.revisions.pulled.any { it == 'master' } json.revisions.branches.size()>1 json.revisions.branches.any { it.name == 'master' } json.revisions.tags.size()>1 From 35ea81249b3b8291cbb578d3fb139250c3d19094 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 20:32:21 +0100 Subject: [PATCH 33/44] CmdInfoTest fix Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy index e885519525..1a39f2a556 100644 --- a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy @@ -95,7 +95,7 @@ class CmdInfoTest extends Specification { json.manifest.defaultBranch == 'master' json.revisions.current == 'master' json.revisions.master == 'master' - json.revisions.pulled.size()>1 + json.revisions.pulled.size() == 1 json.revisions.pulled.any { it == 'master' } json.revisions.branches.size()>1 json.revisions.branches.any { it.name == 'master' } @@ -124,7 +124,7 @@ class CmdInfoTest extends Specification { json.manifest.defaultBranch == 'master' json.revisions.current == 'master' json.revisions.master == 'master' - json.revisions.pulled.size()>1 + json.revisions.pulled.size() == 1 json.revisions.pulled.any { it == 'master' } json.revisions.branches.size()>1 json.revisions.branches.any { it.name == 'master' } From 80ecacd181a81d0da46d9103dadab160eb52d98d Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 20:36:35 +0100 Subject: [PATCH 34/44] CmdInfo: added code comment Signed-off-by: Dr Marco Claudio De La Pierre --- modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index a1476ecc20..8680ce0164 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -82,6 +82,7 @@ class CmdInfo extends CmdBase { Plugins.init() def manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) { + // if no revision specified and default branch not found locally, use first one from list of local pulls if ( manager.listRevisions() && !revision ) { manager = new AssetManager(args[0], manager.getPulledRevisions()[0]) } From 5e4b45fdb9355d32f83e5633c8dae1849cc3981a Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 21:52:24 +0100 Subject: [PATCH 35/44] AssetManager: default revision recognised correctly if specified in manifest Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 26ee50124c..049de2b5d9 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -133,6 +133,13 @@ class AssetManager { @PackageScope AssetManager build( String pipelineName, String revision = null, Map config = null, HubOptions cliOpts = null ) { + if ( revision ) { + def referenceManager = new AssetManager(pipelineName, null, cliOpts) + if ( revision == referenceManager.getDefaultBranch() ) { + revision = null + } + } + this.providerConfigs = ProviderConfig.createFromMap(config) this.revision = revision From aa94d7b68ab099f41cf2ad717579d8c0cfb7991f Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 4 Mar 2024 22:03:20 +0100 Subject: [PATCH 36/44] small CLI Docs update Signed-off-by: Dr Marco Claudio De La Pierre --- docs/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli.md b/docs/cli.md index ca7caf2a6e..9a71652ae4 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -673,7 +673,7 @@ $ nextflow info [options] [project] **Description** -The `info` command prints out the nextflow runtime information about the hardware as well as the software versions of the Nextflow version and build, operating system, and Groovy and Java runtime. It can also be used to display information about a specific project. +The `info` command prints out the nextflow runtime information about the hardware as well as the software versions of the Nextflow version and build, operating system, and Groovy and Java runtime. It can also be used to display information about a specific project; in this case, note how revisions marked as `P` are pulled locally. If no run name or session id is provided, it will clean the latest run. From d965ee5dcd36ea6b7fc9712610e87d56c9bfe28f Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Wed, 6 Mar 2024 10:55:43 +0100 Subject: [PATCH 37/44] added a couple of comments Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 049de2b5d9..f9eb0465f6 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -133,6 +133,8 @@ class AssetManager { @PackageScope AssetManager build( String pipelineName, String revision = null, Map config = null, HubOptions cliOpts = null ) { + // if requested revision corresponds to the default branch, then unset it + // this avoids duplication of the default branch if ( revision ) { def referenceManager = new AssetManager(pipelineName, null, cliOpts) if ( revision == referenceManager.getDefaultBranch() ) { @@ -570,7 +572,6 @@ class AssetManager { log.debug "Listing revisions for project: $projectName" def result = new LinkedList() - if( !root.exists() ) return result @@ -754,7 +755,7 @@ class AssetManager { } /** - * @return The name of all currently pulled revisions for a given project, i.e. locally available + * @return The names of all locally pulled revisions for a given project * * If revision is null, default is assumed */ From 9aacb2bed52f63cb911036ff6ebcb005898eb910 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 03:12:44 +0000 Subject: [PATCH 38/44] Review: REVISION_DELIM and added comments Signed-off-by: Dr Marco Claudio De La Pierre --- .../main/groovy/nextflow/cli/CmdClone.groovy | 4 +-- .../main/groovy/nextflow/cli/CmdDrop.groovy | 8 +++--- .../main/groovy/nextflow/cli/CmdInfo.groovy | 4 +-- .../main/groovy/nextflow/cli/CmdList.groovy | 6 ++--- .../main/groovy/nextflow/cli/CmdPull.groovy | 4 +-- .../main/groovy/nextflow/cli/CmdRun.groovy | 8 +++--- .../main/groovy/nextflow/cli/CmdView.groovy | 4 +-- .../groovy/nextflow/scm/AssetManager.groovy | 25 +++++++++++++------ 8 files changed, 36 insertions(+), 27 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index 3901f76e40..6977a7ea88 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters @@ -55,7 +55,7 @@ class CmdClone extends CmdBase implements HubOptions { Plugins.init() // the pipeline name String pipeline = args[0] - String revisionSuffix = revision ? revisionDelim + revision : '' + String revisionSuffix = revision ? REVISION_DELIM + revision : '' final manager = new AssetManager(pipeline, revision, this) // the target directory is the second parameter diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index f30811d0ab..875de92200 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters @@ -61,7 +61,7 @@ class CmdDrop extends CmdBase { if ( allrevisions ) { def referenceManager = new AssetManager(args[0]) referenceManager.listRevisions().each { - dropList << new AssetManager(it.tokenize(revisionDelim)[0], it.tokenize(revisionDelim)[1]) + dropList << new AssetManager(it.tokenize(REVISION_DELIM)[0], it.tokenize(REVISION_DELIM)[1]) } } else { dropList << new AssetManager(args[0], revision) @@ -73,13 +73,13 @@ class CmdDrop extends CmdBase { dropList.each { manager -> if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${manager.project}${manager.revision ? revisionDelim + manager.revision : ''}") + throw new AbortOperationException("No match found for: ${manager.project}${manager.revision ? REVISION_DELIM + manager.revision : ''}") } if( this.force || manager.isClean() ) { manager.close() if( !manager.localPath.deleteDir() ) - throw new AbortOperationException("Unable to delete project `${manager.project}${manager.revision ? revisionDelim + manager.revision : ''}` -- Check access permissions for path: ${manager.localPath}") + throw new AbortOperationException("Unable to delete project `${manager.project}${manager.revision ? REVISION_DELIM + manager.revision : ''}` -- Check access permissions for path: ${manager.localPath}") return } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index 8680ce0164..8df05f5eb9 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import java.lang.management.ManagementFactory import java.nio.file.spi.FileSystemProvider @@ -87,7 +87,7 @@ class CmdInfo extends CmdBase { manager = new AssetManager(args[0], manager.getPulledRevisions()[0]) } else { - throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? REVISION_DELIM + revision : ''}`") } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy index 4f80670dd3..f6c851931a 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdList.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters @@ -52,11 +52,11 @@ class CmdList extends CmdBase { } if (revisions) { - all.collect{ it.tokenize(revisionDelim) } + all.collect{ it.tokenize(REVISION_DELIM) } .groupBy{ it[0] } .each{ println ' ' + it.value[0][0] ; it.value.each{ y -> println ( y.size()==1 ? ' (default)' : ' ' + y[1] ) } } } else { - all.collect{ it.replaceAll( /$revisionDelim.*/, '' ) } + all.collect{ it.replaceAll( /$REVISION_DELIM.*/, '' ) } .unique() .each{ println ' ' + it } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy index 988d4ea085..2e41e5f5f4 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdPull.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters @@ -76,7 +76,7 @@ class CmdPull extends CmdBase implements HubOptions { Plugins.init() list.each { - log.info "Checking $it${revision ? revisionDelim + revision : ''} ..." + log.info "Checking $it${revision ? REVISION_DELIM + revision : ''} ..." def manager = new AssetManager(it, revision, this) def result = manager.download(deep) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy index 2424f1d75e..03b5cfecae 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy @@ -18,7 +18,7 @@ package nextflow.cli import static org.fusesource.jansi.Ansi.* -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import java.nio.file.NoSuchFileException import java.nio.file.Path @@ -580,8 +580,8 @@ class CmdRun extends CmdBase implements HubOptions { boolean checkForUpdate = true if( !manager.isRunnable() || latest ) { if( offline ) - throw new AbortOperationException("Unknown project `$repo${revision ? revisionDelim + revision : ''}` -- NOTE: automatic download from remote repositories is disabled") - log.info "Pulling $repo${revision ? revisionDelim + revision : ''} ..." + throw new AbortOperationException("Unknown project `$repo${revision ? REVISION_DELIM + revision : ''}` -- NOTE: automatic download from remote repositories is disabled") + log.info "Pulling $repo${revision ? REVISION_DELIM + revision : ''} ..." def result = manager.download(deep) if( result ) log.info " $result" @@ -600,7 +600,7 @@ class CmdRun extends CmdBase implements HubOptions { throw e } catch( Exception e ) { - throw new AbortOperationException("Unknown error accessing project `$repo${revision ? revisionDelim + revision : ''}` -- Repository may be corrupted: ${manager.localPath}", e) + throw new AbortOperationException("Unknown error accessing project `$repo${revision ? REVISION_DELIM + revision : ''}` -- Repository may be corrupted: ${manager.localPath}", e) } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy index 42901f5f70..165be1f9b3 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdView.groovy @@ -16,7 +16,7 @@ package nextflow.cli -import static nextflow.scm.AssetManager.revisionDelim +import static nextflow.scm.AssetManager.REVISION_DELIM import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters @@ -58,7 +58,7 @@ class CmdView extends CmdBase { Plugins.init() def manager = new AssetManager(args[0], revision) if( !manager.isLocal() ) - throw new AbortOperationException("Unknown project `${args[0]}${revision ? revisionDelim + revision : ''}`") + throw new AbortOperationException("Unknown project `${args[0]}${revision ? REVISION_DELIM + revision : ''}`") if( all ) { if( !quiet ) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 4b8c387cf2..fa4c66054c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -62,7 +62,7 @@ class AssetManager { @PackageScope static File root = DEFAULT_ROOT - static public final String revisionDelim = ':' + static public final String REVISION_DELIM = ':' /** * The pipeline name. It must be in the form {@code username/repo} where 'username' @@ -206,7 +206,7 @@ class AssetManager { throw new IllegalArgumentException("Not a valid project name: $projectName") } - new File(root, project + (revision ? revisionDelim + revision : '')) + new File(root, project + (revision ? REVISION_DELIM + revision : '')) } /** @@ -572,7 +572,7 @@ class AssetManager { return result list().each { - if( it.tokenize(revisionDelim)[0] == projectName ) { + if( it.tokenize(REVISION_DELIM)[0] == projectName ) { result << it } } @@ -580,19 +580,28 @@ class AssetManager { return result } - // updated for new localPath schema (see localPath declaration at top of this class file) + // Updated for new localPath schema (see localPath declaration at top of this class file) static protected def find( String name, String revision = null ) { def exact = [] def partial = [] list().each { def items = it.split('/') - def itemsRev = items[1].tokenize(':') + /** + * itemsRev[0] is the name of each list'ed project + * itemsRev[1] is the revision + */ + def itemsRev = items[1].tokenize(REVISION_DELIM) + // Check on matching revision: either null or same revision string if( (!revision && !itemsRev[1]) || (revision && itemsRev[1] == revision) ) { + // Exact name match if( itemsRev[0] == name ) - exact << it.tokenize(':')[0] + // Return item without revision + exact << it.tokenize(REVISION_DELIM)[0] + // Partial name match else if( itemsRev[0].startsWith(name ) ) - partial << it.tokenize(':')[0] + // Return item without revision + partial << it.tokenize(REVISION_DELIM)[0] } } @@ -757,7 +766,7 @@ class AssetManager { */ List getPulledRevisions() { return listRevisions().collect{ - it -> String y = it.tokenize(revisionDelim)[1] + it -> String y = it.tokenize(REVISION_DELIM)[1] it = ( y != null ? y : getDefaultBranch() ) } } From 12718c79e0fe5763f8c90874b76f2baf2986ed23 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 03:45:15 +0000 Subject: [PATCH 39/44] review: added method getProjectWithRevision Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy | 7 ++----- .../nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy | 4 ++-- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 2 ++ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index 6977a7ea88..0c0e369317 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -16,8 +16,6 @@ package nextflow.cli -import static nextflow.scm.AssetManager.REVISION_DELIM - import com.beust.jcommander.Parameter import com.beust.jcommander.Parameters import groovy.transform.CompileStatic @@ -55,7 +53,6 @@ class CmdClone extends CmdBase implements HubOptions { Plugins.init() // the pipeline name String pipeline = args[0] - String revisionSuffix = revision ? REVISION_DELIM + revision : '' final manager = new AssetManager(pipeline, revision, this) // the target directory is the second parameter @@ -72,9 +69,9 @@ class CmdClone extends CmdBase implements HubOptions { } manager.checkValidRemoteRepo() - print "Cloning ${manager.project}${revisionSuffix} ..." + print "Cloning ${manager.getProjectWithRevision()} ..." manager.clone(target, deep) print "\r" - println "${manager.project}${revisionSuffix} cloned to: $target" + println "${manager.getProjectWithRevision()} cloned to: $target" } } diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy index 875de92200..fdad006d55 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdDrop.groovy @@ -73,13 +73,13 @@ class CmdDrop extends CmdBase { dropList.each { manager -> if( !manager.localPath.exists() ) { - throw new AbortOperationException("No match found for: ${manager.project}${manager.revision ? REVISION_DELIM + manager.revision : ''}") + throw new AbortOperationException("No match found for: ${manager.getProjectWithRevision()}") } if( this.force || manager.isClean() ) { manager.close() if( !manager.localPath.deleteDir() ) - throw new AbortOperationException("Unable to delete project `${manager.project}${manager.revision ? REVISION_DELIM + manager.revision : ''}` -- Check access permissions for path: ${manager.localPath}") + throw new AbortOperationException("Unable to delete project `${manager.getProjectWithRevision()}` -- Check access permissions for path: ${manager.localPath}") return } diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index fa4c66054c..9f5b8ed762 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -326,6 +326,8 @@ class AssetManager { String getRevision() { revision } + String getProjectWithRevision() { project + ( revision ? REVISION_DELIM + revision : '' ) } + String getHub() { hub } @PackageScope From 0b572626c9e4773da9f59ba1bc5a464bc3dd32f4 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 03:51:41 +0000 Subject: [PATCH 40/44] updated method getBaseNameWithRevision Signed-off-by: Dr Marco Claudio De La Pierre --- .../nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy | 2 +- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy index 0c0e369317..b7be19d0b6 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdClone.groovy @@ -57,7 +57,7 @@ class CmdClone extends CmdBase implements HubOptions { // the target directory is the second parameter // otherwise default the current pipeline name - def target = new File(args.size()> 1 ? args[1] : manager.getBaseName()) + def target = new File(args.size()> 1 ? args[1] : manager.getBaseNameWithRevision()) if( target.exists() ) { if( target.isFile() ) throw new AbortOperationException("A file with the same name already exists: $target") diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 9f5b8ed762..266e483c70 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -503,10 +503,11 @@ class AssetManager { } - String getBaseName() { + String getBaseNameWithRevision() { def result = project.tokenize('/') if( result.size() > 2 ) throw new IllegalArgumentException("Not a valid project name: $project") - return result.size()==1 ? result[0] : result[1] + result = ( result.size()==1 ? result[0] : result[1] ) + return result + ( revision ? REVISION_DELIM + revision : '' ) } boolean isLocal() { From 17067eadcc691bc24a7021eb4322985b54249580 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 06:38:20 +0000 Subject: [PATCH 41/44] docs/sharing: added paragraph on multiple revisions, with caveat on reproducibility Signed-off-by: Dr Marco De La Pierre Signed-off-by: Dr Marco Claudio De La Pierre --- docs/sharing.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/sharing.md b/docs/sharing.md index 2db5b9b527..d218597de1 100644 --- a/docs/sharing.md +++ b/docs/sharing.md @@ -58,6 +58,15 @@ nextflow run nextflow-io/hello -r v1.1 It will execute two different project revisions corresponding to the Git tag/branch having that names. +:::{versionadded} 24.03.0-edge +::: + +Nextflow downloads and locally maintains each explicitly requested Git branch, tag or commit ID in a separate directory path, thus enabling to run multiple revisions of the same pipeline at the same time. + +:::{warning} +If you really care about reproducibility of your pipelines, you should explicitly refer to them by tag or commit ID, rather than my branch. This is because the same branch will point to different underlying commits over time, as pipeline development goes on. This caveat is particularly relevant in a scenario where multiple people manage and share the same local collection of pipelines. +::: + ## Commands to manage projects The following commands allows you to perform some basic operations that can be used to manage your projects. From 67dc5d5a4b7f836e656ec3a198698f70e312f424 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 08:35:36 +0000 Subject: [PATCH 42/44] cmd info: removed sticky current revision, updated docs Signed-off-by: Dr Marco De La Pierre Signed-off-by: Dr Marco Claudio De La Pierre --- docs/cli.md | 3 --- docs/sharing.md | 8 ++++---- .../main/groovy/nextflow/cli/CmdInfo.groovy | 18 ++++++------------ .../groovy/nextflow/scm/AssetManager.groovy | 8 ++------ 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index c0c7ce5c1c..be95ff9f32 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -691,9 +691,6 @@ If no run name or session id is provided, it will clean the latest run. `-o` (`text`) : Output format, either `text`, `json` or `yaml`. -`-r, -revision` -: Revision of the project (either a git branch, tag or commit SHA number). - **Examples** Display Nextflow runtime and system info: diff --git a/docs/sharing.md b/docs/sharing.md index d218597de1..64dc771641 100644 --- a/docs/sharing.md +++ b/docs/sharing.md @@ -61,7 +61,7 @@ It will execute two different project revisions corresponding to the Git tag/bra :::{versionadded} 24.03.0-edge ::: -Nextflow downloads and locally maintains each explicitly requested Git branch, tag or commit ID in a separate directory path, thus enabling to run multiple revisions of the same pipeline at the same time. +Nextflow downloads and locally maintains each explicitly requested Git branch, tag or commit ID in a separate directory path, thus enabling to run multiple revisions of the same pipeline at the same time. Each downloaded revision is stored in a sister path to the default revision one, featuring an extra suffix string `:`. :::{warning} If you really care about reproducibility of your pipelines, you should explicitly refer to them by tag or commit ID, rather than my branch. This is because the same branch will point to different underlying commits over time, as pipeline development goes on. This caveat is particularly relevant in a scenario where multiple people manage and share the same local collection of pipelines. @@ -103,13 +103,13 @@ repository : http://github.com/nextflow-io/hello local path : $HOME/.nextflow/assets/nextflow-io/hello main script : main.nf revisions : -* master (default) +P master (default) mybranch - v1.1 [t] +P v1.1 [t] v1.2 [t] ``` -Starting from the top it shows: 1) the project name; 2) the Git repository URL; 3) the local folder where the project has been downloaded; 4) the script that is executed when launched; 5) the list of available revisions i.e. branches and tags. Tags are marked with a `[t]` on the right, the current checked-out revision is marked with a `*` on the left. +Starting from the top it shows: 1) the project name; 2) the Git repository URL; 3) the local path where the default project can be found (alternate revisions are in sister paths with an extra suffix `:`); 4) the script that is executed when launched; 5) the list of available revisions i.e. branches and tags. Tags are marked with a `[t]` on the right, the locally pulled revisions are marked with a `P` on the left. ### Pulling or updating a project diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy index 8df05f5eb9..428c914f9a 100644 --- a/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/cli/CmdInfo.groovy @@ -52,9 +52,6 @@ class CmdInfo extends CmdBase { @Parameter(description = 'project name') List args - @Parameter(names=['-r','-revision'], description = 'Revision of the project (either a git branch, tag or commit SHA number)') - String revision - @Parameter(names='-d',description = 'Show detailed information', arity = 0) boolean detailed @@ -80,14 +77,14 @@ class CmdInfo extends CmdBase { } Plugins.init() - def manager = new AssetManager(args[0], revision) + def manager = new AssetManager(args[0], null) if( !manager.isLocal() ) { - // if no revision specified and default branch not found locally, use first one from list of local pulls - if ( manager.listRevisions() && !revision ) { + // if default branch not found locally, use first one from list of local pulls + if ( manager.listRevisions() ) { manager = new AssetManager(args[0], manager.getPulledRevisions()[0]) } else { - throw new AbortOperationException("Unknown project `${args[0]}${revision ? REVISION_DELIM + revision : ''}`") + throw new AbortOperationException("Unknown project `${args[0]}`") } } @@ -111,11 +108,9 @@ class CmdInfo extends CmdBase { protected printText(AssetManager manager, int level) { final manifest = manager.getManifest() - def printedRevision = manager.revision ?: manager.getDefaultBranch() out.println " project name: ${manager.project}" - out.println " revision : ${printedRevision}" out.println " repository : ${manager.repositoryUrl}" - out.println " local path : ${manager.localPath}" + out.println " local path : ${manager.localPath.toString().tokenize(REVISION_DELIM)[0]}" out.println " main script : ${manager.mainScriptName}" if( manager.homePage && manager.homePage != manager.repositoryUrl ) out.println " home page : ${manager.homePage}" @@ -151,9 +146,8 @@ class CmdInfo extends CmdBase { protected Map createMap(AssetManager manager) { def result = [:] result.projectName = manager.project - result.revision = manager.revision ?: manager.getDefaultBranch() result.repository = manager.repositoryUrl - result.localPath = manager.localPath?.toString() + result.localPath = manager.localPath?.toString().tokenize(REVISION_DELIM)[0] result.manifest = manager.manifest.toMap() result.revisions = manager.getBranchesAndTags(checkForUpdates) return result diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 266e483c70..b586351db3 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -807,8 +807,7 @@ class AssetManager { * v1.1 (t) * * - * The star character on the left highlights the selected revision, - * the character {@code P} on the left indicates the revision is pulled locally, + * The character {@code P} on the left indicates the revision is pulled locally, * the string {@code (default)} ticks that it is the default working branch, * while the string {@code (t)} shows that the revision is a git tag (instead of a branch) */ @@ -847,7 +846,6 @@ class AssetManager { Map getBranchesAndTags(boolean checkForUpdates) { final result = [:] - final current = getCurrentRevision() final master = getDefaultBranch() final branches = [] @@ -864,7 +862,6 @@ class AssetManager { .findAll { it.name.startsWith('refs/tags/') } .each { Ref it -> tags << refToMap(it,remote) } - result.current = current // current branch name result.master = master // master branch name result.pulled = getPulledRevisions() // list of pulled revisions result.branches = branches // collection of branches @@ -905,8 +902,7 @@ class AssetManager { def result = new StringBuilder() def name = shortenRefName(ref.name) - result << (name == current ? '*' : ' ') - result << (name in pulled ? ' P' : ' ') + result << (name in pulled ? 'P' : ' ') if( level ) { def peel = git.getRepository().peel(ref) From 7716416cfa2671713c8df497ac21791852636954 Mon Sep 17 00:00:00 2001 From: Dr Marco De La Pierre Date: Thu, 21 Mar 2024 10:42:03 +0000 Subject: [PATCH 43/44] fixed unit tests in CmdInfoTest Signed-off-by: Dr Marco De La Pierre Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/test/groovy/nextflow/cli/CmdInfoTest.groovy | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy index 1a39f2a556..59a12a847f 100644 --- a/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/cli/CmdInfoTest.groovy @@ -67,12 +67,11 @@ class CmdInfoTest extends Specification { then: screen.contains(" project name: nextflow-io/hello") - screen.contains(" revision : master") screen.contains(" repository : https://github.com/nextflow-io/hello") screen.contains(" local path : $tempDir/nextflow-io/hello" ) screen.contains(" main script : main.nf") screen.contains(" revisions : ") - screen.contains(" * P master (default)") + screen.contains(" P master (default)") } def 'should print json info' () { @@ -88,12 +87,10 @@ class CmdInfoTest extends Specification { then: json.projectName == "nextflow-io/hello" - json.revision == "master" json.repository == "https://github.com/nextflow-io/hello" json.localPath == "$tempDir/nextflow-io/hello" json.manifest.mainScript == 'main.nf' json.manifest.defaultBranch == 'master' - json.revisions.current == 'master' json.revisions.master == 'master' json.revisions.pulled.size() == 1 json.revisions.pulled.any { it == 'master' } @@ -117,12 +114,10 @@ class CmdInfoTest extends Specification { then: json.projectName == "nextflow-io/hello" - json.revision == "master" json.repository == "https://github.com/nextflow-io/hello" json.localPath == "$tempDir/nextflow-io/hello" json.manifest.mainScript == 'main.nf' json.manifest.defaultBranch == 'master' - json.revisions.current == 'master' json.revisions.master == 'master' json.revisions.pulled.size() == 1 json.revisions.pulled.any { it == 'master' } From 77b55f3dbe00092844067bc79fa301886cbd71f4 Mon Sep 17 00:00:00 2001 From: Dr Marco Claudio De La Pierre Date: Mon, 24 Jun 2024 10:39:34 +0200 Subject: [PATCH 44/44] AssetManager: revert back to set revision in checkValidRemoteRepo() Signed-off-by: Dr Marco Claudio De La Pierre --- .../src/main/groovy/nextflow/scm/AssetManager.groovy | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy index 440ca64d2f..85d7bb1b34 100644 --- a/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/scm/AssetManager.groovy @@ -149,7 +149,6 @@ class AssetManager { this.localPath = checkProjectDir(project, this.revision) this.hub = checkHubProvider(cliOpts) this.provider = createHubProvider(hub) - this.provider.setRevision(this.revision) setupCredentials(cliOpts) validateProjectDir() @@ -392,7 +391,10 @@ class AssetManager { } AssetManager checkValidRemoteRepo() { - // Check that the remote git provider contains the main script file (main.nf by default) + // Configure the git provider to use the required revision as source for all needed remote resources: + // - config if present in repo (nextflow.config by default) + // - main script (main.nf by default) + provider.revision = revision final scriptName = getMainScriptName() provider.validateFor(scriptName) return this