[Notes] [Git][BuildStream/buildstream][valentindavid/cargo_plugin] Add source plugin for cargo.



Title: GitLab

Valentin David pushed to branch valentindavid/cargo_plugin at BuildStream / buildstream

Commits:

1 changed file:

Changes:

  • buildstream/plugins/sources/cargo.py
    1
    +#
    
    2
    +#  Copyright (C) 2018 Codethink Limited
    
    3
    +#
    
    4
    +#  This program is free software; you can redistribute it and/or
    
    5
    +#  modify it under the terms of the GNU Lesser General Public
    
    6
    +#  License as published by the Free Software Foundation; either
    
    7
    +#  version 2 of the License, or (at your option) any later version.
    
    8
    +#
    
    9
    +#  This library is distributed in the hope that it will be useful,
    
    10
    +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    11
    +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    
    12
    +#  Lesser General Public License for more details.
    
    13
    +#
    
    14
    +#  You should have received a copy of the GNU Lesser General Public
    
    15
    +#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
    
    16
    +#
    
    17
    +#  Authors:
    
    18
    +#        Valentin David  <valentin david codethink co uk>
    
    19
    +
    
    20
    +"""
    
    21
    +cargo - stage files from cargo manifest
    
    22
    +=======================================
    
    23
    +
    
    24
    +`cargo` downloads and stages cargo crates based on a `Cargo.toml`
    
    25
    +manifest provided by a previous source.
    
    26
    +
    
    27
    +`ref` will contain the `Cargo.lock` file. `bst track` should be used
    
    28
    +to set it.
    
    29
    +
    
    30
    +When `keep-lock` is true, tracking will store the current `Cargo.lock`
    
    31
    +provided by previous sources. in the `ref`. If `keep-lock` is false or
    
    32
    +absent, then `ref` will be created for the latest available crates.
    
    33
    +
    
    34
    +**Host dependencies:**
    
    35
    +
    
    36
    +  * cargo
    
    37
    +  * cargo-vendor (can be installed with `cargo install cargo-vendor`).
    
    38
    +
    
    39
    +**Usage:**
    
    40
    +
    
    41
    +.. code:: yaml
    
    42
    +
    
    43
    +   # Specify the cargo source kind
    
    44
    +   kind: cargo
    
    45
    +
    
    46
    +   # Optionally give the subdirectory where the `Cargo.toml` manifest
    
    47
    +   # can be found.
    
    48
    +   subdir: subproject
    
    49
    +
    
    50
    +   # Optionally disallow rewriting `Cargo.lock`. In this case tracking
    
    51
    +   # will just read the existing file. If not used, then tracking
    
    52
    +   # will create `Cargo.lock`.
    
    53
    +   keep-lock: true
    
    54
    +"""
    
    55
    +
    
    56
    +
    
    57
    +import hashlib
    
    58
    +import os
    
    59
    +
    
    60
    +from buildstream import Consistency, Source, utils
    
    61
    +
    
    62
    +
    
    63
    +class CargoSource(Source):
    
    64
    +
    
    65
    +    BST_REQUIRES_PREVIOUS_SOURCES_TRACK = True
    
    66
    +    BST_REQUIRES_PREVIOUS_SOURCES_FETCH = True
    
    67
    +
    
    68
    +    def configure(self, node):
    
    69
    +        self.node_validate(node, ['ref', 'subdir', 'keep-lock'] + Source.COMMON_CONFIG_KEYS)
    
    70
    +        self.ref = self.node_get_member(node, str, 'ref', None)
    
    71
    +        self.subdir = self.node_get_member(node, str, 'subdir', '.')
    
    72
    +        self.keeplock = self.node_get_member(node, bool, 'keep-lock', False)
    
    73
    +        self.extra_path = None
    
    74
    +
    
    75
    +    def preflight(self):
    
    76
    +        self.host_cargo = utils.get_host_tool('cargo')
    
    77
    +
    
    78
    +        try:
    
    79
    +            utils.get_host_tool('cargo-vendor')
    
    80
    +        except utils.ProgramNotFoundError:
    
    81
    +            cargo_home = os.environ.get('CARGO_HOME', os.path.expanduser('~/.cargo'))
    
    82
    +            self.extra_path = os.path.join(cargo_home, 'bin')
    
    83
    +
    
    84
    +        self.call([self.host_cargo, 'vendor', '-V'],
    
    85
    +                  env=self._environment(),
    
    86
    +                  fail='Cannot find "cargo vendor". Please install it with "cargo install cargo-vendor".')
    
    87
    +
    
    88
    +    def get_unique_key(self):
    
    89
    +        return [self.subdir, self.ref]
    
    90
    +
    
    91
    +    def get_ref(self):
    
    92
    +        return self.ref
    
    93
    +
    
    94
    +    def load_ref(self, node):
    
    95
    +        self.ref = self.node_get_member(node, str, 'ref', None)
    
    96
    +
    
    97
    +    def set_ref(self, ref, node):
    
    98
    +        node['ref'] = self.ref = ref
    
    99
    +
    
    100
    +    def _environment(self, *, set_home=False):
    
    101
    +        env = {}
    
    102
    +        env.update(os.environ)
    
    103
    +        if self.extra_path:
    
    104
    +            path = env.get('PATH', '').split(':')
    
    105
    +            path.append(self.extra_path)
    
    106
    +            env['PATH'] = ':'.join(path)
    
    107
    +        if set_home:
    
    108
    +            home = os.path.join(self.get_mirror_directory(), 'home')
    
    109
    +            os.makedirs(home, exist_ok=True)
    
    110
    +            env['CARGO_HOME'] = home
    
    111
    +        return env
    
    112
    +
    
    113
    +    def _get_manifest(self, directory):
    
    114
    +        projectdir = os.path.join(directory, self.subdir)
    
    115
    +        manifest = os.path.join(projectdir, 'Cargo.toml')
    
    116
    +        lockfile = os.path.join(projectdir, 'Cargo.lock')
    
    117
    +        return manifest, lockfile
    
    118
    +
    
    119
    +    def track(self, previous_sources_dir):
    
    120
    +        manifest, lockfile = self._get_manifest(previous_sources_dir)
    
    121
    +
    
    122
    +        if not self.keeplock:
    
    123
    +            self.call([self.host_cargo, 'generate-lockfile', '--manifest-path', manifest],
    
    124
    +                      env=self._environment(set_home=True),
    
    125
    +                      fail="Failed to track cargo packages")
    
    126
    +        try:
    
    127
    +            with open(lockfile, 'rb') as f:
    
    128
    +                lockcontent = f.read().decode('utf-8')
    
    129
    +        except OSError as e:
    
    130
    +            if self.keeplock and e.errno == errno.ENOENT:
    
    131
    +                raise SourceError("{}: Cannot find Cargo.lock".format(self))
    
    132
    +            else:
    
    133
    +                raise
    
    134
    +
    
    135
    +        return lockcontent
    
    136
    +
    
    137
    +    def _get_stamp(self):
    
    138
    +        h = hashlib.sha256()
    
    139
    +        h.update(self.get_ref().encode('utf-8'))
    
    140
    +        return os.path.join(self.get_mirror_directory(), 'stamps', h.hexdigest())
    
    141
    +
    
    142
    +    def get_consistency(self):
    
    143
    +        if not self.ref:
    
    144
    +            return Consistency.INCONSISTENT
    
    145
    +        if os.path.exists(self._get_stamp()):
    
    146
    +            return Consistency.CACHED
    
    147
    +        return Consistency.RESOLVED
    
    148
    +
    
    149
    +    def fetch(self, previous_sources_dir):
    
    150
    +        manifest, lockfile = self._get_manifest(previous_sources_dir)
    
    151
    +        if not self.keeplock:
    
    152
    +            with open(lockfile, 'wb') as f:
    
    153
    +                f.write(self.get_ref().encode('utf-8'))
    
    154
    +
    
    155
    +        self.call([self.host_cargo, 'fetch', '--manifest-path', manifest, '--locked'],
    
    156
    +                  env=self._environment(set_home=True),
    
    157
    +                  fail="Failed to fetch cargo packages")
    
    158
    +        stamp = self._get_stamp()
    
    159
    +        os.makedirs(os.path.dirname(stamp), exist_ok=True)
    
    160
    +        with open(stamp, 'w'):
    
    161
    +            pass
    
    162
    +
    
    163
    +    def stage(self, directory):
    
    164
    +        manifest, lockfile = self._get_manifest(directory)
    
    165
    +        if not self.keeplock:
    
    166
    +            with open(lockfile, 'wb') as f:
    
    167
    +                f.write(self.ref.encode('utf-8'))
    
    168
    +
    
    169
    +        config = os.path.join(os.path.dirname(manifest), '.cargo', 'config')
    
    170
    +        os.makedirs(os.path.dirname(config), exist_ok=True)
    
    171
    +
    
    172
    +        vendordir = os.path.join(directory, 'vendor')
    
    173
    +        relvendordir = os.path.relpath(vendordir, os.path.dirname(manifest))
    
    174
    +
    
    175
    +        with utils.save_file_atomic(config, 'wb') as f:
    
    176
    +            self.call([self.host_cargo, 'vendor', '--frozen', '--relative-path', relvendordir],
    
    177
    +                      env=self._environment(set_home=True),
    
    178
    +                      cwd=os.path.dirname(manifest),
    
    179
    +                      stdout=f,
    
    180
    +                      fail="Failed to stage cargo packages")
    
    181
    +
    
    182
    +
    
    183
    +def setup():
    
    184
    +    return CargoSource



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]