From 56b8aa6b926850aecbe0b830973721735078159d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 4 Oct 2024 14:24:14 +0200 Subject: [PATCH 1/2] Fix revision'd checkout of scmsync package When specifing a revision to a checkout we need to transfer the information to the bridge to do the right checkout. We also need to take the former git url in case it has changed meanwhile. --- osc/core.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osc/core.py b/osc/core.py index 51a9d569..2799939a 100644 --- a/osc/core.py +++ b/osc/core.py @@ -3156,8 +3156,25 @@ def checkout_package( raise oscerr.OscIOError(None, 'Install the obs-scm-bridge package to work on packages managed in scm (git)!') scm_url = scmsync_element.text directory = make_dir(apiurl, project, package, pathname, prj_dir, conf.config['do_package_tracking'], outdir) + + if revision is not None: + # search for the git sha sum based on the OBS DISTURL package source revision + # we need also take into account that the url was different at that point of time + url = shasum = None + u = makeurl(apiurl, ['source', project, package, '_scmsync.obsinfo'], {'rev': revision}) + f = http_GET(u) + for line in f.readlines(): + if line.startswith(b"revision: "): + shasum = line[10:].rstrip() + if line.startswith(b"url: "): + url = line[5:].rstrip() + if shasum is None: + raise oscerr.OscIOError(None, 'Unable to find git shasum for given revision') + scm_url = url + b'#' + shasum + os.putenv("OSC_VERSION", get_osc_version()) run_external(['/usr/lib/obs/service/obs_scm_bridge', '--outdir', directory, '--url', scm_url]) + Package.init_package(apiurl, project, package, directory, size_limit, meta, progress_obj, scm_url) # add package to /.obs/_packages From 5172002728c7fe7bad2e77746c107ab228accd27 Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Mon, 7 Oct 2024 09:55:40 +0200 Subject: [PATCH 2/2] Refactor code handling _scmsync.obsinfo to obs_api.scmsync_obsinfo.ScmsyncObsinfo class --- osc/core.py | 14 ++------- osc/obs_api/scmsync_obsinfo.py | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 osc/obs_api/scmsync_obsinfo.py diff --git a/osc/core.py b/osc/core.py index 2799939a..fcd31c83 100644 --- a/osc/core.py +++ b/osc/core.py @@ -3160,17 +3160,9 @@ def checkout_package( if revision is not None: # search for the git sha sum based on the OBS DISTURL package source revision # we need also take into account that the url was different at that point of time - url = shasum = None - u = makeurl(apiurl, ['source', project, package, '_scmsync.obsinfo'], {'rev': revision}) - f = http_GET(u) - for line in f.readlines(): - if line.startswith(b"revision: "): - shasum = line[10:].rstrip() - if line.startswith(b"url: "): - url = line[5:].rstrip() - if shasum is None: - raise oscerr.OscIOError(None, 'Unable to find git shasum for given revision') - scm_url = url + b'#' + shasum + from .obs_api.scmsync_obsinfo import ScmsyncObsinfo + scmsync_obsinfo = ScmsyncObsinfo.from_api(apiurl, project, package, rev=revision) + scm_url = f"{scmsync_obsinfo.url}#{scmsync_obsinfo.revision}" os.putenv("OSC_VERSION", get_osc_version()) run_external(['/usr/lib/obs/service/obs_scm_bridge', '--outdir', directory, '--url', scm_url]) diff --git a/osc/obs_api/scmsync_obsinfo.py b/osc/obs_api/scmsync_obsinfo.py new file mode 100644 index 00000000..84d4df76 --- /dev/null +++ b/osc/obs_api/scmsync_obsinfo.py @@ -0,0 +1,56 @@ +import typing + +from ..util.models import * # pylint: disable=wildcard-import,unused-wildcard-import + + +class ScmsyncObsinfo(BaseModel): + """ + Class for handling _scmsync.obsinfo files + """ + + mtime: int = Field() + commit: str = Field() + url: str = Field() + revision: str = Field() + + @classmethod + def from_string(cls, data: str) -> "ScmsyncObsinfo": + kwargs = {} + for line in data.splitlines(): + line = line.strip() + if not line: + continue + key, value = line.split(": ", 1) + field = cls.__fields__.get(key, None) + if field and field.type is int: + value = int(value) + kwargs[key] = value + return cls(**kwargs) + + @classmethod + def from_file(cls, file: Union[str, typing.IO]) -> "ScmsyncObsinfo": + if isinstance(file, str): + with open(file, "r", encoding="utf-8") as f: + return cls.from_string(f.read()) + data = file.read() + if isinstance(data, bytes): + data = data.decode("utf-8") + return cls.from_string(data) + + @classmethod + def from_api(cls, apiurl: str, project: str, package: str, *, rev: str) -> "ScmsyncObsinfo": + import urllib.error + from .. import oscerr + from ..connection import http_request + from ..core import makeurl + + url_path = ["source", project, package, "_scmsync.obsinfo"] + url_query = {"rev": rev} + url = makeurl(apiurl, url_path, url_query) + try: + response = http_request("GET", url) + except urllib.error.HTTPError as e: + if e.status == 404: + raise oscerr.NotFoundAPIError(f"File '_scmsync.obsinfo' was not found in {project}/{package}, rev={rev}") + raise + return cls.from_file(response)