distutils_rust: download vendored crates from LFS

Summary: Switch from dewey to in-repo LFS utility.

Test Plan:
Run `make local` on my Arch Linux. Check `hg-vendored-crates.tar.gz` was
downloaded and stored in `build/`. Run `make local` again and make sure it
says:

  hg-vendored-crates.tar.gz was already downloaded and up-to-date

Reviewers: mbthomas, #mercurial

Reviewed By: mbthomas

Differential Revision: https://phabricator.intern.facebook.com/D6706906

Signature: 6706906:1515723430:233ccbb47286dbc4e5d856ff4b20c848b281928c
This commit is contained in:
Jun Wu 2018-01-11 17:16:44 -08:00
parent e53b0261c1
commit 32d36d135d
2 changed files with 31 additions and 42 deletions

View File

@ -3,6 +3,7 @@
# Copyright 2017 Facebook, Inc.
from __future__ import absolute_import
import contextlib
import distutils
import distutils.command.build
import distutils.core
@ -13,6 +14,18 @@ import shutil
import subprocess
import tarfile
SCRIPT_ROOT = os.path.realpath(os.path.join(__file__, '../..'))
LFS_SCRIPT_PATH = os.path.join(SCRIPT_ROOT, 'fb/tools/lfs.py')
@contextlib.contextmanager
def chdir(path):
cwd = os.getcwd()
try:
os.chdir(path)
yield
finally:
os.chdir(cwd)
class RustExtension(object):
"""Data for a Rust extension.
@ -32,25 +45,20 @@ class RustExtension(object):
self.manifest = manifest or 'Cargo.toml'
class RustVendoredCrates(object):
"""Data for Rust vendored crates stored in Dewey.
"""Data for Rust vendored crates stored in LFS.
'name' is the name of the vendoring set, and is also the Dewey tag.
'project' is the Dewey project the vendored crates are stored in.
'hashfile' is the filename that stores the Dewey hash that should be
downloaded.
'path' is the path in Dewey of the file to download.
'name' is the name of the vendoring set, and is also the LFS name (with
".tar.gz" appended) to download.
'dest' is the directory into which the archive should be extracted.
"""
def __init__(self, name, project=None, hashfile=None, path=None, dest=None):
def __init__(self, name, dest=None):
self.name = name
self.project = project
self.hashfile = hashfile or '.' + name
self.path = path or name + '.tar.gz'
self.dest = dest or '.'
self.dest = dest or os.getcwd()
@property
def filename(self):
return '%s.tar.gz' % self.name
class BuildRustExt(distutils.core.Command):
@ -126,40 +134,21 @@ class BuildRustExt(distutils.core.Command):
return os.path.join(package_dir, name)
def download_vendored_crates(self, ven):
commit = open(ven.hashfile).read()
desttarfile = os.path.join(ven.dest, ven.path)
desthashfile = desttarfile + ".hash"
if (os.path.exists(ven.dest) and
os.path.exists(desthashfile) and
commit == open(desthashfile).read()):
# Already downloaded, nothing to do.
return
try:
os.makedirs(ven.dest)
except OSError:
pass
distutils.log.info("downloading vendored crates '%s'", ven.name)
cmd = ["dewey", "cat"]
if ven.project is not None:
cmd += ["--project", ven.project]
cmd += [
"--commit", commit,
"--tag", ven.name,
"--path", ven.path,
"--dest", desttarfile]
cmd = [LFS_SCRIPT_PATH, 'download', ven.filename]
with chdir(ven.dest):
rc = subprocess.call(cmd)
if rc:
raise distutils.errors.CompileError(
"download of Rust vendored crates '%s' failed" % ven.name)
rc = subprocess.call(cmd)
if rc:
raise distutils.errors.CompileError(
"download of Rust vendored crates '%s' failed" % ven.name)
with tarfile.open(desttarfile, 'r:gz') as tar:
tar.extractall(ven.dest)
os.remove(desttarfile)
with open(desthashfile, 'w') as f:
f.write(commit)
with tarfile.open(ven.filename, 'r:gz') as tar:
tar.extractall(ven.dest)
def build_ext(self, ext):
distutils.log.info("building '%s' extension", ext.name)

View File

@ -1285,7 +1285,7 @@ def build_libraries(self, libraries):
distutils.command.build_clib.build_clib.build_libraries = build_libraries
rustvendoredcrates = [
RustVendoredCrates('hg-vendored-crates', project='fbsource', dest='build'),
RustVendoredCrates('hg-vendored-crates', dest='build'),
]
rustextmodules = [