Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package osc for openSUSE:Factory checked in at 2023-02-03 22:05:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/osc (Old) and /work/SRC/openSUSE:Factory/.osc.new.4462 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "osc" Fri Feb 3 22:05:58 2023 rev:170 rq:1063021 version:1.0.0~b4 Changes: -------- --- /work/SRC/openSUSE:Factory/osc/osc.changes 2023-01-25 17:51:54.254858955 +0100 +++ /work/SRC/openSUSE:Factory/.osc.new.4462/osc.changes 2023-02-03 22:12:57.669979725 +0100 @@ -1,0 +2,28 @@ +Fri Feb 3 10:11:27 UTC 2023 - Daniel Mach <daniel.m...@suse.com> + +- 1.0.0b4 + - Fix regressions to osc 0.x: + - mv: Fix traceback due to missing target file name + - rm: Fix creating a Package object by providing multiple files on the command line + - copypac: Fix downgrading a package to an old revision + - buildhist: Fix running from a package checkout + - rebuild: Fix running from a package checkout + - rdiff: Fix traceback when new project is not specified + - rq list: Fix passing values of the --type option + - build: Fix reading extra-pkgs from oscrc + - Support withfullhistory in osc.core.get_request_list again + - Fix osc.get_request_list ignoring the req_type parameter + - Revert "Do not list declined requests by default" + - connection: Mute the "Converted retries value" debug message + - connection: Fix traceback on loading an invalid cookiejar file + - connection: Save cookiejar only when there's a Set-Cookie header in the response + - Add oscerr.ProjectError class needed by core.delete_project() + - Fix all errors reported by pylint + +- spec file: + - drop upstreamed patches: + - 1217.patch + - 1228.patch + - Recommend python3-distro - needed for setting the default editor by distro + +------------------------------------------------------------------- Old: ---- 1217.patch 1228.patch osc-1.0.0~b3.tar.gz New: ---- osc-1.0.0~b4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ osc.spec ++++++ --- /var/tmp/diff_new_pack.p6fTAd/_old 2023-02-03 22:12:58.141982467 +0100 +++ /var/tmp/diff_new_pack.p6fTAd/_new 2023-02-03 22:12:58.149982513 +0100 @@ -49,7 +49,7 @@ %endif Name: osc -Version: 1.0.0~b3 +Version: 1.0.0~b4 Release: 0 Summary: Command-line client for the Open Build Service License: GPL-2.0-or-later @@ -62,8 +62,7 @@ Source1: debian.dirs Source2: debian.docs %endif -Patch1: https://github.com/openSUSE/osc/pull/1228.patch -Patch2: https://github.com/openSUSE/osc/pull/1217.patch + BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -84,6 +83,9 @@ # needed for showing download progressbars Recommends: %{use_python_pkg}-progressbar +# needed for setting the default editor by distro +Recommends: %{use_python_pkg}-distro + # needed for storing credentials in kwallet/gnome-keyring Recommends: %{use_python_pkg}-keyring Recommends: %{use_python_pkg}-keyring-keyutils ++++++ PKGBUILD ++++++ --- /var/tmp/diff_new_pack.p6fTAd/_old 2023-02-03 22:12:58.193982769 +0100 +++ /var/tmp/diff_new_pack.p6fTAd/_new 2023-02-03 22:12:58.197982792 +0100 @@ -1,5 +1,5 @@ pkgname=osc -pkgver=1.0.0~b3 +pkgver=1.0.0~b4 pkgrel=0 pkgdesc="Command-line client for the Open Build Service" arch=('x86_64') ++++++ _service ++++++ --- /var/tmp/diff_new_pack.p6fTAd/_old 2023-02-03 22:12:58.217982908 +0100 +++ /var/tmp/diff_new_pack.p6fTAd/_new 2023-02-03 22:12:58.225982955 +0100 @@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> - <param name="version">1.0.0~b3</param> - <param name="revision">1.0.0b3</param> + <param name="version">1.0.0~b4</param> + <param name="revision">1.0.0b4</param> <param name="url">https://github.com/openSUSE/osc.git</param> <param name="scm">git</param> </service> ++++++ debian.changelog ++++++ --- /var/tmp/diff_new_pack.p6fTAd/_old 2023-02-03 22:12:58.269983211 +0100 +++ /var/tmp/diff_new_pack.p6fTAd/_new 2023-02-03 22:12:58.273983233 +0100 @@ -1,4 +1,4 @@ -osc (1.0.0~b3-0) unstable; urgency=low +osc (1.0.0~b4-0) unstable; urgency=low - Update to 0.174.0: - fix password deletion via "osc config -d <apiurl> pass" - support changing the password store via "osc config <apiurl> ++++++ osc-1.0.0~b3.tar.gz -> osc-1.0.0~b4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/.github/workflows/build-install.yaml new/osc-1.0.0~b4/.github/workflows/build-install.yaml --- old/osc-1.0.0~b3/.github/workflows/build-install.yaml 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/.github/workflows/build-install.yaml 2023-02-03 11:01:51.000000000 +0100 @@ -10,6 +10,10 @@ - 'README.md' - 'doc/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: rpmbuild: name: 'rpmbuild test' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/.github/workflows/codeql.yml new/osc-1.0.0~b4/.github/workflows/codeql.yml --- old/osc-1.0.0~b3/.github/workflows/codeql.yml 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/.github/workflows/codeql.yml 2023-02-03 11:01:51.000000000 +0100 @@ -8,6 +8,10 @@ schedule: - cron: "13 12 * * 6" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: analyze: name: Analyze diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/.github/workflows/linters.yaml new/osc-1.0.0~b4/.github/workflows/linters.yaml --- old/osc-1.0.0~b3/.github/workflows/linters.yaml 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/.github/workflows/linters.yaml 2023-02-03 11:01:51.000000000 +0100 @@ -7,6 +7,10 @@ - '.github/**' - '**.py' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: mypy: runs-on: ubuntu-latest @@ -25,11 +29,25 @@ with: fetch-depth: 0 - uses: actions/setup-python@v4 - - uses: akaihola/darker@1.5.1 + - uses: akaihola/darker@1.6.1 with: options: "--check --diff --color --line-length=120" src: "." - version: "1.5.1" + + pylint_errors: + name: 'Run pylint that reports only errors' + runs-on: 'ubuntu-latest' + steps: + - name: 'Install packages' + run: | + sudo apt-get -y update + sudo apt-get -y --no-install-recommends install pylint python3-rpm + + - uses: actions/checkout@v3 + + - name: 'Run pylint --errors-only' + run: | + pylint --errors-only osc pylint_plugins: name: 'Diff pylint runs on osc plugin' @@ -64,11 +82,28 @@ repository: ${{ matrix.plugin_repository }} path: plugin + - name: 'Run pylint with osc from master' + run: | + cd plugin + find . -type f -name "*.py" | sort | PYTHONPATH="../osc-master" xargs pylint --errors-only >> pylint-osc-master.log || : + + echo + echo ">>>>> pylint-osc-master.log <<<<<" + cat pylint-osc-master.log + + - name: 'Run pylint with osc from pull-request' + run: | + cd plugin + find . -type f -name "*.py" | sort | PYTHONPATH="../osc-pr" xargs pylint --errors-only >> pylint-osc-pr.log || : + + echo + echo ">>>>> pylint-osc-pr.log <<<<<" + cat pylint-osc-pr.log + - name: 'Diff pylint runs' run: | cd plugin - find -maxdepth 2 -name __init__.py | while read i; do dirname $i; done | sort > .pylint-args - find -maxdepth 1 -name '*.py' | sort >> .pylint-args - PYTHONPATH="../osc-master" pylint --errors-only $(cat .pylint-args) | sort > pylint-osc-master.log || : - PYTHONPATH="../osc-pr" pylint --errors-only $(cat .pylint-args) | sort > pylint-osc-pr.log || : + + echo + echo ">>>>> diff <<<<<" diff -u pylint-osc-master.log pylint-osc-pr.log diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/.github/workflows/tests.yaml new/osc-1.0.0~b4/.github/workflows/tests.yaml --- old/osc-1.0.0~b3/.github/workflows/tests.yaml 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/.github/workflows/tests.yaml 2023-02-03 11:01:51.000000000 +0100 @@ -9,6 +9,10 @@ - 'behave/**' - 'tests/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: unit: name: "unit" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/NEWS new/osc-1.0.0~b4/NEWS --- old/osc-1.0.0~b3/NEWS 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/NEWS 2023-02-03 11:01:51.000000000 +0100 @@ -1,3 +1,22 @@ +1.0.0b4 + - Fix regressions to osc 0.x: + - mv: Fix traceback due to missing target file name + - rm: Fix creating a Package object by providing multiple files on the command line + - copypac: Fix downgrading a package to an old revision + - buildhist: Fix running from a package checkout + - rebuild: Fix running from a package checkout + - rdiff: Fix traceback when new project is not specified + - rq list: Fix passing values of the --type option + - build: Fix reading extra-pkgs from oscrc + - Support withfullhistory in osc.core.get_request_list again + - Fix osc.get_request_list ignoring the req_type parameter + - Revert "Do not list declined requests by default" + - connection: Mute the "Converted retries value" debug message + - connection: Fix traceback on loading an invalid cookiejar file + - connection: Save cookiejar only when there's a Set-Cookie header in the response + - Add oscerr.ProjectError class needed by core.delete_project() + - Fix all errors reported by pylint + 1.0.0b3 - add create-pbuild-config (cpc) command which allows to create a working config for pbuild tool based on OBS server side data diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/buildhist.feature new/osc-1.0.0~b4/behave/features/buildhist.feature --- old/osc-1.0.0~b3/behave/features/buildhist.feature 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/buildhist.feature 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1,30 @@ +Feature: `osc buildhist` command + + +# common steps for all scenarios +Background: + Given I set working directory to "{context.osc.temp}" + + +Scenario: Run `osc buildist <project>/<package> <repository>/<arch>` + When I execute osc with args "buildhist test:factory/test-pkgA standard/x86_64" + Then the exit code is 0 + + +Scenario: Run `osc buildist <repository>/<arch>` from a package checkout + Given I execute osc with args "co test:factory/test-pkgA" + And I set working directory to "{context.osc.temp}/test:factory/test-pkgA" + When I execute osc with args "buildhist standard/x86_64" + Then the exit code is 0 + + +Scenario: Run `osc buildist <repository>/<arch>` from outside a package checkout + When I execute osc with args "buildhist standard/x86_64" + Then the exit code is 1 + + +Scenario: Run `osc buildist <repository>/<arch>` from a project checkout + Given I execute osc with args "co test:factory" + And I set working directory to "{context.osc.temp}/test:factory" + When I execute osc with args "buildhist standard/x86_64" + Then the exit code is 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/copypac.feature new/osc-1.0.0~b4/behave/features/copypac.feature --- old/osc-1.0.0~b3/behave/features/copypac.feature 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/copypac.feature 2023-02-03 11:01:51.000000000 +0100 @@ -18,6 +18,12 @@ Then the exit code is 0 +@destructive +Scenario: Run `osc copypac <project>/<package> <project>/<package> --keep-link --revision` + When I execute osc with args "copypac test:factory/test-pkgA test:factory/test-pkgA --keep-link --revision=1" + Then the exit code is 0 + + Scenario: Run `osc copypac` where the source and target are the same When I execute osc with args "copypac test:factory/test-pkgA test:factory" Then the exit code is 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/mv.feature new/osc-1.0.0~b4/behave/features/mv.feature --- old/osc-1.0.0~b3/behave/features/mv.feature 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/mv.feature 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1,21 @@ +Feature: `osc mv` 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 mv <file> <new-name>` in a package checkout + When I execute osc with args "mv test-pkgA.changes new-name.changes" + Then the exit code is 0 + And I execute osc with args "status" + And stdout is + """ + A new-name.changes + D test-pkgA.changes + """ + And file "{context.osc.temp}/test:factory/test-pkgA/test-pkgA.changes" does not exist + And file "{context.osc.temp}/test:factory/test-pkgA/new-name.changes" exists diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/rdelete.feature new/osc-1.0.0~b4/behave/features/rdelete.feature --- old/osc-1.0.0~b3/behave/features/rdelete.feature 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/rdelete.feature 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1,6 @@ +Feature: `osc rdelete` command + +@destructive +Scenario: Run `osc rdelete` to delete a project and mark it with a desctructive tag + When I execute osc with args "rdelete -r -f test:factory -m 'cleanup'" + Then the exit code is 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/rdiff.feature new/osc-1.0.0~b4/behave/features/rdiff.feature --- old/osc-1.0.0~b3/behave/features/rdiff.feature 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/rdiff.feature 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1,26 @@ +Feature: `osc rdiff` command + + +# common steps for all scenarios +Background: + Given I set working directory to "{context.osc.temp}" + + +Scenario: Run `osc rdiff <project>/<package> <target-project>/<target-package>` + When I execute osc with args "rdiff test:factory/test-pkgA test:factory/test-pkgA" + Then the exit code is 0 + + +Scenario: Run `osc rdiff <project>/<package> <target-project>` + When I execute osc with args "rdiff test:factory/test-pkgA test:factory" + Then the exit code is 0 + + +Scenario: Run `osc rdiff <project>/<package>` + When I execute osc with args "rdiff test:factory/test-pkgA" + Then the exit code is 0 + + +Scenario: Run `osc rdiff <project>/<package> --change` + When I execute osc with args "rdiff test:factory/test-pkgA --change=1" + Then the exit code is 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/behave/features/rm.feature new/osc-1.0.0~b4/behave/features/rm.feature --- old/osc-1.0.0~b3/behave/features/rm.feature 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/behave/features/rm.feature 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1,19 @@ +Feature: `osc rm` 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 rm` on multiple files + When I execute osc with args "rm test-pkgA.spec test-pkgA.changes" + Then the exit code is 0 + And I execute osc with args "status" + And stdout is + """ + D test-pkgA.changes + D test-pkgA.spec + """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/contrib/osc.spec new/osc-1.0.0~b4/contrib/osc.spec --- old/osc-1.0.0~b3/contrib/osc.spec 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/contrib/osc.spec 2023-02-03 11:01:51.000000000 +0100 @@ -19,7 +19,7 @@ %endif # generate manpages on distros where argparse-manpage >= 3 is available -%if 0%{?suse_version} > 1500 || 0%{?fedora} +%if 0%{?suse_version} > 1500 || 0%{?fedora} >= 37 %bcond_without man %else %bcond_with man @@ -31,7 +31,7 @@ %endif Name: osc -Version: 1.0.0~b3 +Version: 1.0.0~b4 Release: 0 Summary: Command-line client for the Open Build Service License: GPL-2.0-or-later @@ -65,6 +65,9 @@ # needed for showing download progressbars Recommends: %{use_python_pkg}-progressbar +# needed for setting the default editor by distro +Recommends: %{use_python_pkg}-distro + # needed for storing credentials in kwallet/gnome-keyring Recommends: %{use_python_pkg}-keyring Recommends: %{use_python_pkg}-keyring-keyutils diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/doc/README.md new/osc-1.0.0~b4/doc/README.md --- old/osc-1.0.0~b3/doc/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/doc/README.md 2023-02-03 11:01:51.000000000 +0100 @@ -0,0 +1 @@ +This is the place where all osc documentation starts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/__init__.py new/osc-1.0.0~b4/osc/__init__.py --- old/osc-1.0.0~b3/osc/__init__.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/__init__.py 2023-02-03 11:01:51.000000000 +0100 @@ -13,7 +13,7 @@ from .util import git_version -__version__ = git_version.get_version('1.0.0~b3') +__version__ = git_version.get_version('1.0.0~b4') # vim: sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/_private/api_build.py new/osc-1.0.0~b4/osc/_private/api_build.py --- old/osc-1.0.0~b3/osc/_private/api_build.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/_private/api_build.py 2023-02-03 11:01:51.000000000 +0100 @@ -34,7 +34,7 @@ ] url_query = {} if self._limit and self._limit > 0: - query["limit"] = self._limit + url_query["limit"] = self._limit root = api.get(self.apiurl, url_path, url_query) @@ -47,8 +47,13 @@ "ver_rel": node.get("versrel"), "build_count": int(node.get("bcnt")), "time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(node.get("time")))), - "duration": int(node.get("duration")), } + + # duration may not always be available + duration = node.get("duration") + if duration: + item["duration"] = int(duration) + result.append(item) return result @@ -72,7 +77,7 @@ i["srcmd5"], f"{i['ver_rel']}.{i['build_count']}", i["rev"], - i["duration"], + i.get("duration", ""), ) data.extend(item) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/_private/common.py new/osc-1.0.0~b4/osc/_private/common.py --- old/osc-1.0.0~b3/osc/_private/common.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/_private/common.py 2023-02-03 11:01:51.000000000 +0100 @@ -12,7 +12,7 @@ elif print_to == "stdout": print(msg) else: - raise ValueError(f"Invalid value of the 'output' option: {output}") + raise ValueError(f"Invalid value of the 'print_to' option: {print_to}") def format_msg_project_package_options( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/babysitter.py new/osc-1.0.0~b4/osc/babysitter.py --- old/osc-1.0.0~b3/osc/babysitter.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/babysitter.py 2023-02-03 11:01:51.000000000 +0100 @@ -26,6 +26,7 @@ try: # import as RPMError because the class "error" is too generic + # pylint: disable=E0611 from rpm import error as RPMError except: # if rpm-python isn't installed (we might be on a debian system): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/build.py new/osc-1.0.0~b4/osc/build.py --- old/osc-1.0.0~b3/osc/build.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/build.py 2023-02-03 11:01:51.000000000 +0100 @@ -221,6 +221,14 @@ def __init__(self, node, buildarch, pacsuffix, apiurl, localpkgs=None): localpkgs = localpkgs or [] + + # set attributes to mute pylint error E1101: Instance of 'Pac' has no '<attr>' member (no-member) + self.project = None + self.name = None + self.canonname = None + self.repository = None + self.repoarch = None + self.mp = {} for i in ['binary', 'package', 'epoch', 'version', 'release', 'hdrmd5', @@ -292,7 +300,7 @@ self.urllist = [url % self.mp for url in urllist] def __str__(self): - return self.name + return self.name or "" def __repr__(self): return "%s" % self.name @@ -863,7 +871,7 @@ extra_pkgs = [] if not opts.extra_pkgs: - extra_pkgs = getattr(config, 'extra-pkgs', extra_pkgs) + extra_pkgs = config.get('extra-pkgs', []) elif opts.extra_pkgs != ['']: extra_pkgs = opts.extra_pkgs @@ -1177,11 +1185,11 @@ def __del__(self): self.cleanup() - def __exit__(self): + def __exit__(self, exc_type, exc_value, traceback): self.cleanup() def __str__(self): - return self.name + return self.name or "" old_pkg_dir = mytmpdir(prefix='.build.oldpackages', dir=os.path.abspath(os.curdir)) if not os.path.exists(destdir): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/checker.py new/osc-1.0.0~b4/osc/checker.py --- old/osc-1.0.0~b3/osc/checker.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/checker.py 2023-02-03 11:01:51.000000000 +0100 @@ -19,6 +19,7 @@ import rpm self.dbdir = mkdtemp(prefix='oscrpmdb') self.imported = {} + # pylint: disable=E1101 rpm.addMacro('_dbpath', self.dbdir) self.ts = rpm.TransactionSet() self.ts.initDB() @@ -29,6 +30,7 @@ def readkeys(self, keys=None): import rpm keys = keys or [] + # pylint: disable=E1101 rpm.addMacro('_dbpath', self.dbdir) for key in keys: try: @@ -40,6 +42,7 @@ raise KeyError('', "no key imported") import rpm + # pylint: disable=E1101 rpm.delMacro("_dbpath") # python is an idiot diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/commandline.py new/osc-1.0.0~b4/osc/commandline.py --- old/osc-1.0.0~b3/osc/commandline.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/commandline.py 2023-02-03 11:01:51.000000000 +0100 @@ -1856,7 +1856,7 @@ print('created request id', result) if conf.config['print_web_links']: - obs_url = _private.get_configuration_option(apiurl, "obs_url") + obs_url = _private.get_configuration_value(apiurl, "obs_url") print(f"{obs_url}/request/show/{result}") if supersede_existing: @@ -2487,7 +2487,7 @@ @cmdln.option('-f', '--force', action='store_true', help='enforce state change, can be used to ignore open reviews') @cmdln.option('-s', '--state', - help='only list requests in one of the comma separated given states (new/review/accepted/revoked/declined) or "all" [default="new,review"]') + help='only list requests in one of the comma separated given states (new/review/accepted/revoked/declined) or "all" [default="new,review,declined"]') @cmdln.option('-D', '--days', metavar='DAYS', help='only list requests in state "new" or changed in the last DAYS.') @cmdln.option('-U', '--user', metavar='USER', @@ -2621,7 +2621,7 @@ state_list = ["all"] else: if not opts.state: - opts.state = "new,review" + opts.state = "new,review,declined" state_list = opts.state.split(",") state_list = [i for i in state_list if i.strip()] @@ -2773,7 +2773,7 @@ roles = ["creator"] if opts.mine else None results = get_request_collection( apiurl, project=project, package=package, user=who, - states=state_list, types=opts.type, roles=roles) + states=state_list, types=[opts.type], roles=roles) # Check if project actually exists if result list is empty if not results: @@ -3349,9 +3349,8 @@ if opts.message: comment = opts.message else: - if not rev: - rev = show_upstream_rev(src_apiurl, src_project, src_package) - comment = 'osc copypac from project:%s package:%s revision:%s' % (src_project, src_package, rev) + src_rev = rev or show_upstream_rev(src_apiurl, src_project, src_package) + comment = 'osc copypac from project:%s package:%s revision:%s' % (src_project, src_package, src_rev) if opts.keep_link: comment += ", using keep-link" if opts.expand: @@ -3650,7 +3649,7 @@ r = create_maintenance_request(apiurl, source_project, source_packages, target_project, release_project, opt_sourceupdate, opts.message, opts.enforce_branching) print(r.reqid) if conf.config['print_web_links']: - obs_url = _private.get_configuration_option(apiurl, "obs_url") + obs_url = _private.get_configuration_value(apiurl, "obs_url") print(f"{obs_url}/request/show/{r.reqid}") if supersede_existing: @@ -4201,6 +4200,9 @@ ) ensure_no_remaining_args(args) + if not new_project: + new_project = old_project + if not new_package: new_package = old_package @@ -4578,7 +4580,7 @@ else: raise oscerr.WrongArgs('Wrong number of arguments') - download_url = _private.get_configuration_option(apiurl, "download_url") + download_url = _private.get_configuration_value(apiurl, "download_url") url_deb_tmpl = 'deb ' + download_url + '/%s/%s/ /' url_arch_tmpl = 'Server=' + download_url + '/%s/%s/$arch' @@ -6907,8 +6909,16 @@ apiurl = self.get_api_url() args = list(args) - project, package, repository, arch = pop_project_package_repository_arch_from_args(args) - ensure_no_remaining_args(args) + args_backup = args.copy() + + try: + args = [".", "."] + args_backup.copy() + project, package, repository, arch = pop_project_package_repository_arch_from_args(args) + ensure_no_remaining_args(args) + except (oscerr.NoWorkingCopy, oscerr.WrongArgs): + args[:] = args_backup.copy() + project, package, repository, arch = pop_project_package_repository_arch_from_args(args) + ensure_no_remaining_args(args) if opts.multibuild_package: package = package + ":" + opts.multibuild_package @@ -7144,6 +7154,8 @@ package_is_optional=True, repository_is_optional=True, arch_is_optional=True, + default_project='.', + default_package='.', ) ensure_no_remaining_args(args) @@ -9159,11 +9171,11 @@ os.rename(source, dest) try: - tgt_pkg[0].addfile(os.path.basename(dest)) + tgt_pkg.addfile(os.path.basename(dest)) except oscerr.PackageFileConflict: # file is already tracked pass - src_pkg[0].delete_file(os.path.basename(source), force=opts.force) + src_pkg.delete_file(os.path.basename(source), force=opts.force) @cmdln.option('-d', '--delete', action='store_true', help='delete option from config or reset option to the default)') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/connection.py new/osc-1.0.0~b4/osc/connection.py --- old/osc-1.0.0~b3/osc/connection.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/connection.py 2023-02-03 11:01:51.000000000 +0100 @@ -217,7 +217,7 @@ pool = CONNECTION_POOLS.get(apiurl, None) if not pool: pool_kwargs = {} - pool_kwargs["retries"] = int(conf.config["http_retries"]) + pool_kwargs["retries"] = urllib3.Retry(total=int(conf.config["http_retries"])) if purl.scheme == "https": ssl_context = oscssl.create_ssl_context() @@ -451,7 +451,10 @@ pass jar = http.cookiejar.LWPCookieJar(self.cookiejar_path) if os.path.isfile(self.cookiejar_path): - jar.load() + try: + jar.load() + except http.cookiejar.LoadError: + pass self.COOKIEJARS[self.cookiejar_path] = jar return jar @@ -484,8 +487,9 @@ return False def process_response(self, url, request_headers, response): - self._cookiejar.extract_cookies(response, MockRequest(url, response.headers)) - self._cookiejar.save() + if response.headers.get_all("set-cookie", None): + self._cookiejar.extract_cookies(response, MockRequest(url, response.headers)) + self._cookiejar.save() self._unlock() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/core.py new/osc-1.0.0~b4/osc/core.py --- old/osc-1.0.0~b3/osc/core.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/core.py 2023-02-03 11:01:51.000000000 +0100 @@ -1224,7 +1224,14 @@ def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True): global store - self.dir = workingdir + self.todo = [] + if os.path.isfile(workingdir) or not os.path.exists(workingdir): + # workingdir is a file + # workingdir doesn't exist -> it points to a non-existing file in a working dir (e.g. during mv) + workingdir, todo_entry = os.path.split(workingdir) + self.todo.append(todo_entry) + + self.dir = workingdir or "." self.absdir = os.path.abspath(self.dir) self.store = Store(self.dir) self.storedir = os.path.join(self.absdir, store) @@ -1251,8 +1258,6 @@ 'of the working copy afterwards (via \'osc status %s\')' % (self.dir, self.dir, self.dir) raise oscerr.WorkingCopyInconsistent(self.prjname, self.name, dirty_files, msg) - self.todo = [] - def __repr__(self): return super().__repr__() + f"({self.prjname}/{self.name})" @@ -1272,18 +1277,24 @@ """ packages = [] for path in paths: - # TODO: match only dirs, remove the code for resolving files into Package objects - orig_path = path - path_is_file = os.path.isfile(path) - if path_is_file: - path = os.path.dirname(path) or "." package = cls(path, progress_obj) - if path_is_file: - # XXX: modifying 'todo' is an unexpected side-effect - package.todo = [os.path.basename(orig_path)] - if package in packages: - raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package") - packages.append(package) + seen_package = None + try: + # re-use an existing package + seen_package_index = packages.index(package) + seen_package = packages[seen_package_index] + except ValueError: + pass + + if seen_package: + # merge package into seen_package + if seen_package.absdir != package.absdir: + raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package") + seen_package.merge(package) + else: + # use the new package instance + packages.append(package) + return packages @classmethod @@ -1295,21 +1306,30 @@ packages = [] failed_to_load = [] for path in paths: - # TODO: match only dirs, remove the code for resolving files into Package objects - orig_path = path - path_is_file = os.path.isfile(path) - if path_is_file: - path = os.path.dirname(path) or "." try: package = cls(path, progress_obj) - if path_is_file: - # XXX: modifying 'todo' is an unexpected side-effect - package.todo = [os.path.basename(orig_path)] - if package in packages: + except oscerr.NoWorkingCopy: + failed_to_load.append(path) + continue + + # the following code is identical to from_paths() + seen_package = None + try: + # re-use an existing package + seen_package_index = packages.index(package) + seen_package = packages[seen_package_index] + except ValueError: + pass + + if seen_package: + # merge package into seen_package + if seen_package.absdir != package.absdir: raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package") + seen_package.merge(package) + else: + # use the new package instance packages.append(package) - except oscerr.NoWorkingCopy: - failed_to_load.append(orig_path) + return packages, failed_to_load def wc_check(self): @@ -2134,7 +2154,6 @@ def diff_add_delete(fname, add, revision): diff = [] diff.append(diff_hdr % fname.encode()) - tmpfile = None origname = fname if add: diff.append(b'--- %s\t(revision 0)\n' % fname.encode()) @@ -2155,6 +2174,8 @@ diff.append(b'+++ %s\t(working copy)\n' % fname.encode()) fname = os.path.join(self.storedir, fname) + fd = None + tmpfile = None try: if revision is not None and not add: (fd, tmpfile) = tempfile.mkstemp(prefix='osc_diff') @@ -2180,8 +2201,9 @@ lines.append(b'\n\\ No newline at end of file\n') diff.extend(lines) finally: - if tmpfile is not None: + if fd is not None: os.close(fd) + if tmpfile is not None and os.path.exists(tmpfile): os.unlink(tmpfile) return diff @@ -2226,6 +2248,7 @@ if revision is None: yield get_source_file_diff(self.absdir, f.name, self.rev) else: + fd = None tmpfile = None diff = [] try: @@ -2234,8 +2257,9 @@ diff = get_source_file_diff(self.absdir, f.name, revision, os.path.basename(tmpfile), os.path.dirname(tmpfile), f.name) finally: - if tmpfile is not None: + if fd is not None: os.close(fd) + if tmpfile is not None and os.path.exists(tmpfile): os.unlink(tmpfile) yield diff @@ -2245,7 +2269,9 @@ yield diff_add_delete(f, False, revision) def merge(self, otherpac): - self.todo += otherpac.todo + for todo_entry in otherpac.todo: + if todo_entry not in self.todo: + self.todo.append(todo_entry) def __str__(self): r = """ @@ -2617,7 +2643,8 @@ elif filename in self.skipped: raise oscerr.OscIOError(None, 'file \'%s\' is marked as skipped and cannot be reverted' % filename) if filename in self.filenamelist and not os.path.exists(os.path.join(self.storedir, filename)): - raise oscerr.PackageInternalError('file \'%s\' is listed in filenamelist but no storefile exists' % filename) + msg = f"file '{filename}' is listed in filenamelist but no storefile exists" + raise oscerr.PackageInternalError(self.prjname, self.name, msg) state = self.status(filename) if not (state == 'A' or state == '!' and filename in self.to_be_added): shutil.copyfile(os.path.join(self.storedir, filename), os.path.join(self.absdir, filename)) @@ -4203,10 +4230,7 @@ def _get_linux_distro(): if distro is not None: return distro.id() - elif sys.version_info >= (3, 8): - return None - # compatibility for Python 2.6 to 3.7 - return platform.linux_distribution()[0] + return None def get_default_editor(): @@ -4604,8 +4628,9 @@ package=None, states=None, review_states=None, - types=None, + types: List[str] = None, ids=None, + withfullhistory=False ): # We don't want to overload server by requesting everything. @@ -4632,7 +4657,7 @@ raise ValueError("Project must be set to query a package; see https://github.com/openSUSE/open-build-service/issues/13075") query["package"] = package - states = states or ("new", "review") + states = states or ("new", "review", "declined") if states: if "all" not in states: query["states"] = ",".join(states) @@ -4642,11 +4667,15 @@ query["review_states"] = ",".join(review_states) if types: + assert not isinstance(types, str) query["types"] = ",".join(types) if ids: query["ids"] = ",".join(ids) + if withfullhistory: + query["withfullhistory"] = "1" + u = makeurl(apiurl, ['request'], query) f = http_GET(u) res = ET.parse(f).getroot() @@ -4726,10 +4755,13 @@ "project": project, "package": package, "states": req_state, + "withfullhistory": withfullhistory, } + if req_type is not None: + kwargs["types"] = [req_type] + assert not exclude_target_projects, "unsupported" - assert not withfullhistory, "unsupported" return get_request_collection(**kwargs) @@ -4741,6 +4773,7 @@ req_state=( "new", "review", + "declined", ), req_type=None, exclude_projects=None, @@ -5932,8 +5965,10 @@ or by the server, in a single api call. """ if (src_apiurl, src_project, src_package) == (dst_apiurl, dst_project, dst_package): - # copypac is also used to expand sources, let's allow that - if not expand: + # special cases when source and target can be the same: + # * expanding sources + # * downgrading package to an old revision + if not any([expand, revision]): raise oscerr.OscValueError("Cannot copy package. Source and target are the same.") if not (src_apiurl == dst_apiurl and src_project == dst_project @@ -6073,7 +6108,7 @@ def delete_project(apiurl: str, prj: str, force=False, msg=None, recursive=False): if not recursive: - packages = meta_get_packagelist(apiurl, project) + packages = meta_get_packagelist(apiurl, prj) if packages: error_msg = \ "Project contains packages. It must be empty before deleting it. " \ @@ -8000,7 +8035,7 @@ return msg -def print_request_list(apiurl, project, package=None, states=('new', 'review'), force=False): +def print_request_list(apiurl, project, package=None, states=("new", "review"), force=False): """ prints list of pending requests for the specified project/package if "check_for_request_on_action" is enabled in the config or if "force" is set to True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/fetch.py new/osc-1.0.0~b4/osc/fetch.py --- old/osc-1.0.0~b3/osc/fetch.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/fetch.py 2023-02-03 11:01:51.000000000 +0100 @@ -86,6 +86,8 @@ pac = pkgs[decode_it(hdr.filename)] # Extract a single file from the cpio archive + fd = None + tmpfile = None try: fd, tmpfile = tempfile.mkstemp(prefix='osc_build_file') archive.copyin_file(hdr.filename, @@ -93,8 +95,9 @@ decode_it(os.path.basename(tmpfile))) self.move_package(tmpfile, pac.localdir, pac) finally: - os.close(fd) - if os.path.exists(tmpfile): + if fd is not None: + os.close(fd) + if tmpfile is not None and os.path.exists(tmpfile): os.unlink(tmpfile) for pac in pkgs.values(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/osc/oscerr.py new/osc-1.0.0~b4/osc/oscerr.py --- old/osc-1.0.0~b3/osc/oscerr.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/osc/oscerr.py 2023-02-03 11:01:51.000000000 +0100 @@ -126,6 +126,21 @@ % (self.args[0], self.args[1], self.args[2])) +class ProjectError(OscBaseError): + """Base class for all Project related exceptions""" + + def __init__(self, prj, msg=None): + super().__init__() + self.prj = prj + self.msg = msg + + def __str__(self): + result = f"{self.__class__.__name__}: {self.prj}" + if self.msg: + result += f": {self.msg}" + return result + + class PackageError(OscBaseError): """Base class for all Package related exceptions""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/tests/fixtures/packages/osctest/projectA/pkgA-symlink new/osc-1.0.0~b4/tests/fixtures/packages/osctest/projectA/pkgA-symlink --- old/osc-1.0.0~b3/tests/fixtures/packages/osctest/projectA/pkgA-symlink 1970-01-01 01:00:00.000000000 +0100 +++ new/osc-1.0.0~b4/tests/fixtures/packages/osctest/projectA/pkgA-symlink 2023-02-03 22:12:58.545984814 +0100 @@ -0,0 +1 @@ +symbolic link to pkgA diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.0.0~b3/tests/test_core_package.py new/osc-1.0.0~b4/tests/test_core_package.py --- old/osc-1.0.0~b3/tests/test_core_package.py 2023-01-17 09:35:55.000000000 +0100 +++ new/osc-1.0.0~b4/tests/test_core_package.py 2023-02-03 11:01:51.000000000 +0100 @@ -69,6 +69,36 @@ def _get_fixtures_dir(self): return FIXTURES_DIR + def test_package_object_dir(self): + path = "projectA/pkgA" + path = os.path.join(self.tmpdir, 'osctest', path) + pac = osc.core.Package(path) + + self.assertEqual(pac.name, "pkgA") + self.assertEqual(pac.prjname, "projectA") + self.assertEqual(pac.apiurl, "http://localhost") + self.assertEqual(pac.todo, []) + + def test_package_object_file(self): + path = "projectA/pkgA/pkgA.spec" + path = os.path.join(self.tmpdir, 'osctest', path) + pac = osc.core.Package(path) + + self.assertEqual(pac.name, "pkgA") + self.assertEqual(pac.prjname, "projectA") + self.assertEqual(pac.apiurl, "http://localhost") + self.assertEqual(pac.todo, ["pkgA.spec"]) + + def test_package_object_file_missing(self): + path = "projectA/pkgA/missing-file" + path = os.path.join(self.tmpdir, 'osctest', path) + pac = osc.core.Package(path) + + self.assertEqual(pac.name, "pkgA") + self.assertEqual(pac.prjname, "projectA") + self.assertEqual(pac.apiurl, "http://localhost") + self.assertEqual(pac.todo, ["missing-file"]) + def test_single_package(self): paths = ["projectA/pkgA"] paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] @@ -81,10 +111,31 @@ self.assertEqual(pac.apiurl, "http://localhost") def test_duplicates(self): + # passing a path twice is ok paths = ["projectA/pkgA", "projectA/pkgA"] paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] + pacs = osc.core.Package.from_paths(paths) + pac = pacs[0] + self.assertEqual(pac.name, "pkgA") + self.assertEqual(pac.prjname, "projectA") + self.assertEqual(pac.apiurl, "http://localhost") + + # the same package in 2 paths is an error + paths = ["projectA/pkgA", "projectA/pkgA-symlink"] + paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] self.assertRaises(osc.oscerr.PackageExists, osc.core.Package.from_paths, paths) + def test_one_package_two_files(self): + paths = ["projectA/pkgA/pkgA.spec", "projectA/pkgA/pkgA.changes"] + paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] + pacs = osc.core.Package.from_paths(paths) + self.assertEqual(len(pacs), 1) + + pac = pacs[0] + self.assertEqual(pac.name, "pkgA") + self.assertEqual(pac.prjname, "projectA") + self.assertEqual(pac.apiurl, "http://localhost") + def test_two_packages(self): paths = ["projectA/pkgA", "projectA/pkgB"] paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] ++++++ osc.dsc ++++++ --- /var/tmp/diff_new_pack.p6fTAd/_old 2023-02-03 22:12:58.693985673 +0100 +++ /var/tmp/diff_new_pack.p6fTAd/_new 2023-02-03 22:12:58.697985697 +0100 @@ -1,6 +1,6 @@ Format: 1.0 Source: osc -Version: 1.0.0~b1-0 +Version: 1.0.0~b4-0 Binary: osc Maintainer: Adrian Schroeter <adr...@suse.de> Architecture: any