mirror of
https://github.com/openSUSE/osc.git
synced 2024-12-25 17:36:13 +01:00
Merge pull request #1193 from dmach/commandline-project-package
commandline: Migrate project, package argument parsing to pop_project_package_from_args()
This commit is contained in:
commit
85d86249d4
32
behave/features/addchannels-pkgcheckout.feature
Normal file
32
behave/features/addchannels-pkgcheckout.feature
Normal file
@ -0,0 +1,32 @@
|
||||
Feature: `osc addchannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels`
|
||||
When I execute osc with args "addchannels"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels --enable-all`
|
||||
When I execute osc with args "addchannels --enable-all"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA' options: enable-all
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels --skip-disabled`
|
||||
When I execute osc with args "addchannels --skip-disabled"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA' options: skip-disabled
|
||||
"""
|
32
behave/features/addchannels-prjcheckout.feature
Normal file
32
behave/features/addchannels-prjcheckout.feature
Normal file
@ -0,0 +1,32 @@
|
||||
Feature: `osc addchannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels`
|
||||
When I execute osc with args "addchannels"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels --enable-all`
|
||||
When I execute osc with args "addchannels --enable-all"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory' options: enable-all
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels --skip-disabled`
|
||||
When I execute osc with args "addchannels --skip-disabled"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory' options: skip-disabled
|
||||
"""
|
38
behave/features/addchannels-project-package.feature
Normal file
38
behave/features/addchannels-project-package.feature
Normal file
@ -0,0 +1,38 @@
|
||||
Feature: `osc addchannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project> <package>`
|
||||
When I execute osc with args "addchannels test:factory test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project>/<package>`
|
||||
When I execute osc with args "addchannels test:factory/test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project> <package> --enable-all`
|
||||
When I execute osc with args "addchannels test:factory test-pkgA --enable-all"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA' options: enable-all
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project> <package> --skip-disabled`
|
||||
When I execute osc with args "addchannels test:factory test-pkgA --skip-disabled"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to package 'test:factory/test-pkgA' options: skip-disabled
|
||||
"""
|
31
behave/features/addchannels-project.feature
Normal file
31
behave/features/addchannels-project.feature
Normal file
@ -0,0 +1,31 @@
|
||||
Feature: `osc addchannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project>`
|
||||
When I execute osc with args "addchannels test:factory"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project> --enable-all`
|
||||
When I execute osc with args "addchannels test:factory --enable-all"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory' options: enable-all
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addchannels <project> --skip-disabled`
|
||||
When I execute osc with args "addchannels test:factory --skip-disabled"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding channels to project 'test:factory' options: skip-disabled
|
||||
"""
|
||||
|
24
behave/features/addcontainers-pkgcheckout.feature
Normal file
24
behave/features/addcontainers-pkgcheckout.feature
Normal file
@ -0,0 +1,24 @@
|
||||
Feature: `osc addcontainers` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers`
|
||||
When I execute osc with args "addcontainers"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding containers to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers --extend-package-names`
|
||||
When I execute osc with args "addcontainers --extend-package-names"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding containers to package 'test:factory/test-pkgA' options: extend-package-names
|
||||
"""
|
17
behave/features/addcontainers-prjcheckout.feature
Normal file
17
behave/features/addcontainers-prjcheckout.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: `osc addcontainers` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers`
|
||||
When I execute osc with args "addcontainers"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Directory '{context.osc.temp}/test:factory' is not a working copy of a package
|
||||
"""
|
30
behave/features/addcontainers-project-package.feature
Normal file
30
behave/features/addcontainers-project-package.feature
Normal file
@ -0,0 +1,30 @@
|
||||
Feature: `osc addcontainers` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers <project> <package>`
|
||||
When I execute osc with args "addcontainers test:factory test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding containers to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers <project>/<package>`
|
||||
When I execute osc with args "addcontainers test:factory/test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding containers to package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc addcontainers <project> <package> --extend-package-names`
|
||||
When I execute osc with args "addcontainers test:factory test-pkgA --extend-package-names"
|
||||
Then stdout is
|
||||
"""
|
||||
Adding containers to package 'test:factory/test-pkgA' options: extend-package-names
|
||||
"""
|
16
behave/features/develproject-pkgcheckout.feature
Normal file
16
behave/features/develproject-pkgcheckout.feature
Normal file
@ -0,0 +1,16 @@
|
||||
Feature: `osc develproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject"
|
||||
Then stdout is
|
||||
"""
|
||||
test:devel/test-pkgA
|
||||
"""
|
17
behave/features/develproject-prjcheckout.feature
Normal file
17
behave/features/develproject-prjcheckout.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: `osc develproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Directory '{context.osc.temp}/test:factory' is not a working copy of a package
|
||||
"""
|
32
behave/features/develproject-project-package.feature
Normal file
32
behave/features/develproject-project-package.feature
Normal file
@ -0,0 +1,32 @@
|
||||
Feature: `osc develproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject test:factory test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
test:devel/test-pkgA
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject test:factory test-pkgB"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Package test:factory/test-pkgB has no devel project
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject test:factory/test-pkgB"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Package test:factory/test-pkgB has no devel project
|
||||
"""
|
15
behave/features/develproject-project.feature
Normal file
15
behave/features/develproject-project.feature
Normal file
@ -0,0 +1,15 @@
|
||||
Feature: `osc develproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc develproject`
|
||||
When I execute osc with args "develproject test:factory"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
*** Error: Please specify a package
|
||||
"""
|
16
behave/features/enablechannels-pkgcheckout.feature
Normal file
16
behave/features/enablechannels-pkgcheckout.feature
Normal file
@ -0,0 +1,16 @@
|
||||
Feature: `osc enablechannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
|
||||
|
||||
Scenario: Run `osc enablechannels`
|
||||
When I execute osc with args "enablechannels"
|
||||
Then stdout is
|
||||
"""
|
||||
Enabling channels in package 'test:factory/test-pkgA'
|
||||
"""
|
16
behave/features/enablechannels-prjcheckout.feature
Normal file
16
behave/features/enablechannels-prjcheckout.feature
Normal file
@ -0,0 +1,16 @@
|
||||
Feature: `osc enablechannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc enablechannels`
|
||||
When I execute osc with args "enablechannels"
|
||||
Then stdout is
|
||||
"""
|
||||
Enabling channels in project 'test:factory'
|
||||
"""
|
22
behave/features/enablechannels-project-package.feature
Normal file
22
behave/features/enablechannels-project-package.feature
Normal file
@ -0,0 +1,22 @@
|
||||
Feature: `osc enablechannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc enablechannels <project> <package>`
|
||||
When I execute osc with args "enablechannels test:factory test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Enabling channels in package 'test:factory/test-pkgA'
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc enablechannels <project>/<package>`
|
||||
When I execute osc with args "enablechannels test:factory/test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Enabling channels in package 'test:factory/test-pkgA'
|
||||
"""
|
14
behave/features/enablechannels-project.feature
Normal file
14
behave/features/enablechannels-project.feature
Normal file
@ -0,0 +1,14 @@
|
||||
Feature: `osc enablechannels` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
Scenario: Run `osc enablechannels <project>`
|
||||
When I execute osc with args "enablechannels test:factory"
|
||||
Then stdout is
|
||||
"""
|
||||
Enabling channels in project 'test:factory'
|
||||
"""
|
@ -20,8 +20,9 @@ def before_scenario(context, scenario):
|
||||
def after_scenario(context, scenario):
|
||||
if "destructive" in scenario.tags:
|
||||
# start a new container after a destructive test
|
||||
context.podman.kill()
|
||||
context.podman = podman.Podman()
|
||||
# we must use an existing podman instance defined in `before_all` due to context attribute life-cycle:
|
||||
# https://behave.readthedocs.io/en/stable/context_attributes.html
|
||||
context.podman.restart()
|
||||
context.osc.clear()
|
||||
common.check_exit_code(context)
|
||||
|
||||
@ -46,7 +47,7 @@ def before_all(context):
|
||||
# absolute path to .../behave/fixtures
|
||||
context.fixtures = os.path.join(os.path.dirname(__file__), "..", "fixtures")
|
||||
|
||||
context.podman = podman.Podman()
|
||||
context.podman = podman.Podman(context)
|
||||
context.osc = osc.Osc(context)
|
||||
|
||||
|
||||
|
57
behave/features/setdevelproject-pkgcheckout.feature
Normal file
57
behave/features/setdevelproject-pkgcheckout.feature
Normal file
@ -0,0 +1,57 @@
|
||||
Feature: `osc setdevelproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <devel_project>`
|
||||
When I execute osc with args "setdevelproject test:devel"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgA' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <devel_project> <devel_package>`
|
||||
When I execute osc with args "setdevelproject test:devel test-pkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgA' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <devel_project>/<devel_package>`
|
||||
When I execute osc with args "setdevelproject test:devel/test-pkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgA' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject --unset`
|
||||
Given I execute osc with args "setdevelproject test:devel"
|
||||
When I execute osc with args "setdevelproject --unset"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Unsetting devel project from package 'test:factory/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
17
behave/features/setdevelproject-prjcheckout.feature
Normal file
17
behave/features/setdevelproject-prjcheckout.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: `osc setdevelproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc setdevelproject <devel_project>`
|
||||
When I execute osc with args "setdevelproject devel"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Directory '{context.osc.temp}/test:factory' is not a working copy of a package
|
||||
"""
|
54
behave/features/setdevelproject-project-package.feature
Normal file
54
behave/features/setdevelproject-project-package.feature
Normal file
@ -0,0 +1,54 @@
|
||||
Feature: `osc setdevelproject` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <project> <package> <devel_project>`
|
||||
When I execute osc with args "setdevelproject test:factory test-pkgA test:devel"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgA' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <project> <package> <devel_project> <devel_package>`
|
||||
When I execute osc with args "setdevelproject test:factory test-pkgB test:devel test-pkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgB' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <project>/<package> <devel_project>/<devel_package>`
|
||||
When I execute osc with args "setdevelproject test:factory/test-pkgB test:devel/test-pkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Setting devel project of package 'test:factory/test-pkgB' to package 'test:devel/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Run `osc setdevelproject <project> <package> --unset`
|
||||
When I execute osc with args "setdevelproject test:factory test-pkgA --unset"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
Unsetting devel project from package 'test:factory/test-pkgA'
|
||||
Sending meta data...
|
||||
Done.
|
||||
"""
|
39
behave/features/setlinkrev-project-package.feature
Normal file
39
behave/features/setlinkrev-project-package.feature
Normal file
@ -0,0 +1,39 @@
|
||||
Feature: `osc setlinkrev` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "linkpac test:factory/test-pkgA home:Admin --force"
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project> <package>`
|
||||
When I execute osc with args "setlinkrev home:Admin test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Set link revision of package home:Admin/test-pkgA to 3
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project>/<package>`
|
||||
When I execute osc with args "setlinkrev home:Admin/test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
Set link revision of package home:Admin/test-pkgA to 3
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project> <package> --revision`
|
||||
When I execute osc with args "setlinkrev home:Admin test-pkgA --revision=2"
|
||||
Then stdout is
|
||||
"""
|
||||
Set link revision of package home:Admin/test-pkgA to 2
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project> <package> --unset`
|
||||
When I execute osc with args "setlinkrev home:Admin test-pkgA --unset"
|
||||
Then stdout is
|
||||
"""
|
||||
Removed link revision from package home:Admin/test-pkgA
|
||||
"""
|
33
behave/features/setlinkrev-project.feature
Normal file
33
behave/features/setlinkrev-project.feature
Normal file
@ -0,0 +1,33 @@
|
||||
Feature: `osc setlinkrev` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "linkpac test:factory/test-pkgA home:Admin --force"
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project>`
|
||||
When I execute osc with args "setlinkrev home:Admin"
|
||||
Then stdout is
|
||||
"""
|
||||
Set link revision of package home:Admin/test-pkgA to 3
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project> --revision`
|
||||
When I execute osc with args "setlinkrev home:Admin --revision=2"
|
||||
Then the exit code is 2
|
||||
|
||||
|
||||
Scenario: Run `osc setlinkrev <project> --unset`
|
||||
Given I execute osc with args "setlinkrev home:Admin test-pkgA --revision=2"
|
||||
And stdout is
|
||||
"""
|
||||
Set link revision of package home:Admin/test-pkgA to 2
|
||||
"""
|
||||
When I execute osc with args "setlinkrev home:Admin --unset"
|
||||
Then stdout is
|
||||
"""
|
||||
Removed link revision from package home:Admin/test-pkgA
|
||||
"""
|
17
behave/features/showlinked-pkgcheckout.feature
Normal file
17
behave/features/showlinked-pkgcheckout.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: `osc showlinked` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory/test-pkgA"
|
||||
And I set working directory to "{context.osc.temp}/test:factory/test-pkgA"
|
||||
And I execute osc with args "linkpac test:factory/test-pkgA home:Admin --force"
|
||||
|
||||
|
||||
Scenario: Run `osc showlinked`
|
||||
When I execute osc with args "showlinked"
|
||||
Then stdout is
|
||||
"""
|
||||
home:Admin/test-pkgA
|
||||
"""
|
17
behave/features/showlinked-prjcheckout.feature
Normal file
17
behave/features/showlinked-prjcheckout.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: `osc showlinked` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "checkout test:factory"
|
||||
And I set working directory to "{context.osc.temp}/test:factory"
|
||||
|
||||
|
||||
Scenario: Run `osc showlinked`
|
||||
When I execute osc with args "showlinked"
|
||||
Then the exit code is 1
|
||||
And stderr is
|
||||
"""
|
||||
Directory '{context.osc.temp}/test:factory' is not a working copy of a package
|
||||
"""
|
23
behave/features/showlinked-project-package.feature
Normal file
23
behave/features/showlinked-project-package.feature
Normal file
@ -0,0 +1,23 @@
|
||||
Feature: `osc showlinked` command
|
||||
|
||||
|
||||
# common steps for all scenarios
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute osc with args "linkpac test:factory/test-pkgA home:Admin --force"
|
||||
|
||||
|
||||
Scenario: Run `osc showlinked <project> <package>`
|
||||
When I execute osc with args "showlinked test:factory test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
home:Admin/test-pkgA
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Run `osc showlinked <project>/<package>`
|
||||
When I execute osc with args "showlinked test:factory/test-pkgA"
|
||||
Then stdout is
|
||||
"""
|
||||
home:Admin/test-pkgA
|
||||
"""
|
@ -6,6 +6,13 @@ import subprocess
|
||||
import behave
|
||||
|
||||
|
||||
def debug(context, *args):
|
||||
if not context.config.userdata.get("DEBUG", False):
|
||||
return
|
||||
msg = " ".join((str(i).strip() for i in args))
|
||||
print(f"DEBUG: {msg}")
|
||||
|
||||
|
||||
def makedirs(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
@ -62,16 +69,14 @@ def run_in_context(context, cmd, can_fail=False, **run_args):
|
||||
env["PATH"] = path.replace("$PATH", env["PATH"])
|
||||
run_args["env"] = env
|
||||
|
||||
if context.config.userdata.get("DEBUG", False):
|
||||
print(f"DEBUG: command: {cmd}")
|
||||
debug(context, "Running command:", cmd)
|
||||
|
||||
context.cmd_exitcode, context.cmd_stdout, context.cmd_stderr = run(cmd, **run_args)
|
||||
context.cmd_exitcode_checked = False
|
||||
|
||||
if context.config.userdata.get("DEBUG", False):
|
||||
print(f"DEBUG: exit code: {context.cmd_exitcode}")
|
||||
print(f"DEBUG: stdout: {context.cmd_stdout}")
|
||||
print(f"DEBUG: stderr: {context.cmd_stderr}")
|
||||
debug(context, "> return code:", context.cmd_exitcode)
|
||||
debug(context, "> stdout:", context.cmd_stdout)
|
||||
debug(context, "> stderr:", context.cmd_stderr)
|
||||
|
||||
if not can_fail and context.cmd_exitcode != 0:
|
||||
raise AssertionError('Running command "%s" failed: %s' % (cmd, context.cmd_exitcode))
|
||||
@ -93,8 +98,8 @@ def step_impl(context, text):
|
||||
|
||||
@behave.step("stdout is")
|
||||
def step_impl(context):
|
||||
expected = context.text.format(context=context).rstrip().split('\n')
|
||||
found = context.cmd_stdout.rstrip().split('\n')
|
||||
expected = context.text.format(context=context).rstrip().split("\n")
|
||||
found = context.cmd_stdout.rstrip().split("\n")
|
||||
|
||||
if found == expected:
|
||||
return
|
||||
@ -104,6 +109,19 @@ def step_impl(context):
|
||||
raise AssertionError(f"Stdout is not:\n{expected_str}\n\nActual stdout:\n{found_str}")
|
||||
|
||||
|
||||
@behave.step("stderr is")
|
||||
def step_impl(context):
|
||||
expected = context.text.format(context=context).rstrip().split("\n")
|
||||
found = context.cmd_stderr.rstrip().split("\n")
|
||||
|
||||
if found == expected:
|
||||
return
|
||||
|
||||
expected_str = "\n".join(expected)
|
||||
found_str = "\n".join(found)
|
||||
raise AssertionError(f"Stderr is not:\n{expected_str}\n\nActual stderr:\n{found_str}")
|
||||
|
||||
|
||||
@behave.step('I set working directory to "{path}"')
|
||||
def step_impl(context, path):
|
||||
path = path.format(context=context)
|
||||
@ -183,7 +201,15 @@ def step_impl(context, path, mode):
|
||||
@behave.step("the exit code is {exitcode}")
|
||||
def the_exit_code_is(context, exitcode):
|
||||
if context.cmd_exitcode != int(exitcode):
|
||||
raise AssertionError(f"Command has exited with code {context.cmd_exitcode}: {context.cmd}")
|
||||
lines = [
|
||||
f"Command has exited with code {context.cmd_exitcode}: {context.cmd}",
|
||||
"> stdout:",
|
||||
context.cmd_stdout.strip(),
|
||||
"",
|
||||
"> stderr:",
|
||||
context.cmd_stderr.strip(),
|
||||
]
|
||||
raise AssertionError("\n".join(lines))
|
||||
context.cmd_exitcode_checked = True
|
||||
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import behave
|
||||
|
||||
from steps.common import debug
|
||||
from steps.common import run_in_context
|
||||
|
||||
|
||||
@ -14,6 +16,7 @@ class Osc:
|
||||
raise RuntimeError("context doesn't have 'podman' object set")
|
||||
|
||||
self.context = context
|
||||
debug(self.context, "Osc.__init__()")
|
||||
self.temp = None
|
||||
self.clear()
|
||||
|
||||
@ -24,6 +27,7 @@ class Osc:
|
||||
pass
|
||||
|
||||
def clear(self):
|
||||
debug(self.context, "Osc.clear()")
|
||||
if self.temp:
|
||||
shutil.rmtree(self.temp)
|
||||
self.temp = tempfile.mkdtemp(prefix="osc_behave_")
|
||||
@ -54,6 +58,8 @@ def step_impl(context, args):
|
||||
cmd = context.osc.get_cmd() + [args]
|
||||
cmd = " ".join(cmd)
|
||||
run_in_context(context, cmd, can_fail=True)
|
||||
# remove InsecureRequestWarning that is irrelevant to the tests
|
||||
context.cmd_stderr = re.sub(r"^.*InsecureRequestWarning.*\n warnings.warn\(\n", "", context.cmd_stderr)
|
||||
|
||||
|
||||
@behave.step('I wait for osc results for "{project}" "{package}"')
|
||||
|
@ -1,12 +1,14 @@
|
||||
import subprocess
|
||||
|
||||
from steps.common import debug
|
||||
|
||||
|
||||
class Podman:
|
||||
def __init__(self):
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
debug(context, "Podman.__init__()")
|
||||
self.container_id = None
|
||||
self.run()
|
||||
self.wait_on_systemd()
|
||||
self.port = self.get_port()
|
||||
self.start()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
@ -16,6 +18,7 @@ class Podman:
|
||||
|
||||
def _run(self, args, check=True):
|
||||
cmd = ["podman"] + args
|
||||
debug(self.context, "Running command:", cmd)
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
@ -23,9 +26,13 @@ class Podman:
|
||||
encoding="utf-8",
|
||||
check=check,
|
||||
)
|
||||
debug(self.context, "> return code:", proc.returncode)
|
||||
debug(self.context, "> stdout:", proc.stdout)
|
||||
debug(self.context, "> stderr:", proc.stderr)
|
||||
return proc
|
||||
|
||||
def run(self):
|
||||
def start(self):
|
||||
debug(self.context, "Podman.start()")
|
||||
args = [
|
||||
"run",
|
||||
"--name", "obs-server-behave",
|
||||
@ -41,14 +48,22 @@ class Podman:
|
||||
proc = self._run(args)
|
||||
lines = proc.stdout.strip().splitlines()
|
||||
self.container_id = lines[-1]
|
||||
self.wait_on_systemd()
|
||||
self.port = self.get_port()
|
||||
|
||||
def kill(self):
|
||||
if not self.container_id:
|
||||
return
|
||||
debug(self.context, "Podman.kill()")
|
||||
args = ["kill", self.container_id]
|
||||
self._run(args)
|
||||
self.container_id = None
|
||||
|
||||
def restart(self):
|
||||
debug(self.context, "Podman.restart()")
|
||||
self.kill()
|
||||
self.start()
|
||||
|
||||
def wait_on_systemd(self):
|
||||
args = [
|
||||
"exec",
|
||||
@ -65,4 +80,4 @@ class Podman:
|
||||
if line.startswith("443/tcp"):
|
||||
# return <port> from: "443/tcp -> 0.0.0.0:<port>"
|
||||
return line.split(":")[-1]
|
||||
return None
|
||||
raise RuntimeError(f"Could not determine port of container {self.container_id}")
|
||||
|
@ -3,5 +3,12 @@
|
||||
#
|
||||
# The cherry-picked imports will be the supported API.
|
||||
|
||||
from .api_source import add_channels
|
||||
from .api_source import add_containers
|
||||
from .api_source import enable_channels
|
||||
from .api_source import get_linked_packages
|
||||
from .api_source import release
|
||||
from .common import print_msg
|
||||
from .common import format_msg_project_package_options
|
||||
from .package import ApiPackage
|
||||
from .request import forward_request
|
||||
|
@ -33,6 +33,31 @@ def get(apiurl, path, query=None):
|
||||
return root
|
||||
|
||||
|
||||
def post(apiurl, path, query=None):
|
||||
"""
|
||||
Send a POST request to OBS.
|
||||
|
||||
:param apiurl: OBS apiurl.
|
||||
:type apiurl: str
|
||||
:param path: URL path segments.
|
||||
:type path: list(str)
|
||||
:param query: URL query values.
|
||||
:type query: dict(str, str)
|
||||
:returns: Parsed XML root.
|
||||
:rtype: xml.etree.ElementTree.Element
|
||||
"""
|
||||
assert apiurl
|
||||
assert path
|
||||
|
||||
if not isinstance(path, (list, tuple)):
|
||||
raise TypeError("Argument `path` expects a list of strings")
|
||||
|
||||
url = osc_core.makeurl(apiurl, path, query)
|
||||
with osc_connection.http_POST(url) as f:
|
||||
root = osc_core.ET.parse(f).getroot()
|
||||
return root
|
||||
|
||||
|
||||
def find_nodes(root, root_name, node_name):
|
||||
"""
|
||||
Find nodes with given `node_name`.
|
||||
|
126
osc/_private/api_source.py
Normal file
126
osc/_private/api_source.py
Normal file
@ -0,0 +1,126 @@
|
||||
from . import api
|
||||
from .common import format_msg_project_package_options
|
||||
from .common import print_msg
|
||||
from .. import oscerr
|
||||
|
||||
|
||||
def add_channels(apiurl, project, package=None, enable_all=False, skip_disabled=False, print_to="debug"):
|
||||
if all((enable_all, skip_disabled)):
|
||||
raise oscerr.OscValueError("Options 'enable_all' and 'skip_disabled' are mutually exclusive")
|
||||
|
||||
msg = format_msg_project_package_options(
|
||||
"Adding channels to",
|
||||
project,
|
||||
package,
|
||||
enable_all=enable_all,
|
||||
skip_disabled=skip_disabled,
|
||||
)
|
||||
print_msg(msg, print_to=print_to)
|
||||
|
||||
url_path = ["source", project]
|
||||
if package:
|
||||
url_path += [package]
|
||||
|
||||
url_query = {"cmd": "addchannels"}
|
||||
if enable_all:
|
||||
url_query["mode"] = "enable_all"
|
||||
if skip_disabled:
|
||||
url_query["mode"] = "skip_disabled"
|
||||
|
||||
return api.post(apiurl, url_path, url_query)
|
||||
|
||||
|
||||
def add_containers(apiurl, project, package, extend_package_names=False, print_to="debug"):
|
||||
msg = format_msg_project_package_options(
|
||||
"Adding containers to",
|
||||
project,
|
||||
package,
|
||||
extend_package_names=extend_package_names,
|
||||
)
|
||||
print_msg(msg, print_to=print_to)
|
||||
|
||||
url_path = ["source", project, package]
|
||||
|
||||
url_query = {"cmd": "addcontainers"}
|
||||
if extend_package_names:
|
||||
url_query["extend_package_names"] = "1"
|
||||
|
||||
return api.post(apiurl, url_path, url_query)
|
||||
|
||||
|
||||
def enable_channels(apiurl, project, package=None, print_to="debug"):
|
||||
msg = format_msg_project_package_options(
|
||||
"Enabling channels in",
|
||||
project,
|
||||
package,
|
||||
)
|
||||
print_msg(msg, print_to=print_to)
|
||||
|
||||
url_path = ["source", project]
|
||||
if package:
|
||||
url_path += [package]
|
||||
|
||||
if package:
|
||||
url_query = {"cmd": "enablechannel"}
|
||||
else:
|
||||
url_query = {"cmd": "modifychannels", "mode": "enable_all"}
|
||||
|
||||
return api.post(apiurl, url_path, url_query)
|
||||
|
||||
|
||||
def get_linked_packages(apiurl, project, package):
|
||||
url_path = ["source", project, package]
|
||||
url_query = {"cmd": "showlinked"}
|
||||
root = api.post(apiurl, url_path, url_query)
|
||||
|
||||
result = []
|
||||
nodes = api.find_nodes(root, "collection", "package")
|
||||
for node in nodes:
|
||||
item = {
|
||||
"project": node.get("project"),
|
||||
"name": node.get("name"),
|
||||
}
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
|
||||
def release(
|
||||
apiurl,
|
||||
project,
|
||||
package,
|
||||
repository,
|
||||
target_project,
|
||||
target_repository,
|
||||
set_release_to=None,
|
||||
delayed=False,
|
||||
print_to="debug",
|
||||
):
|
||||
msg = format_msg_project_package_options(
|
||||
"Releasing",
|
||||
project,
|
||||
package,
|
||||
target_project,
|
||||
target_package=None,
|
||||
repository=repository,
|
||||
dest_repository=target_repository,
|
||||
delayed=delayed,
|
||||
)
|
||||
print_msg(msg, print_to=print_to)
|
||||
|
||||
url_path = ["source", project]
|
||||
if package:
|
||||
url_path += [package]
|
||||
|
||||
url_query = {"cmd": "release"}
|
||||
if repository:
|
||||
url_query["repository"] = repository
|
||||
if target_project:
|
||||
url_query["target_project"] = target_project
|
||||
if target_repository:
|
||||
url_query["target_repository"] = target_repository
|
||||
if set_release_to:
|
||||
url_query["setrelease"] = set_release_to
|
||||
if not delayed:
|
||||
url_query["nodelay"] = "1"
|
||||
|
||||
return api.post(apiurl, url_path, url_query)
|
57
osc/_private/common.py
Normal file
57
osc/_private/common.py
Normal file
@ -0,0 +1,57 @@
|
||||
import sys
|
||||
|
||||
|
||||
def print_msg(msg, print_to="debug"):
|
||||
from .. import conf
|
||||
|
||||
if print_to is None:
|
||||
return
|
||||
elif print_to == "debug":
|
||||
if conf.config["debug"]:
|
||||
print(f"DEBUG: {msg}", file=sys.stderr)
|
||||
elif print_to == "stdout":
|
||||
print(msg)
|
||||
else:
|
||||
raise ValueError(f"Invalid value of the 'output' option: {output}")
|
||||
|
||||
|
||||
def format_msg_project_package_options(
|
||||
msg,
|
||||
project=None,
|
||||
package=None,
|
||||
dest_project=None,
|
||||
dest_package=None,
|
||||
repository=None,
|
||||
dest_repository=None,
|
||||
**options,
|
||||
):
|
||||
"""
|
||||
Format msg, project, package, dest_project, dest_package and options into a meaningful message
|
||||
that can be printed out directly or as a debug message.
|
||||
"""
|
||||
if project and not package:
|
||||
msg += f" project '{project}'"
|
||||
else:
|
||||
msg += f" package '{project}/{package}'"
|
||||
|
||||
if repository:
|
||||
msg += f" repository '{repository}'"
|
||||
|
||||
if any([dest_project, dest_package, dest_repository]):
|
||||
msg += " to"
|
||||
|
||||
if dest_project and not dest_package:
|
||||
msg += f" project '{dest_project}'"
|
||||
elif dest_project and dest_package:
|
||||
msg += f" package '{dest_project}/{dest_package}'"
|
||||
|
||||
if dest_repository:
|
||||
msg += f" repository '{dest_repository}'"
|
||||
|
||||
msg_options = [key.replace("_", "-") for key, value in options.items() if value]
|
||||
if msg_options:
|
||||
msg_options.sort()
|
||||
msg_options_str = ", ".join(msg_options)
|
||||
msg += f" options: {msg_options_str}"
|
||||
|
||||
return msg
|
@ -48,6 +48,87 @@ def get_parser():
|
||||
return osc.argparser
|
||||
|
||||
|
||||
def pop_project_package_from_args(args, default_project=None, default_package=None, package_is_optional=False):
|
||||
"""
|
||||
Get project and package from given `args`.
|
||||
|
||||
:param args: List of command-line arguments.
|
||||
WARNING: `args` gets modified in this function call!
|
||||
:type args: list(str)
|
||||
:param default_project: Used if project cannot be retrieved from `args`.
|
||||
Resolved from the current working copy if set to '.'.
|
||||
:type default_project: str
|
||||
:param default_package: Used if package cannot be retrieved from `args`.
|
||||
Resolved from the current working copy if set to '.'.
|
||||
:type default_package: str
|
||||
:param package_is_optional: Whether to error out when package name cannot be retrieved.
|
||||
:type package_is_optional: bool
|
||||
:returns: Project name and package name.
|
||||
:rtype: tuple(str)
|
||||
"""
|
||||
assert isinstance(args, list)
|
||||
path = Path.cwd()
|
||||
|
||||
used_default_project = False
|
||||
try:
|
||||
project = args.pop(0)
|
||||
except IndexError:
|
||||
if not default_project:
|
||||
raise oscerr.OscValueError("Please specify a project")
|
||||
project = default_project
|
||||
used_default_project = True
|
||||
|
||||
if not isinstance(project, str):
|
||||
raise TypeError(f"Project should be 'str', found: {type(project).__name__}")
|
||||
|
||||
package = None
|
||||
|
||||
if project == "/":
|
||||
# no project name (to support listing all projects via `osc ls /`)
|
||||
project = None
|
||||
elif project and "/" in project:
|
||||
# project/package
|
||||
if project.count("/") != 1:
|
||||
raise oscerr.OscValueError(f"Argument doesn't match the '<project>/<package>' pattern: {project}")
|
||||
project, package = project.split("/")
|
||||
|
||||
if project == ".":
|
||||
# project name taken from the working copy
|
||||
store = osc_store.Store(path)
|
||||
project = store.project
|
||||
|
||||
if package is None:
|
||||
try:
|
||||
package = args.pop(0)
|
||||
except IndexError:
|
||||
if not package_is_optional and not used_default_project:
|
||||
# package is not optional and it wasn't specified together with the project
|
||||
raise oscerr.OscValueError("Please specify a package")
|
||||
|
||||
if default_package:
|
||||
package = default_package
|
||||
else:
|
||||
if package_is_optional:
|
||||
return project, None
|
||||
raise oscerr.OscValueError("Please specify a package")
|
||||
|
||||
if not isinstance(package, str):
|
||||
raise TypeError(f"Package should be 'str', found: {type(package).__name__}")
|
||||
|
||||
if package == ".":
|
||||
# package name taken from the working copy
|
||||
try:
|
||||
store = osc_store.Store(path)
|
||||
store.assert_is_package()
|
||||
package = store.package
|
||||
except oscerr.NoWorkingCopy:
|
||||
if not package_is_optional:
|
||||
raise
|
||||
package = None
|
||||
|
||||
return project, package
|
||||
|
||||
|
||||
class Osc(cmdln.Cmdln):
|
||||
"""
|
||||
openSUSE commander is a command-line interface to the Open Build Service.
|
||||
@ -514,28 +595,16 @@ class Osc(cmdln.Cmdln):
|
||||
osc addcontainers [PROJECT PACKAGE]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
localdir = Path.cwd()
|
||||
project = package = None
|
||||
if not args:
|
||||
if is_package_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
package = store_read_package(localdir)
|
||||
elif len(args) == 2:
|
||||
project = self._process_project_name(args[0])
|
||||
package = args[1]
|
||||
|
||||
if project is None or package is None:
|
||||
raise oscerr.WrongArgs('Either specify project and package or call it from a package working copy')
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=False
|
||||
)
|
||||
|
||||
query = {'cmd': 'addcontainers'}
|
||||
if opts.extend_package_names:
|
||||
query['extend_package_names'] = '1'
|
||||
|
||||
print("Add containers...")
|
||||
url = makeurl(apiurl, ['source', project, package], query=query)
|
||||
f = http_POST(url)
|
||||
_private.add_containers(
|
||||
apiurl, project, package, extend_package_names=opts.extend_package_names, print_to="stdout"
|
||||
)
|
||||
|
||||
@cmdln.option('-s', '--skip-disabled', action='store_true',
|
||||
help='Skip disabled channels. Otherwise the source gets added, but not the repositories.')
|
||||
@ -554,36 +623,19 @@ class Osc(cmdln.Cmdln):
|
||||
Examples:
|
||||
osc addchannels [PROJECT [PACKAGE]]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
localdir = Path.cwd()
|
||||
channel = None
|
||||
if not args:
|
||||
if is_project_dir(localdir) or is_package_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
elif is_package_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
channel = store_read_package(localdir)
|
||||
else:
|
||||
raise oscerr.WrongArgs('Either specify project [package] or call it from a project/package working copy')
|
||||
else:
|
||||
project = self._process_project_name(args[0])
|
||||
|
||||
query = {'cmd': 'addchannels'}
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
|
||||
if opts.enable_all and opts.skip_disabled:
|
||||
raise oscerr.WrongOptions('--enable-all and --skip-disabled options are mutually exclusive')
|
||||
elif opts.enable_all:
|
||||
query['mode'] = 'enable_all'
|
||||
elif opts.skip_disabled:
|
||||
query['mode'] = 'skip_disabled'
|
||||
self.argparse_error("Options '--enable-all' and '--skip-disabled' are mutually exclusive")
|
||||
|
||||
print("Looking for channels...")
|
||||
url = makeurl(apiurl, ['source', project], query=query)
|
||||
if channel:
|
||||
url = makeurl(apiurl, ['source', project, channel], query=query)
|
||||
f = http_POST(url)
|
||||
_private.add_channels(
|
||||
apiurl, project, package, enable_all=opts.enable_all, skip_disabled=opts.skip_disabled, print_to="stdout"
|
||||
)
|
||||
|
||||
@cmdln.alias('enablechannel')
|
||||
def do_enablechannels(self, subcmd, opts, *args):
|
||||
@ -595,37 +647,16 @@ class Osc(cmdln.Cmdln):
|
||||
The command can be used to enable a specific one or all channels of a project.
|
||||
|
||||
Examples:
|
||||
osc enablechannels [PROJECT [CHANNEL_PACKAGE]]
|
||||
osc enablechannels [PROJECT [PACKAGE]]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
localdir = Path.cwd()
|
||||
channel = None
|
||||
if not args:
|
||||
if is_project_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
elif is_package_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
channel = store_read_package(localdir)
|
||||
else:
|
||||
raise oscerr.WrongArgs('Either specify project [package] or call it from a project/package working copy')
|
||||
else:
|
||||
project = self._process_project_name(args[0])
|
||||
if len(args) > 1:
|
||||
channel = args[1]
|
||||
|
||||
query = {}
|
||||
if channel:
|
||||
query['cmd'] = 'enablechannel'
|
||||
else:
|
||||
query = {'cmd': 'modifychannels', 'mode': 'enable_all'}
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
|
||||
print("Enable channel(s)...")
|
||||
url = makeurl(apiurl, ['source', project], query=query)
|
||||
if channel:
|
||||
url = makeurl(apiurl, ['source', project, channel], query=query)
|
||||
f = http_POST(url)
|
||||
_private.enable_channels(apiurl, project, package, print_to="stdout")
|
||||
|
||||
@cmdln.option('-f', '--force', action='store_true',
|
||||
help='force generation of new patchinfo file, do not update existing one.')
|
||||
@ -711,28 +742,22 @@ class Osc(cmdln.Cmdln):
|
||||
Print the devel project / package of a package
|
||||
|
||||
Examples:
|
||||
osc develproject PRJ PKG
|
||||
osc develproject
|
||||
osc develproject [PROJECT PACKAGE]
|
||||
"""
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
|
||||
if len(args) == 0:
|
||||
project = store_read_project(Path.cwd())
|
||||
package = store_read_package(Path.cwd())
|
||||
elif len(args) == 2:
|
||||
project = self._process_project_name(args[0])
|
||||
package = args[1]
|
||||
else:
|
||||
raise oscerr.WrongArgs('need Project and Package')
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=False
|
||||
)
|
||||
|
||||
devprj, devpkg = show_devel_project(apiurl, project, package)
|
||||
if devprj is None:
|
||||
print('%s / %s has no devel project' % (project, package))
|
||||
elif devpkg and devpkg != package:
|
||||
print("%s %s" % (devprj, devpkg))
|
||||
else:
|
||||
print(devprj)
|
||||
devel_project, devel_package = show_devel_project(apiurl, project, package)
|
||||
|
||||
if not devel_project:
|
||||
print(f"Package {project}/{package} has no devel project", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"{devel_project}/{devel_package}")
|
||||
|
||||
@cmdln.alias('ca')
|
||||
def do_cleanassets(self, subcmd, opts, *args):
|
||||
@ -757,29 +782,41 @@ class Osc(cmdln.Cmdln):
|
||||
"""Set the devel project / package of a package
|
||||
|
||||
Examples:
|
||||
osc setdevelproject [PRJ PKG] DEVPRJ [DEVPKG]
|
||||
osc setdevelproject [PROJECT PACKAGE] DEVEL_PROJECT [DEVEL_PACKAGE]
|
||||
"""
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
|
||||
devprj, devpkg = None, None
|
||||
if len(args) == 3 or len(args) == 4:
|
||||
project, package = self._process_project_name(args[0]), args[1]
|
||||
devprj = self._process_project_name(args[2])
|
||||
if len(args) == 4:
|
||||
devpkg = args[3]
|
||||
elif len(args) >= 1 and len(args) <= 2:
|
||||
project, package = store_read_project(Path.cwd()), store_read_package(Path.cwd())
|
||||
devprj = self._process_project_name(args[0])
|
||||
if len(args) == 2:
|
||||
devpkg = args[1]
|
||||
args = list(args)
|
||||
if opts.unset:
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=False
|
||||
)
|
||||
devel_project = None
|
||||
devel_package = None
|
||||
else:
|
||||
if opts.unset:
|
||||
project, package = store_read_project(Path.cwd()), store_read_package(Path.cwd())
|
||||
else:
|
||||
raise oscerr.WrongArgs('need at least DEVPRJ (and possibly DEVPKG)')
|
||||
args_backup = args.copy()
|
||||
|
||||
set_devel_project(apiurl, project, package, devprj, devpkg)
|
||||
try:
|
||||
# try this sequence first: project package devel_project [devel_package]
|
||||
project, package = pop_project_package_from_args(args, package_is_optional=False)
|
||||
devel_project, devel_package = pop_project_package_from_args(
|
||||
args, default_package=package, package_is_optional=True
|
||||
)
|
||||
except oscerr.OscValueError:
|
||||
# then read project and package from working copy and try devel_project [devel_package]
|
||||
args = args_backup.copy()
|
||||
project, package = pop_project_package_from_args(
|
||||
[], default_project=".", default_package=".", package_is_optional=False
|
||||
)
|
||||
devel_project, devel_package = pop_project_package_from_args(
|
||||
args, default_package=package, package_is_optional=True
|
||||
)
|
||||
|
||||
if args:
|
||||
args_str = ", ".join(args)
|
||||
self.argparse_error(f"Unknown arguments: {args_str}")
|
||||
|
||||
set_devel_project(apiurl, project, package, devel_project, devel_package, print_to="stdout")
|
||||
|
||||
def do_showlinked(self, subcmd, opts, *args):
|
||||
"""
|
||||
@ -789,24 +826,16 @@ class Osc(cmdln.Cmdln):
|
||||
osc showlinked [PROJECT PACKAGE]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
localdir = Path.cwd()
|
||||
project = package = None
|
||||
if len(args) == 2:
|
||||
project = self._process_project_name(args[0])
|
||||
package = args[1]
|
||||
elif is_package_dir(localdir):
|
||||
project = store_read_project(localdir)
|
||||
package = store_read_package(localdir)
|
||||
else:
|
||||
raise oscerr.WrongArgs('Either specify project and package or call it from a package working copy')
|
||||
|
||||
url = makeurl(apiurl, ['source', project, package], query={'cmd': 'showlinked'})
|
||||
f = http_POST(url)
|
||||
root = ET.parse(f).getroot()
|
||||
for node in root.findall('package'):
|
||||
print(node.get('project') + " " + node.get('name'))
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=False
|
||||
)
|
||||
|
||||
linked_packages = _private.get_linked_packages(apiurl, project, package)
|
||||
for pkg in linked_packages:
|
||||
print(f"{pkg['project']}/{pkg['name']}")
|
||||
|
||||
@cmdln.option('-c', '--create', action='store_true',
|
||||
help='Create a new token')
|
||||
@ -2744,27 +2773,28 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
osc setlinkrev PROJECT [PACKAGE]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
package = None
|
||||
|
||||
rev = parseRevisionOption(opts.revision)[0] or ''
|
||||
if opts.unset:
|
||||
rev = None
|
||||
|
||||
args = list(args)
|
||||
if not args:
|
||||
p = Package(Path.cwd())
|
||||
project = p.prjname
|
||||
package = p.name
|
||||
apiurl = p.apiurl
|
||||
assert apiurl == p.apiurl
|
||||
if not p.islink():
|
||||
sys.exit('Local directory is no checked out source link package, aborting')
|
||||
elif len(args) == 2:
|
||||
project = self._process_project_name(args[0])
|
||||
package = args[1]
|
||||
elif len(args) == 1:
|
||||
project = self._process_project_name(args[0])
|
||||
else:
|
||||
self.argparse_error("Incorrect number of arguments.")
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
|
||||
if opts.revision and not package:
|
||||
# It is highly unlikely that all links for all packages in a project should be set to the same revision.
|
||||
self.argparse_error("The --revision option requires to specify a package")
|
||||
|
||||
if package:
|
||||
packages = [package]
|
||||
@ -2772,12 +2802,18 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
packages = meta_get_packagelist(apiurl, project)
|
||||
|
||||
for p in packages:
|
||||
rev = set_link_rev(apiurl, project, p, revision=rev,
|
||||
expand=not opts.use_plain_revision)
|
||||
try:
|
||||
rev = set_link_rev(apiurl, project, p, revision=rev, expand=not opts.use_plain_revision)
|
||||
except HTTPError as e:
|
||||
if e.code != 404:
|
||||
raise
|
||||
print(f"WARNING: Package {project}/{p} has no link", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if rev is None:
|
||||
print('removed revision from link')
|
||||
print(f"Removed link revision from package {project}/{p}")
|
||||
else:
|
||||
print('set revision to %s for package %s' % (rev, p))
|
||||
print(f"Set link revision of package {project}/{p} to {rev}")
|
||||
|
||||
def do_linktobranch(self, subcmd, opts, *args):
|
||||
"""
|
||||
@ -3100,51 +3136,26 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
It requires defined release targets set to trigger="manual".
|
||||
|
||||
usage:
|
||||
osc release [ SOURCEPROJECT [ SOURCEPACKAGE ] ]
|
||||
osc release [PROJECT [PACKAGE]]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
|
||||
source_project = source_package = None
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
|
||||
if len(args) > 2:
|
||||
raise oscerr.WrongArgs('Too many arguments.')
|
||||
|
||||
if len(args) == 0:
|
||||
if is_package_dir(Path.cwd()):
|
||||
source_project = store_read_project(Path.cwd())
|
||||
source_package = store_read_package(Path.cwd())
|
||||
elif is_project_dir(Path.cwd()):
|
||||
source_project = store_read_project(Path.cwd())
|
||||
else:
|
||||
raise oscerr.WrongArgs('Too few arguments.')
|
||||
if len(args) > 0:
|
||||
source_project = self._process_project_name(args[0])
|
||||
if len(args) > 1:
|
||||
source_package = args[1]
|
||||
|
||||
query = {'cmd': 'release'}
|
||||
if opts.target_project:
|
||||
query["target_project"] = opts.target_project
|
||||
if opts.target_repository:
|
||||
query["target_repository"] = opts.target_repository
|
||||
if opts.repo:
|
||||
query["repository"] = opts.repo
|
||||
if opts.set_release:
|
||||
query["setrelease"] = opts.set_release
|
||||
if opts.no_delay:
|
||||
query["nodelay"] = "1"
|
||||
baseurl = ['source', source_project]
|
||||
if source_package:
|
||||
baseurl.append(source_package)
|
||||
url = makeurl(apiurl, baseurl, query=query)
|
||||
f = http_POST(url)
|
||||
while True:
|
||||
buf = f.read(16384)
|
||||
if not buf:
|
||||
break
|
||||
sys.stdout.write(decode_it(buf))
|
||||
_private.release(
|
||||
apiurl,
|
||||
project=project,
|
||||
package=package,
|
||||
repository=opts.repo,
|
||||
target_project=opts.target_project,
|
||||
target_repository=opts.target_repository,
|
||||
set_release_to=opts.set_release,
|
||||
delayed=not opts.no_delay,
|
||||
print_to="stdout",
|
||||
)
|
||||
|
||||
@cmdln.option('-m', '--message', metavar='TEXT',
|
||||
help='specify message TEXT')
|
||||
@ -6827,30 +6838,12 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
||||
osc log (inside working copy)
|
||||
osc log remote_project [remote_package]
|
||||
"""
|
||||
|
||||
args = slash_split(args)
|
||||
apiurl = self.get_api_url()
|
||||
|
||||
if len(args) == 0:
|
||||
wd = Path.cwd()
|
||||
if is_project_dir(wd) or is_package_dir(wd):
|
||||
project = store_read_project(wd)
|
||||
if is_project_dir(wd):
|
||||
package = "_project"
|
||||
else:
|
||||
package = store_read_package(wd)
|
||||
else:
|
||||
raise oscerr.NoWorkingCopy("Error: \"%s\" is not an osc working copy." % os.path.abspath(wd))
|
||||
elif len(args) < 1:
|
||||
raise oscerr.WrongArgs('Too few arguments (required none or two)')
|
||||
elif len(args) > 2:
|
||||
raise oscerr.WrongArgs('Too many arguments (required none or two)')
|
||||
elif len(args) == 1:
|
||||
project = self._process_project_name(args[0])
|
||||
package = "_project"
|
||||
else:
|
||||
project = self._process_project_name(args[0])
|
||||
package = args[1]
|
||||
args = list(args)
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
|
||||
rev, rev_upper = parseRevisionOption(opts.revision)
|
||||
if rev and not checkRevision(project, package, rev, apiurl, opts.meta):
|
||||
|
20
osc/core.py
20
osc/core.py
@ -43,6 +43,7 @@ except ImportError:
|
||||
distro = None
|
||||
|
||||
from . import __version__
|
||||
from . import _private
|
||||
from . import conf
|
||||
from . import meter
|
||||
from . import oscerr
|
||||
@ -3688,7 +3689,21 @@ def show_devel_project(apiurl, prj, pac):
|
||||
return node.get('project'), node.get('package', None)
|
||||
|
||||
|
||||
def set_devel_project(apiurl, prj, pac, devprj=None, devpac=None):
|
||||
def set_devel_project(apiurl, prj, pac, devprj=None, devpac=None, print_to="debug"):
|
||||
if devprj:
|
||||
msg = "Setting devel project of"
|
||||
else:
|
||||
msg = "Unsetting devel project from"
|
||||
|
||||
msg = _private.format_msg_project_package_options(
|
||||
msg,
|
||||
prj,
|
||||
pac,
|
||||
devprj,
|
||||
devpac,
|
||||
)
|
||||
_private.print_msg(msg, print_to=print_to)
|
||||
|
||||
meta = show_package_meta(apiurl, prj, pac)
|
||||
root = ET.fromstring(b''.join(meta))
|
||||
node = root.find('devel')
|
||||
@ -6866,6 +6881,9 @@ def print_jobhistory(apiurl: str, prj: str, current_package: str, repository: st
|
||||
def get_commitlog(
|
||||
apiurl: str, prj: str, package: str, revision, format="text", meta=False, deleted=False, revision_upper=None
|
||||
):
|
||||
if package is None:
|
||||
package = "_project"
|
||||
|
||||
query = {}
|
||||
if deleted:
|
||||
query['deleted'] = 1
|
||||
|
144
tests/test_commandline.py
Normal file
144
tests/test_commandline.py
Normal file
@ -0,0 +1,144 @@
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from osc.commandline import pop_project_package_from_args
|
||||
from osc.oscerr import NoWorkingCopy, OscValueError
|
||||
from osc.store import Store
|
||||
|
||||
|
||||
class TestPopProjectPackageFromArgs(unittest.TestCase):
|
||||
def _write_store(self, project=None, package=None):
|
||||
store = Store(self.tmpdir, check=False)
|
||||
if project:
|
||||
store.project = project
|
||||
store.is_project = True
|
||||
if package:
|
||||
store.package = package
|
||||
store.is_project = False
|
||||
store.is_package = True
|
||||
|
||||
def setUp(self):
|
||||
self.tmpdir = tempfile.mkdtemp(prefix="osc_test")
|
||||
os.chdir(self.tmpdir)
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
shutil.rmtree(self.tmpdir)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def test_explicit_project_and_package(self):
|
||||
args = ["project", "package", "another-arg"]
|
||||
project, package = pop_project_package_from_args(args)
|
||||
self.assertEqual(project, "project")
|
||||
self.assertEqual(package, "package")
|
||||
self.assertEqual(args, ["another-arg"])
|
||||
|
||||
def test_defaults(self):
|
||||
args = ["project"]
|
||||
self.assertRaises(OscValueError, pop_project_package_from_args, args, default_package="default-package")
|
||||
|
||||
args = ["project"]
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_package="default-package", package_is_optional=True
|
||||
)
|
||||
self.assertEqual(project, "project")
|
||||
self.assertEqual(package, "default-package")
|
||||
self.assertEqual(args, [])
|
||||
|
||||
args = []
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project="default-project", default_package="default-package"
|
||||
)
|
||||
self.assertEqual(project, "default-project")
|
||||
self.assertEqual(package, "default-package")
|
||||
self.assertEqual(args, [])
|
||||
|
||||
args = []
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project="default-project", default_package="default-package", package_is_optional=True
|
||||
)
|
||||
self.assertEqual(project, "default-project")
|
||||
self.assertEqual(package, "default-package")
|
||||
self.assertEqual(args, [])
|
||||
|
||||
def test_slash_separator(self):
|
||||
args = ["project/package", "another-arg"]
|
||||
project, package = pop_project_package_from_args(args)
|
||||
self.assertEqual(project, "project")
|
||||
self.assertEqual(package, "package")
|
||||
self.assertEqual(args, ["another-arg"])
|
||||
|
||||
args = ["project/", "another-arg"]
|
||||
project, package = pop_project_package_from_args(args)
|
||||
self.assertEqual(project, "project")
|
||||
self.assertEqual(package, "")
|
||||
self.assertEqual(args, ["another-arg"])
|
||||
|
||||
def test_no_working_copy(self):
|
||||
args = [".", "."]
|
||||
self.assertRaises(NoWorkingCopy, pop_project_package_from_args, args)
|
||||
|
||||
args = [".", "package"]
|
||||
self.assertRaises(NoWorkingCopy, pop_project_package_from_args, args)
|
||||
|
||||
args = ["project", "."]
|
||||
self.assertRaises(NoWorkingCopy, pop_project_package_from_args, args)
|
||||
|
||||
def test_project_and_package_from_project_working_copy(self):
|
||||
self._write_store("store_project")
|
||||
|
||||
args = [".", ".", "another-arg"]
|
||||
self.assertRaises(NoWorkingCopy, pop_project_package_from_args, args)
|
||||
|
||||
args = ["."]
|
||||
project, package = pop_project_package_from_args(args, package_is_optional=True)
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, None)
|
||||
self.assertEqual(args, [])
|
||||
|
||||
args = []
|
||||
self.assertRaises(NoWorkingCopy, pop_project_package_from_args, args, default_project=".", default_package=".")
|
||||
|
||||
args = []
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, None)
|
||||
self.assertEqual(args, [])
|
||||
|
||||
def test_project_and_package_from_package_working_copy(self):
|
||||
self._write_store("store_project", "store_package")
|
||||
|
||||
args = [".", ".", "another-arg"]
|
||||
project, package = pop_project_package_from_args(args)
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, "store_package")
|
||||
self.assertEqual(args, ["another-arg"])
|
||||
|
||||
args = ["."]
|
||||
project, package = pop_project_package_from_args(args, package_is_optional=True)
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, None)
|
||||
self.assertEqual(args, [])
|
||||
|
||||
args = []
|
||||
project, package = pop_project_package_from_args(args, default_project=".", default_package=".")
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, "store_package")
|
||||
self.assertEqual(args, [])
|
||||
|
||||
args = []
|
||||
project, package = pop_project_package_from_args(
|
||||
args, default_project=".", default_package=".", package_is_optional=True
|
||||
)
|
||||
self.assertEqual(project, "store_project")
|
||||
self.assertEqual(package, "store_package")
|
||||
self.assertEqual(args, [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user