--- a/python/mozbuild/mozbuild/vendor_rust.py
+++ b/python/mozbuild/mozbuild/vendor_rust.py
@@ -8,16 +8,17 @@ from distutils.version import LooseVersi
import logging
from mozbuild.base import (
BuildEnvironmentNotFoundException,
MozbuildObject,
)
import mozfile
import mozpack.path as mozpath
import os
+import re
import subprocess
import sys
class VendorRust(MozbuildObject):
def get_cargo_path(self):
try:
return self.substs['CARGO']
except (BuildEnvironmentNotFoundException, KeyError):
@@ -30,16 +31,29 @@ class VendorRust(MozbuildObject):
Ensure that cargo is new enough. cargo 0.12 added support
for source replacement, which is required for vendoring to work.
'''
out = subprocess.check_output([cargo, '--version']).splitlines()[0]
if not out.startswith('cargo'):
return False
return LooseVersion(out.split()[1]) >= b'0.13'
+ def check_cargo_vendor_version(self, cargo):
+ '''
+ Ensure that cargo-vendor is new enough. cargo-vendor 0.1.3 and newer
+ strips out .gitattributes files which we want.
+ '''
+ for l in subprocess.check_output([cargo, 'install', '--list']).splitlines():
+ # The line looks like `cargo-vendor v0.1.3:`
+ m = re.match('cargo-vendor v((\d\.)*\d):', l)
+ if m:
+ version = m.group(1)
+ return LooseVersion(version) >= b'0.1.3'
+ return False
+
def check_modified_files(self):
'''
Ensure that there aren't any uncommitted changes to files
in the working copy, since we're going to change some state
on the user. Allow changes to Cargo.{toml,lock} since that's
likely to be a common use case.
'''
modified = [f for f in self.repository.get_modified_files() if os.path.basename(f) not in ('Cargo.toml', 'Cargo.lock')]
@@ -89,22 +103,27 @@ Please commit or stash these changes bef
cargo = self.get_cargo_path()
if not self.check_cargo_version(cargo):
self.log(logging.ERROR, 'cargo_version', {}, 'Cargo >= 0.13 required (install Rust 1.12 or newer)')
return
else:
self.log(logging.DEBUG, 'cargo_version', {}, 'cargo is new enough')
have_vendor = any(l.strip() == 'vendor' for l in subprocess.check_output([cargo, '--list']).splitlines())
if not have_vendor:
- self.log(logging.INFO, 'installing', {}, 'Installing cargo-vendor')
+ self.log(logging.INFO, 'installing', {}, 'Installing cargo-vendor (this may take a few minutes)...')
env = self.check_openssl()
self.run_process(args=[cargo, 'install', 'cargo-vendor'],
append_env=env)
+ elif not self.check_cargo_vendor_version(cargo):
+ self.log(logging.INFO, 'cargo_vendor', {}, 'cargo-vendor >= 0.1.3 required; force-reinstalling (this may take a few minutes)...')
+ env = self.check_openssl()
+ self.run_process(args=[cargo, 'install', '--force', 'cargo-vendor'],
+ append_env=env)
else:
- self.log(logging.DEBUG, 'cargo_vendor', {}, 'cargo-vendor already intalled')
+ self.log(logging.DEBUG, 'cargo_vendor', {}, 'sufficiently new cargo-vendor is already intalled')
relative_vendor_dir = 'third_party/rust'
vendor_dir = mozpath.join(self.topsrcdir, relative_vendor_dir)
self.log(logging.INFO, 'rm_vendor_dir', {}, 'rm -rf %s' % vendor_dir)
mozfile.remove(vendor_dir)
# Once we require a new enough cargo to switch to workspaces, we can
# just do this once on the workspace root crate.
crates_and_roots = (
('gkrust', 'toolkit/library/rust'),