diff mbox series

[RFC,20/21] fetch: add cargolock fetcher

Message ID 20241220112613.22647-21-stefan.herbrechtsmeier-oss@weidmueller.com
State New
Headers show
Series Concept for tightly coupled package manager (Node.js, Go, Rust) | expand

Commit Message

Stefan Herbrechtsmeier Dec. 20, 2024, 11:26 a.m. UTC
From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Add cargolock fetcher to fetch dependencies via a cargo.lock file. The
fetcher uses the dependency mixin and supports different types:

cargolock
    The fetcher uses a local cargo.lock file to fetch dependencies.

    SRC_URI = "cargolock://cargo.lock"

cargolock+https
    The fetcher downloads a cargo.lock file or archive with a cargo.lock
    file in the root folder and uses the cargo.lock file to fetch
    dependencies.

    SRC_URI = "cargolock+http://example.com/cargo.lock"
    SRC_URI = "cargolock+http://example.com/${BP}.tar.gz;striplevel=1;subdir=${BP}"

cargolock+git
    The fetcher checkouts a git repository with a cargo.lock file to
    fetch dependencies.

    SRC_URI = "cargolock+git://example.com/${BPN}.git;protocol=https"

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 lib/bb/fetch2/__init__.py  |  2 ++
 lib/bb/fetch2/cargolock.py | 73 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)
 create mode 100644 lib/bb/fetch2/cargolock.py
diff mbox series

Patch

diff --git a/lib/bb/fetch2/__init__.py b/lib/bb/fetch2/__init__.py
index 10b4cf24b..012130ac6 100644
--- a/lib/bb/fetch2/__init__.py
+++ b/lib/bb/fetch2/__init__.py
@@ -2117,6 +2117,7 @@  from . import crate
 from . import gcp
 from . import gomod
 from . import gosum
+from . import cargolock
 
 methods.append(local.Local())
 methods.append(wget.Wget())
@@ -2142,3 +2143,4 @@  methods.append(gomod.GoMod())
 methods.append(gomod.GoModGit())
 methods.extend(npmsw.methods)
 methods.extend(gosum.methods)
+methods.extend(cargolock.methods)
diff --git a/lib/bb/fetch2/cargolock.py b/lib/bb/fetch2/cargolock.py
new file mode 100644
index 000000000..18df160ed
--- /dev/null
+++ b/lib/bb/fetch2/cargolock.py
@@ -0,0 +1,73 @@ 
+# Copyright (C) 2024-2025 Weidmueller Interface GmbH & Co. KG
+# Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+#
+# SPDX-License-Identifier: MIT
+#
+"""
+BitBake 'Fetch' implementation for cargo.lock
+
+The cargolock, cargolock+https and cargolock+git fetchers are used to download
+Cargo dependencies via a cargo.lock file.
+"""
+
+import os
+import tomllib
+import bb
+from bb.fetch2 import ParameterError
+from bb.fetch2 import URI
+from bb.fetch2.dependency import create_methods
+
+class CargoLockMixin:
+    def resolve_dependencies(self, ud, localpath, d):
+        if os.path.isdir(localpath):
+            localpath = os.path.join(localpath, "Cargo.lock")
+        try:
+            with open(localpath, "rb") as f:
+                crates = tomllib.load(f)
+        except Exception as e:
+            raise ParameterError("Invalid Cargo lock file: %s" % str(e), ud.url)
+
+        urls = []
+        for crate in crates.get("package", []):
+            name =  crate.get('name')
+            version = crate.get('version')
+            source = crate.get("source")
+            
+            if not source:
+                continue
+
+            if source.startswith("registry"):
+                uri = URI(source[9:])
+                if (uri.scheme == "https" and uri.hostname == "github.com"
+                        and uri.path == "/rust-lang/crates.io-index"):
+                    uri.scheme = "crate"
+                    uri.hostname = "crates.io"
+                    uri.path = f"/{name}/{version}"
+                    uri.params["dn"] = name
+                    uri.params["dv"] = version
+                else:
+                    bb.warn(f"Please add support for the url to crate fetcher: {source}")
+                    uri.params["subdir"] = os.path.join("cargo_home", "bitbake")
+                uri.params["sha256sum"] = crate.get('checksum')
+                url = str(uri)
+
+            elif source.startswith("git"):
+                url, _, rev = source.partition("#")
+                uri = URI(url)
+                scheme, _, protocol = uri.scheme.partition("+")
+                if protocol:
+                    uri.params["protocol"] = protocol
+                    uri.scheme = scheme
+                uri.params["rev"] = rev
+                uri.params["nobranch"] = "1"
+                uri.params["destsuffix"] = f"{name}-{version}"
+                uri.params["subdir"] = os.path.join("cargo_home", "bitbake")
+                url = str(uri)
+            else:
+                raise ParameterError(f"Unsupported dependency: {name}", ud.url)
+
+            urls.append(url)
+
+        return urls
+
+methods = create_methods("cargolock", CargoLockMixin)