You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by tv...@apache.org on 2021/02/04 07:21:09 UTC

[buildstream] branch valentindavid/cargo_plugin created (now d86dade)

This is an automated email from the ASF dual-hosted git repository.

tvb pushed a change to branch valentindavid/cargo_plugin
in repository https://gitbox.apache.org/repos/asf/buildstream.git.


      at d86dade  Add source plugin for cargo.

This branch includes the following new commits:

     new d86dade  Add source plugin for cargo.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[buildstream] 01/01: Add source plugin for cargo.

Posted by tv...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tvb pushed a commit to branch valentindavid/cargo_plugin
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit d86daded81f2e5cc39d5811601e65fbff3f85c69
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Wed Sep 12 22:13:34 2018 +0200

    Add source plugin for cargo.
    
    Fixes #123.
---
 buildstream/plugins/sources/cargo.py | 186 +++++++++++++++++++++++++++++++++++
 doc/source/core_plugins.rst          |   1 +
 2 files changed, 187 insertions(+)

diff --git a/buildstream/plugins/sources/cargo.py b/buildstream/plugins/sources/cargo.py
new file mode 100644
index 0000000..1075e7f
--- /dev/null
+++ b/buildstream/plugins/sources/cargo.py
@@ -0,0 +1,186 @@
+#
+#  Copyright (C) 2018 Codethink Limited
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
+#
+#  Authors:
+#        Valentin David  <va...@codethink.co.uk>
+
+"""
+cargo - stage files from cargo manifest
+=======================================
+
+`cargo` downloads and stages cargo crates based on a `Cargo.toml`
+manifest provided by a previous source.
+
+`ref` will contain the `Cargo.lock` file. `bst track` should be used
+to set it.
+
+When `keep-lock` is true, tracking will store the current `Cargo.lock`
+provided by previous sources. in the `ref`. If `keep-lock` is false or
+absent, then `ref` will be created for the latest available crates.
+
+**Host dependencies:**
+
+  * cargo
+  * cargo-vendor (can be installed with `cargo install cargo-vendor`).
+
+**Usage:**
+
+.. code:: yaml
+
+   # Specify the cargo source kind
+   kind: cargo
+
+   # Optionally give the subdirectory where the `Cargo.toml` manifest
+   # can be found.
+   subdir: subproject
+
+   # Optionally disallow rewriting `Cargo.lock`. In this case tracking
+   # will just read the existing file. If not used, then tracking
+   # will create `Cargo.lock`.
+   keep-lock: true
+"""
+
+
+import hashlib
+import os
+import errno
+
+from buildstream import Consistency, Source, utils, SourceError
+
+
+class CargoSource(Source):
+    # pylint: disable=attribute-defined-outside-init
+
+    BST_REQUIRES_PREVIOUS_SOURCES_TRACK = True
+    BST_REQUIRES_PREVIOUS_SOURCES_FETCH = True
+
+    def configure(self, node):
+        self.node_validate(node, ['ref', 'subdir', 'keep-lock'] + Source.COMMON_CONFIG_KEYS)
+        self.ref = self.node_get_member(node, str, 'ref', None)
+        self.subdir = self.node_get_member(node, str, 'subdir', '.')
+        self.keeplock = self.node_get_member(node, bool, 'keep-lock', False)
+        self.extra_path = None
+
+    def preflight(self):
+        self.host_cargo = utils.get_host_tool('cargo')
+
+        try:
+            utils.get_host_tool('cargo-vendor')
+        except utils.ProgramNotFoundError:
+            cargo_home = os.environ.get('CARGO_HOME', os.path.expanduser('~/.cargo'))
+            self.extra_path = os.path.join(cargo_home, 'bin')
+
+        self.call([self.host_cargo, 'vendor', '-V'],
+                  env=self._environment(),
+                  fail='Cannot find "cargo vendor". Please install it with "cargo install cargo-vendor".')
+
+    def get_unique_key(self):
+        return [self.subdir, self.ref]
+
+    def get_ref(self):
+        return self.ref
+
+    def load_ref(self, node):
+        self.ref = self.node_get_member(node, str, 'ref', None)
+
+    def set_ref(self, ref, node):
+        node['ref'] = self.ref = ref
+
+    def _environment(self, *, set_home=False):
+        env = {}
+        env.update(os.environ)
+        if self.extra_path:
+            path = env.get('PATH', '').split(':')
+            path.append(self.extra_path)
+            env['PATH'] = ':'.join(path)
+        if set_home:
+            home = os.path.join(self.get_mirror_directory(), 'home')
+            os.makedirs(home, exist_ok=True)
+            env['CARGO_HOME'] = home
+        return env
+
+    def _get_manifest(self, directory):
+        projectdir = os.path.join(directory, self.subdir)
+        manifest = os.path.join(projectdir, 'Cargo.toml')
+        lockfile = os.path.join(projectdir, 'Cargo.lock')
+        return manifest, lockfile
+
+    def track(self, previous_sources_dir):
+        manifest, lockfile = self._get_manifest(previous_sources_dir)
+
+        if not self.keeplock:
+            self.call([self.host_cargo, 'generate-lockfile', '--manifest-path', manifest],
+                      env=self._environment(set_home=True),
+                      fail="Failed to track cargo packages")
+        try:
+            with open(lockfile, 'rb') as f:
+                lockcontent = f.read().decode('utf-8')
+        except OSError as e:
+            if self.keeplock and e.errno == errno.ENOENT:
+                raise SourceError("{}: Cannot find Cargo.lock".format(self))
+            else:
+                raise
+
+        return lockcontent
+
+    def _get_stamp(self):
+        h = hashlib.sha256()
+        h.update(self.get_ref().encode('utf-8'))
+        return os.path.join(self.get_mirror_directory(), 'stamps', h.hexdigest())
+
+    def get_consistency(self):
+        if not self.ref:
+            return Consistency.INCONSISTENT
+        if os.path.exists(self._get_stamp()):
+            return Consistency.CACHED
+        return Consistency.RESOLVED
+
+    def fetch(self, previous_sources_dir):
+        manifest, lockfile = self._get_manifest(previous_sources_dir)
+        if not self.keeplock:
+            with open(lockfile, 'wb') as f:
+                f.write(self.get_ref().encode('utf-8'))
+
+        self.call([self.host_cargo, 'fetch', '--manifest-path', manifest, '--locked'],
+                  env=self._environment(set_home=True),
+                  fail="Failed to fetch cargo packages")
+        stamp = self._get_stamp()
+        os.makedirs(os.path.dirname(stamp), exist_ok=True)
+        with open(stamp, 'w'):
+            pass
+
+    def stage(self, directory):
+        manifest, lockfile = self._get_manifest(directory)
+        if not self.keeplock:
+            with open(lockfile, 'wb') as f:
+                f.write(self.ref.encode('utf-8'))
+
+        config = os.path.join(os.path.dirname(manifest), '.cargo', 'config')
+        os.makedirs(os.path.dirname(config), exist_ok=True)
+
+        vendordir = os.path.join(directory, 'vendor')
+        relvendordir = os.path.relpath(vendordir, os.path.dirname(manifest))
+
+        with utils.save_file_atomic(config, 'wb') as f:
+            self.call([self.host_cargo, 'vendor', '--frozen', '--relative-path', relvendordir],
+                      env=self._environment(set_home=True),
+                      cwd=os.path.dirname(manifest),
+                      stdout=f,
+                      fail="Failed to stage cargo packages")
+
+
+def setup():
+    return CargoSource
diff --git a/doc/source/core_plugins.rst b/doc/source/core_plugins.rst
index c82ffe5..241a035 100644
--- a/doc/source/core_plugins.rst
+++ b/doc/source/core_plugins.rst
@@ -59,6 +59,7 @@ Sources
    sources/patch
    sources/deb
    sources/pip
+   sources/cargo
 
 
 External plugins