From c458627230bef878c86b133e0687614bcf64df56 Mon Sep 17 00:00:00 2001 From: Others Date: Sat, 15 Jul 2017 16:23:11 -0400 Subject: [PATCH 1/8] Improve panic docs for Instant::duration_since The docs for Instant::duration_since has a confusing section on panicking. It's much more clear without the second two sentences of description. --- src/libstd/time/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index e4b8d457e2d2..4eed336a7a00 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -163,10 +163,7 @@ impl Instant { /// /// # Panics /// - /// This function will panic if `earlier` is later than `self`, which should - /// only be possible if `earlier` was created after `self`. Because - /// `Instant` is monotonic, the only time that this should happen should be - /// a bug. + /// This function will panic if `earlier` is later than `self`. /// /// # Examples /// From b525abb7b2f6706e6f698dff5070484fec2dc017 Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Mon, 17 Jul 2017 20:34:13 +1200 Subject: [PATCH 2/8] Add #[derive(Clone)] to TokenTreeIter --- src/libproc_macro/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 3c5d6aceca91..12ed4fba402b 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -375,6 +375,7 @@ impl Literal { } /// An iterator over `TokenTree`s. +#[derive(Clone)] #[unstable(feature = "proc_macro", issue = "38356")] pub struct TokenTreeIter { cursor: tokenstream::Cursor, From ffae5deaa77dcb9ca5e18adcd12d465a90b4c089 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Mon, 17 Jul 2017 22:29:09 +0200 Subject: [PATCH 3/8] configure: allow distros to disable debuginfo-only-std --- configure | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index e08bcc028272..e3ad7ce85f8c 100755 --- a/configure +++ b/configure @@ -560,8 +560,8 @@ case "$CFG_RELEASE_CHANNEL" in *-pc-windows-gnu) ;; *) - CFG_ENABLE_DEBUGINFO_LINES=1 - CFG_ENABLE_DEBUGINFO_ONLY_STD=1 + enable_if_not_disabled debuginfo-lines + enable_if_not_disabled debuginfo-only-std ;; esac @@ -572,8 +572,8 @@ case "$CFG_RELEASE_CHANNEL" in *-pc-windows-gnu) ;; *) - CFG_ENABLE_DEBUGINFO_LINES=1 - CFG_ENABLE_DEBUGINFO_ONLY_STD=1 + enable_if_not_disabled debuginfo-lines + enable_if_not_disabled debuginfo-only-std ;; esac ;; From 9b8c223407ae726157f43173ec1f3a743830d858 Mon Sep 17 00:00:00 2001 From: Vadzim Dambrouski Date: Tue, 18 Jul 2017 14:40:51 +0300 Subject: [PATCH 4/8] Fix LLVM assertion when a weak symbol is defined in global_asm. This change will fix the issue from https://github.com/japaric/svd2rust/pull/130 --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index a5ef0696d7c1..d9e7d2696e41 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit a5ef0696d7c103006d3cb1f4263bad0ca13adca8 +Subproject commit d9e7d2696e41983b6b5a0b4fac604b4e548a84d3 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 6b410502e491..c30290167d48 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-07-12 +2017-07-18 From daa276ebb76c966b0d51768c426eb0ebcebe48ec Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Jul 2017 19:01:51 -0600 Subject: [PATCH 5/8] Update liblibc --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index 2015cf17a6a2..ec1e5ab1ef8b 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 2015cf17a6a2a2280e93d9c57214ba92dbbaf42f +Subproject commit ec1e5ab1ef8baca57f8776bbebd9343572a87082 From 18d970164524ae3f51f97b30080d061f2007c046 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 19 Jul 2017 23:12:58 +0300 Subject: [PATCH 6/8] Add an extra note to `late_bound_lifetime_arguments` error/lint --- src/librustc/ty/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 21 +++++++------ src/librustc_typeck/collect.rs | 28 ++++++++--------- src/test/ui/method-call-lifetime-args-lint.rs | 31 +++++++++++++++++++ .../ui/method-call-lifetime-args-lint.stderr | 31 +++++++++++++++++++ src/test/ui/method-call-lifetime-args.rs | 25 +++++++++++++++ src/test/ui/method-call-lifetime-args.stderr | 26 ++++++++++++++++ 7 files changed, 140 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/method-call-lifetime-args-lint.rs create mode 100644 src/test/ui/method-call-lifetime-args-lint.stderr create mode 100644 src/test/ui/method-call-lifetime-args.rs create mode 100644 src/test/ui/method-call-lifetime-args.stderr diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 1fee0dd98634..2a11b19f8556 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -719,7 +719,7 @@ pub struct Generics { pub type_param_to_index: BTreeMap, pub has_self: bool, - pub has_late_bound_regions: bool, + pub has_late_bound_regions: Option, } impl Generics { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index af11cacb247b..b086c427ba59 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -121,7 +121,7 @@ use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::symbol::{Symbol, InternedString, keywords}; use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::{self, BytePos, Span}; +use syntax_pos::{self, BytePos, Span, MultiSpan}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -4689,20 +4689,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Prohibit explicit lifetime arguments if late bound lifetime parameters are present. let has_late_bound_lifetime_defs = - segment.map_or(false, |(_, generics)| generics.has_late_bound_regions); - if has_late_bound_lifetime_defs && !lifetimes.is_empty() { + segment.map_or(None, |(_, generics)| generics.has_late_bound_regions); + if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) { // Report this as a lint only if no error was reported previously. + let primary_msg = "cannot specify lifetime arguments explicitly \ + if late bound lifetime parameters are present"; + let note_msg = "the late bound lifetime parameter is introduced here"; if !is_method_call && (lifetimes.len() > lifetime_defs.len() || lifetimes.len() < required_len && !infer_lifetimes) { - self.tcx.sess.span_err(lifetimes[0].span, - "cannot specify lifetime arguments explicitly \ - if late bound lifetime parameters are present"); + let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg); + err.span_note(span_late, note_msg); + err.emit(); *segment = None; } else { + let mut multispan = MultiSpan::from_span(lifetimes[0].span); + multispan.push_span_label(span_late, note_msg.to_string()); self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, - lifetimes[0].id, lifetimes[0].span, - format!("cannot specify lifetime arguments explicitly \ - if late bound lifetime parameters are present")); + lifetimes[0].id, multispan, primary_msg.to_string()); } return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 72bd084330dd..143079b0a082 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -774,11 +774,11 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node: hir_map::Node<'tcx>) - -> bool { + -> Option { struct LateBoundRegionsDetector<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, binder_depth: u32, - has_late_bound_regions: bool, + has_late_bound_regions: Option, } impl<'a, 'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'a, 'tcx> { @@ -787,7 +787,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if self.has_late_bound_regions { return } + if self.has_late_bound_regions.is_some() { return } match ty.node { hir::TyBareFn(..) => { self.binder_depth += 1; @@ -801,21 +801,21 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef, m: hir::TraitBoundModifier) { - if self.has_late_bound_regions { return } + if self.has_late_bound_regions.is_some() { return } self.binder_depth += 1; intravisit::walk_poly_trait_ref(self, tr, m); self.binder_depth -= 1; } fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { - if self.has_late_bound_regions { return } + if self.has_late_bound_regions.is_some() { return } match self.tcx.named_region_map.defs.get(<.id).cloned() { Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {} Some(rl::Region::LateBound(debruijn, _)) | Some(rl::Region::LateBoundAnon(debruijn, _)) if debruijn.depth < self.binder_depth => {} - _ => self.has_late_bound_regions = true, + _ => self.has_late_bound_regions = Some(lt.span), } } } @@ -823,13 +823,13 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, generics: &'tcx hir::Generics, decl: &'tcx hir::FnDecl) - -> bool { + -> Option { let mut visitor = LateBoundRegionsDetector { - tcx, binder_depth: 1, has_late_bound_regions: false + tcx, binder_depth: 1, has_late_bound_regions: None }; for lifetime in &generics.lifetimes { if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) { - return true; + return Some(lifetime.lifetime.span); } } visitor.visit_fn_decl(decl); @@ -840,24 +840,24 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_map::NodeTraitItem(item) => match item.node { hir::TraitItemKind::Method(ref sig, _) => has_late_bound_regions(tcx, &sig.generics, &sig.decl), - _ => false, + _ => None, }, hir_map::NodeImplItem(item) => match item.node { hir::ImplItemKind::Method(ref sig, _) => has_late_bound_regions(tcx, &sig.generics, &sig.decl), - _ => false, + _ => None, }, hir_map::NodeForeignItem(item) => match item.node { hir::ForeignItemFn(ref fn_decl, _, ref generics) => has_late_bound_regions(tcx, generics, fn_decl), - _ => false, + _ => None, }, hir_map::NodeItem(item) => match item.node { hir::ItemFn(ref fn_decl, .., ref generics, _) => has_late_bound_regions(tcx, generics, fn_decl), - _ => false, + _ => None, }, - _ => false + _ => None } } diff --git a/src/test/ui/method-call-lifetime-args-lint.rs b/src/test/ui/method-call-lifetime-args-lint.rs new file mode 100644 index 000000000000..f9a4f712e571 --- /dev/null +++ b/src/test/ui/method-call-lifetime-args-lint.rs @@ -0,0 +1,31 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(late_bound_lifetime_arguments)] +#![allow(unused)] + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} +} + +fn method_call() { + S.late::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S.late_implicit::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/method-call-lifetime-args-lint.stderr b/src/test/ui/method-call-lifetime-args-lint.stderr new file mode 100644 index 000000000000..e319b54aa2ca --- /dev/null +++ b/src/test/ui/method-call-lifetime-args-lint.stderr @@ -0,0 +1,31 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint.rs:22:14 + | +17 | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +22 | S.late::<'static>(&0, &0); + | ^^^^^^^ + | +note: lint level defined here + --> $DIR/method-call-lifetime-args-lint.rs:11:9 + | +11 | #![deny(late_bound_lifetime_arguments)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint.rs:26:23 + | +18 | fn late_implicit(self, _: &u8, _: &u8) {} + | - the late bound lifetime parameter is introduced here +... +26 | S.late_implicit::<'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/method-call-lifetime-args.rs b/src/test/ui/method-call-lifetime-args.rs new file mode 100644 index 000000000000..7ce3ebb8beec --- /dev/null +++ b/src/test/ui/method-call-lifetime-args.rs @@ -0,0 +1,25 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} +} + +fn ufcs() { + S::late::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly +} + +fn main() {} diff --git a/src/test/ui/method-call-lifetime-args.stderr b/src/test/ui/method-call-lifetime-args.stderr new file mode 100644 index 000000000000..a6c1b8efe279 --- /dev/null +++ b/src/test/ui/method-call-lifetime-args.stderr @@ -0,0 +1,26 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args.rs:19:15 + | +19 | S::late::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args.rs:14:13 + | +14 | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args.rs:21:24 + | +21 | S::late_implicit::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args.rs:15:31 + | +15 | fn late_implicit(self, _: &u8, _: &u8) {} + | ^ + +error: aborting due to 2 previous errors + From 22f36dbbacf4f8bb65b3d4cd546faf946c4e8a77 Mon Sep 17 00:00:00 2001 From: Milton Mazzarri Date: Sun, 2 Jul 2017 23:32:42 -0500 Subject: [PATCH 7/8] bootstrap: Major refactoring This commit includes the following: * Fix syntax errors in Python 3 * Include more docstrings in classes, methods, and functions * Include unit tests using `unittest` * Merge implementation of `{rustc,cargo}_out_of_date` * Merge implementation of `RustBuild.{cargo,rustc}` * Remove unnecessary source code * Move all the attributes defined outside of `__init__` * Remove remaining `%s` from print function * Remove `WindowsError` reference on non-windows systems * Rename some variables to be more explicit avoid their meaning * Run bootstrap tests in the CI process * Remove non-pythonic getters * Remove duplicate code in `download_stage0` method * Reduce the number of branches in `build_bootstrap` method * Re-raise exception when we cannot execute uname in non-windows systems * Avoid long lines --- src/bootstrap/bootstrap.py | 506 +++++++++++++++++++------------- src/bootstrap/bootstrap_test.py | 114 +++++++ src/ci/run.sh | 6 + 3 files changed, 425 insertions(+), 201 deletions(-) create mode 100644 src/bootstrap/bootstrap_test.py diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ebc4c2fdf7bf..28bdc120a1e3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -37,12 +37,12 @@ def get(url, path, verbose=False): if os.path.exists(path): if verify(path, sha_path, False): if verbose: - print("using already-download file " + path) + print("using already-download file", path) return else: if verbose: - print("ignoring already-download file " + - path + " due to failed verification") + print("ignoring already-download file", + path, "due to failed verification") os.unlink(path) download(temp_path, url, True, verbose) if not verify(temp_path, sha_path, verbose): @@ -59,12 +59,12 @@ def delete_if_present(path, verbose): """Remove the given file if present""" if os.path.isfile(path): if verbose: - print("removing " + path) + print("removing", path) os.unlink(path) def download(path, url, probably_big, verbose): - for x in range(0, 4): + for _ in range(0, 4): try: _download(path, url, probably_big, verbose, True) return @@ -96,7 +96,7 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, sha_path, verbose): """Check if the sha256 sum of the given path is valid""" if verbose: - print("verifying " + path) + print("verifying", path) with open(path, "rb") as source: found = hashlib.sha256(source.read()).hexdigest() with open(sha_path, "r") as sha256sum: @@ -111,29 +111,30 @@ def verify(path, sha_path, verbose): def unpack(tarball, dst, verbose=False, match=None): """Unpack the given tarball file""" - print("extracting " + tarball) + print("extracting", tarball) fname = os.path.basename(tarball).replace(".tar.gz", "") with contextlib.closing(tarfile.open(tarball)) as tar: - for p in tar.getnames(): - if "/" not in p: + for member in tar.getnames(): + if "/" not in member: continue - name = p.replace(fname + "/", "", 1) + name = member.replace(fname + "/", "", 1) if match is not None and not name.startswith(match): continue name = name[len(match) + 1:] - fp = os.path.join(dst, name) + dst_path = os.path.join(dst, name) if verbose: - print(" extracting " + p) - tar.extract(p, dst) - tp = os.path.join(dst, p) - if os.path.isdir(tp) and os.path.exists(fp): + print(" extracting", member) + tar.extract(member, dst) + src_path = os.path.join(dst, member) + if os.path.isdir(src_path) and os.path.exists(dst_path): continue - shutil.move(tp, fp) + shutil.move(src_path, dst_path) shutil.rmtree(os.path.join(dst, fname)) def run(args, verbose=False, exception=False, **kwargs): + """Run a child program in a new process""" if verbose: print("running: " + ' '.join(args)) sys.stdout.flush() @@ -149,97 +150,118 @@ def run(args, verbose=False, exception=False, **kwargs): def stage0_data(rust_root): + """Build a dictionary from stage0.txt""" nightlies = os.path.join(rust_root, "src/stage0.txt") - data = {} with open(nightlies, 'r') as nightlies: - for line in nightlies: - line = line.rstrip() # Strip newline character, '\n' - if line.startswith("#") or line == '': - continue - a, b = line.split(": ", 1) - data[a] = b - return data + lines = [line.rstrip() for line in nightlies + if not line.startswith("#")] + return dict([line.split(": ", 1) for line in lines if line]) def format_build_time(duration): + """Return a nicer format for build time + + >>> format_build_time('300') + '0:05:00' + """ return str(datetime.timedelta(seconds=int(duration))) class RustBuild(object): + """Provide all the methods required to build Rust""" + def __init__(self): + self.cargo_channel = '' + self.date = '' + self._download_url = 'https://static.rust-lang.org' + self.rustc_channel = '' + self.build = '' + self.build_dir = os.path.join(os.getcwd(), "build") + self.clean = False + self.config_mk = '' + self.config_toml = '' + self.printed = False + self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + self.use_locked_deps = '' + self.use_vendored_sources = '' + self.verbose = False def download_stage0(self): - cache_dst = os.path.join(self.build_dir, "cache") - rustc_cache = os.path.join(cache_dst, self.stage0_date()) - if not os.path.exists(rustc_cache): - os.makedirs(rustc_cache) + """Fetch the build system for Rust, written in Rust + + This method will build a cache directory, then it will fetch the + tarball which has the stage0 compiler used to then bootstrap the Rust + compiler itself. - rustc_channel = self.stage0_rustc_channel() - cargo_channel = self.stage0_cargo_channel() + Each downloaded tarball is extracted, after that, the script + will move all the content to the right place. + """ + rustc_channel = self.rustc_channel + cargo_channel = self.cargo_channel if self.rustc().startswith(self.bin_root()) and \ - (not os.path.exists(self.rustc()) or self.rustc_out_of_date()): - self.print_what_it_means_to_bootstrap() + (not os.path.exists(self.rustc()) or + self.program_out_of_date(self.rustc_stamp())): + self.print_what_bootstrap_means() if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) filename = "rust-std-{}-{}.tar.gz".format( rustc_channel, self.build) - url = self._download_url + "/dist/" + self.stage0_date() - tarball = os.path.join(rustc_cache, filename) - if not os.path.exists(tarball): - get("{}/{}".format(url, filename), - tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), - match="rust-std-" + self.build, - verbose=self.verbose) + pattern = "rust-std-{}".format(self.build) + self._download_stage0_helper(filename, pattern) filename = "rustc-{}-{}.tar.gz".format(rustc_channel, self.build) - url = self._download_url + "/dist/" + self.stage0_date() - tarball = os.path.join(rustc_cache, filename) - if not os.path.exists(tarball): - get("{}/{}".format(url, filename), - tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), - match="rustc", verbose=self.verbose) - self.fix_executable(self.bin_root() + "/bin/rustc") - self.fix_executable(self.bin_root() + "/bin/rustdoc") - with open(self.rustc_stamp(), 'w') as f: - f.write(self.stage0_date()) + self._download_stage0_helper(filename, "rustc") + self.fix_executable("{}/bin/rustc".format(self.bin_root())) + self.fix_executable("{}/bin/rustdoc".format(self.bin_root())) + with open(self.rustc_stamp(), 'w') as rust_stamp: + rust_stamp.write(self.date) if "pc-windows-gnu" in self.build: filename = "rust-mingw-{}-{}.tar.gz".format( rustc_channel, self.build) - url = self._download_url + "/dist/" + self.stage0_date() - tarball = os.path.join(rustc_cache, filename) - if not os.path.exists(tarball): - get("{}/{}".format(url, filename), - tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), - match="rust-mingw", verbose=self.verbose) + self._download_stage0_helper(filename, "rust-mingw") if self.cargo().startswith(self.bin_root()) and \ - (not os.path.exists(self.cargo()) or self.cargo_out_of_date()): - self.print_what_it_means_to_bootstrap() + (not os.path.exists(self.cargo()) or + self.program_out_of_date(self.cargo_stamp())): + self.print_what_bootstrap_means() filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) - url = self._download_url + "/dist/" + self.stage0_date() - tarball = os.path.join(rustc_cache, filename) - if not os.path.exists(tarball): - get("{}/{}".format(url, filename), - tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), - match="cargo", verbose=self.verbose) - self.fix_executable(self.bin_root() + "/bin/cargo") - with open(self.cargo_stamp(), 'w') as f: - f.write(self.stage0_date()) - - def fix_executable(self, fname): - # If we're on NixOS we need to change the path to the dynamic loader + self._download_stage0_helper(filename, "cargo") + self.fix_executable("{}/bin/cargo".format(self.bin_root())) + with open(self.cargo_stamp(), 'w') as cargo_stamp: + cargo_stamp.write(self.date) + + def _download_stage0_helper(self, filename, pattern): + cache_dst = os.path.join(self.build_dir, "cache") + rustc_cache = os.path.join(cache_dst, self.date) + if not os.path.exists(rustc_cache): + os.makedirs(rustc_cache) + + url = "{}/dist/{}".format(self._download_url, self.date) + tarball = os.path.join(rustc_cache, filename) + if not os.path.exists(tarball): + get("{}/{}".format(url, filename), tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), match=pattern, verbose=self.verbose) + @staticmethod + def fix_executable(fname): + """Modifies the interpreter section of 'fname' to fix the dynamic linker + + This method is only required on NixOS and uses the PatchELF utility to + change the dynamic linker of ELF executables. + + Please see https://nixos.org/patchelf.html for more information + """ default_encoding = sys.getdefaultencoding() try: ostype = subprocess.check_output( ['uname', '-s']).strip().decode(default_encoding) - except (subprocess.CalledProcessError, WindowsError): + except subprocess.CalledProcessError: return + except OSError as reason: + if getattr(reason, 'winerror', None) is not None: + return + raise reason if ostype != "Linux": return @@ -257,8 +279,8 @@ def fix_executable(self, fname): interpreter = subprocess.check_output( ["patchelf", "--print-interpreter", fname]) interpreter = interpreter.strip().decode(default_encoding) - except subprocess.CalledProcessError as e: - print("warning: failed to call patchelf: %s" % e) + except subprocess.CalledProcessError as reason: + print("warning: failed to call patchelf:", reason) return loader = interpreter.split("/")[-1] @@ -267,8 +289,8 @@ def fix_executable(self, fname): ldd_output = subprocess.check_output( ['ldd', '/run/current-system/sw/bin/sh']) ldd_output = ldd_output.strip().decode(default_encoding) - except subprocess.CalledProcessError as e: - print("warning: unable to call ldd: %s" % e) + except subprocess.CalledProcessError as reason: + print("warning: unable to call ldd:", reason) return for line in ldd_output.splitlines(): @@ -285,45 +307,66 @@ def fix_executable(self, fname): try: subprocess.check_output( ["patchelf", "--set-interpreter", correct_interpreter, fname]) - except subprocess.CalledProcessError as e: - print("warning: failed to call patchelf: %s" % e) + except subprocess.CalledProcessError as reason: + print("warning: failed to call patchelf:", reason) return - def stage0_date(self): - return self._date - - def stage0_rustc_channel(self): - return self._rustc_channel - - def stage0_cargo_channel(self): - return self._cargo_channel - def rustc_stamp(self): - """Return the path for .rustc-stamp""" + """Return the path for .rustc-stamp + + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.rustc_stamp() == os.path.join("build", "stage0", ".rustc-stamp") + True + """ return os.path.join(self.bin_root(), '.rustc-stamp') def cargo_stamp(self): - """Return the path for .cargo-stamp""" - return os.path.join(self.bin_root(), '.cargo-stamp') + """Return the path for .cargo-stamp - def rustc_out_of_date(self): - """Check if rustc is out of date""" - if not os.path.exists(self.rustc_stamp()) or self.clean: - return True - with open(self.rustc_stamp(), 'r') as f: - return self.stage0_date() != f.read() + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.cargo_stamp() == os.path.join("build", "stage0", ".cargo-stamp") + True + """ + return os.path.join(self.bin_root(), '.cargo-stamp') - def cargo_out_of_date(self): - """Check if cargo is out of date""" - if not os.path.exists(self.cargo_stamp()) or self.clean: + def program_out_of_date(self, stamp_path): + """Check if the given program stamp is out of date""" + if not os.path.exists(stamp_path) or self.clean: return True - with open(self.cargo_stamp(), 'r') as f: - return self.stage0_date() != f.read() + with open(stamp_path, 'r') as stamp: + return self.date != stamp.read() def bin_root(self): + """Return the binary root directory + + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.bin_root() == os.path.join("build", "stage0") + True + + When the 'build' property is given should be a nested directory: + + >>> rb.build = "devel" + >>> rb.bin_root() == os.path.join("build", "devel", "stage0") + True + """ return os.path.join(self.build_dir, self.build, "stage0") def get_toml(self, key): + """Returns the value of the given key in config.toml, otherwise returns None + + >>> rb = RustBuild() + >>> rb.config_toml = 'key1 = "value1"\\nkey2 = "value2"' + >>> rb.get_toml("key2") + 'value2' + + If the key does not exists, the result is None: + + >>> rb.get_toml("key3") == None + True + """ for line in self.config_toml.splitlines(): match = re.match(r'^{}\s*=(.*)$'.format(key), line) if match is not None: @@ -332,6 +375,18 @@ def get_toml(self, key): return None def get_mk(self, key): + """Returns the value of the given key in config.mk, otherwise returns None + + >>> rb = RustBuild() + >>> rb.config_mk = 'key := value\\n' + >>> rb.get_mk('key') + 'value' + + If the key does not exists, the result is None: + + >>> rb.get_mk('does_not_exists') == None + True + """ for line in iter(self.config_mk.splitlines()): if line.startswith(key + ' '): var = line[line.find(':=') + 2:].strip() @@ -340,36 +395,64 @@ def get_mk(self, key): return None def cargo(self): - config = self.get_toml('cargo') - if config: - return config - config = self.get_mk('CFG_LOCAL_RUST_ROOT') - if config: - return config + '/bin/cargo' + self.exe_suffix() - return os.path.join(self.bin_root(), "bin/cargo" + self.exe_suffix()) + """Return config path for cargo""" + return self.program_config('cargo') def rustc(self): - config = self.get_toml('rustc') + """Return config path for rustc""" + return self.program_config('rustc') + + def program_config(self, program): + """Return config path for the given program + + >>> rb = RustBuild() + >>> rb.config_toml = 'rustc = "rustc"\\n' + >>> rb.config_mk = 'CFG_LOCAL_RUST_ROOT := /tmp/rust\\n' + >>> rb.program_config('rustc') + 'rustc' + >>> cargo_path = rb.program_config('cargo') + >>> cargo_path.rstrip(".exe") == os.path.join("/tmp/rust", + ... "bin", "cargo") + True + >>> rb.config_toml = '' + >>> rb.config_mk = '' + >>> cargo_path = rb.program_config('cargo') + >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(), + ... "bin", "cargo") + True + """ + config = self.get_toml(program) if config: return config config = self.get_mk('CFG_LOCAL_RUST_ROOT') if config: - return config + '/bin/rustc' + self.exe_suffix() - return os.path.join(self.bin_root(), "bin/rustc" + self.exe_suffix()) - - def get_string(self, line): + return os.path.join(config, "bin", "{}{}".format( + program, self.exe_suffix())) + return os.path.join(self.bin_root(), "bin", "{}{}".format( + program, self.exe_suffix())) + + @staticmethod + def get_string(line): + """Return the value between double quotes + + >>> RustBuild.get_string(' "devel" ') + 'devel' + """ start = line.find('"') if start == -1: return None end = start + 1 + line[start + 1:].find('"') return line[start + 1:end] - def exe_suffix(self): + @staticmethod + def exe_suffix(): + """Return a suffix for executables""" if sys.platform == 'win32': return '.exe' return '' - def print_what_it_means_to_bootstrap(self): + def print_what_bootstrap_means(self): + """Prints more information about the build system""" if hasattr(self, 'printed'): return self.printed = True @@ -386,10 +469,19 @@ def print_what_it_means_to_bootstrap(self): print(' src/bootstrap/README.md before the download finishes') def bootstrap_binary(self): - return os.path.join(self.build_dir, "bootstrap/debug/bootstrap") + """Return the path of the boostrap binary + + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.bootstrap_binary() == os.path.join("build", "bootstrap", + ... "debug", "bootstrap") + True + """ + return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap") def build_bootstrap(self): - self.print_what_it_means_to_bootstrap() + """Build bootstrap""" + self.print_what_bootstrap_means() build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -409,7 +501,8 @@ def build_bootstrap(self): env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): - raise Exception("no cargo executable found at `%s`" % self.cargo()) + raise Exception("no cargo executable found at `{}`".format( + self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] if self.verbose: @@ -423,6 +516,7 @@ def build_bootstrap(self): run(args, env=env, verbose=self.verbose) def build_triple(self): + """Build triple as in LLVM""" default_encoding = sys.getdefaultencoding() config = self.get_toml('build') if config: @@ -445,23 +539,26 @@ def build_triple(self): # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. - if ostype == 'Linux': + ostype_mapper = { + 'Bitrig': 'unknown-bitrig', + 'Darwin': 'apple-darwin', + 'DragonFly': 'unknown-dragonfly', + 'FreeBSD': 'unknown-freebsd', + 'Haiku': 'unknown-haiku', + 'NetBSD': 'unknown-netbsd', + 'OpenBSD': 'unknown-openbsd' + } + + # Consider the direct transformation first and then the special cases + if ostype in ostype_mapper: + ostype = ostype_mapper[ostype] + elif ostype == 'Linux': os_from_sp = subprocess.check_output( ['uname', '-o']).strip().decode(default_encoding) if os_from_sp == 'Android': ostype = 'linux-android' else: ostype = 'unknown-linux-gnu' - elif ostype == 'FreeBSD': - ostype = 'unknown-freebsd' - elif ostype == 'DragonFly': - ostype = 'unknown-dragonfly' - elif ostype == 'Bitrig': - ostype = 'unknown-bitrig' - elif ostype == 'OpenBSD': - ostype = 'unknown-openbsd' - elif ostype == 'NetBSD': - ostype = 'unknown-netbsd' elif ostype == 'SunOS': ostype = 'sun-solaris' # On Solaris, uname -m will return a machine classification instead @@ -477,10 +574,6 @@ def build_triple(self): if self.verbose: raise Exception(err) sys.exit(err) - elif ostype == 'Darwin': - ostype = 'apple-darwin' - elif ostype == 'Haiku': - ostype = 'unknown-haiku' elif ostype.startswith('MINGW'): # msys' `uname` does not print gcc configuration, but prints msys # configuration. so we cannot believe `uname -m`: @@ -499,13 +592,36 @@ def build_triple(self): cputype = 'x86_64' ostype = 'pc-windows-gnu' else: - err = "unknown OS type: " + ostype + err = "unknown OS type: {}".format(ostype) if self.verbose: raise ValueError(err) sys.exit(err) - if cputype in {'i386', 'i486', 'i686', 'i786', 'x86'}: - cputype = 'i686' + cputype_mapper = { + 'BePC': 'i686', + 'aarch64': 'aarch64', + 'amd64': 'x86_64', + 'arm64': 'aarch64', + 'i386': 'i686', + 'i486': 'i686', + 'i686': 'i686', + 'i786': 'i686', + 'powerpc': 'powerpc', + 'powerpc64': 'powerpc64', + 'powerpc64le': 'powerpc64le', + 'ppc': 'powerpc', + 'ppc64': 'powerpc64', + 'ppc64le': 'powerpc64le', + 's390x': 's390x', + 'x64': 'x86_64', + 'x86': 'i686', + 'x86-64': 'x86_64', + 'x86_64': 'x86_64' + } + + # Consider the direct transformation first and then the special cases + if cputype in cputype_mapper: + cputype = cputype_mapper[cputype] elif cputype in {'xscale', 'arm'}: cputype = 'arm' if ostype == 'linux-android': @@ -522,40 +638,26 @@ def build_triple(self): ostype = 'linux-androideabi' else: ostype += 'eabihf' - elif cputype in {'aarch64', 'arm64'}: - cputype = 'aarch64' elif cputype == 'mips': if sys.byteorder == 'big': cputype = 'mips' elif sys.byteorder == 'little': cputype = 'mipsel' else: - raise ValueError('unknown byteorder: ' + sys.byteorder) + raise ValueError("unknown byteorder: {}".format(sys.byteorder)) elif cputype == 'mips64': if sys.byteorder == 'big': cputype = 'mips64' elif sys.byteorder == 'little': cputype = 'mips64el' else: - raise ValueError('unknown byteorder: ' + sys.byteorder) + raise ValueError('unknown byteorder: {}'.format(sys.byteorder)) # only the n64 ABI is supported, indicate it ostype += 'abi64' - elif cputype in {'powerpc', 'ppc'}: - cputype = 'powerpc' - elif cputype in {'powerpc64', 'ppc64'}: - cputype = 'powerpc64' - elif cputype in {'powerpc64le', 'ppc64le'}: - cputype = 'powerpc64le' elif cputype == 'sparcv9': pass - elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}: - cputype = 'x86_64' - elif cputype == 's390x': - cputype = 's390x' - elif cputype == 'BePC': - cputype = 'i686' else: - err = "unknown cpu type: " + cputype + err = "unknown cpu type: {}".format(cputype) if self.verbose: raise ValueError(err) sys.exit(err) @@ -563,6 +665,7 @@ def build_triple(self): return "{}-{}".format(cputype, ostype) def update_submodules(self): + """Update submodules""" if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ self.get_toml('submodules') == "false" or \ self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1": @@ -592,8 +695,13 @@ def update_submodules(self): "clean", "-qdfx"], cwd=self.rust_root, verbose=self.verbose) + def set_dev_environment(self): + """Set download URL for development environment""" + self._download_url = 'https://dev-static.rust-lang.org' + def bootstrap(): + """Configure, fetch, build and run the initial bootstrap""" parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') parser.add_argument('--clean', action='store_true') @@ -603,107 +711,103 @@ def bootstrap(): args, _ = parser.parse_known_args(args) # Configure initial bootstrap - rb = RustBuild() - rb.config_toml = '' - rb.config_mk = '' - rb.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) - rb.build_dir = os.path.join(os.getcwd(), "build") - rb.verbose = args.verbose - rb.clean = args.clean + build = RustBuild() + build.verbose = args.verbose + build.clean = args.clean try: with open(args.config or 'config.toml') as config: - rb.config_toml = config.read() + build.config_toml = config.read() except: pass try: - rb.config_mk = open('config.mk').read() + build.config_mk = open('config.mk').read() except: pass - if '\nverbose = 2' in rb.config_toml: - rb.verbose = 2 - elif '\nverbose = 1' in rb.config_toml: - rb.verbose = 1 + if '\nverbose = 2' in build.config_toml: + build.verbose = 2 + elif '\nverbose = 1' in build.config_toml: + build.verbose = 1 - rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \ - 'CFG_ENABLE_VENDOR' in rb.config_mk + build.use_vendored_sources = '\nvendor = true' in build.config_toml or \ + 'CFG_ENABLE_VENDOR' in build.config_mk - rb.use_locked_deps = '\nlocked-deps = true' in rb.config_toml or \ - 'CFG_ENABLE_LOCKED_DEPS' in rb.config_mk + build.use_locked_deps = '\nlocked-deps = true' in build.config_toml or \ + 'CFG_ENABLE_LOCKED_DEPS' in build.config_mk - if 'SUDO_USER' in os.environ and not rb.use_vendored_sources: + if 'SUDO_USER' in os.environ and not build.use_vendored_sources: if os.environ.get('USER') != os.environ['SUDO_USER']: - rb.use_vendored_sources = True + build.use_vendored_sources = True print('info: looks like you are running this command under `sudo`') print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') print(' before running a command like `sudo make install`') - if rb.use_vendored_sources: + if build.use_vendored_sources: if not os.path.exists('.cargo'): os.makedirs('.cargo') - with open('.cargo/config', 'w') as f: - f.write(""" + with open('.cargo/config', 'w') as cargo_config: + cargo_config.write(""" [source.crates-io] replace-with = 'vendored-sources' registry = 'https://example.com' [source.vendored-sources] directory = '{}/src/vendor' - """.format(rb.rust_root)) + """.format(build.rust_root)) else: if os.path.exists('.cargo'): shutil.rmtree('.cargo') - data = stage0_data(rb.rust_root) - rb._date = data['date'] - rb._rustc_channel = data['rustc'] - rb._cargo_channel = data['cargo'] + data = stage0_data(build.rust_root) + build.date = data['date'] + build.rustc_channel = data['rustc'] + build.cargo_channel = data['cargo'] + if 'dev' in data: - rb._download_url = 'https://dev-static.rust-lang.org' - else: - rb._download_url = 'https://static.rust-lang.org' + build.set_dev_environment() - rb.update_submodules() + build.update_submodules() # Fetch/build the bootstrap - rb.build = rb.build_triple() - rb.download_stage0() + build.build = build.build_triple() + build.download_stage0() sys.stdout.flush() - rb.build_bootstrap() + build.build_bootstrap() sys.stdout.flush() # Run the bootstrap - args = [rb.bootstrap_binary()] + args = [build.bootstrap_binary()] args.extend(sys.argv[1:]) env = os.environ.copy() - env["BUILD"] = rb.build - env["SRC"] = rb.rust_root + env["BUILD"] = build.build + env["SRC"] = build.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable - run(args, env=env, verbose=rb.verbose) + run(args, env=env, verbose=build.verbose) def main(): + """Entry point for the bootstrap process""" start_time = time() help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: bootstrap() if not help_triggered: - print("Build completed successfully in %s" % - format_build_time(time() - start_time)) - except (SystemExit, KeyboardInterrupt) as e: - if hasattr(e, 'code') and isinstance(e.code, int): - exit_code = e.code + print("Build completed successfully in {}".format( + format_build_time(time() - start_time))) + except (SystemExit, KeyboardInterrupt) as error: + if hasattr(error, 'code') and isinstance(error.code, int): + exit_code = error.code else: exit_code = 1 - print(e) + print(error) if not help_triggered: - print("Build completed unsuccessfully in %s" % - format_build_time(time() - start_time)) + print("Build completed unsuccessfully in {}".format( + format_build_time(time() - start_time))) sys.exit(exit_code) diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py new file mode 100644 index 000000000000..a65a3a4042ec --- /dev/null +++ b/src/bootstrap/bootstrap_test.py @@ -0,0 +1,114 @@ +# Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +"""Bootstrap tests""" + +import os +import doctest +import unittest +import tempfile +import hashlib + +from shutil import rmtree + +import bootstrap + + +class Stage0DataTestCase(unittest.TestCase): + """Test Case for stage0_data""" + def setUp(self): + self.rust_root = tempfile.mkdtemp() + os.mkdir(os.path.join(self.rust_root, "src")) + with open(os.path.join(self.rust_root, "src", + "stage0.txt"), "w") as stage0: + stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta") + + def tearDown(self): + rmtree(self.rust_root) + + def test_stage0_data(self): + """Extract data from stage0.txt""" + expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta"} + data = bootstrap.stage0_data(self.rust_root) + self.assertDictEqual(data, expected) + + +class VerifyTestCase(unittest.TestCase): + """Test Case for verify""" + def setUp(self): + self.container = tempfile.mkdtemp() + self.src = os.path.join(self.container, "src.txt") + self.sums = os.path.join(self.container, "sums") + self.bad_src = os.path.join(self.container, "bad.txt") + content = "Hello world" + + with open(self.src, "w") as src: + src.write(content) + with open(self.sums, "w") as sums: + sums.write(hashlib.sha256(content.encode("utf-8")).hexdigest()) + with open(self.bad_src, "w") as bad: + bad.write("Hello!") + + def tearDown(self): + rmtree(self.container) + + def test_valid_file(self): + """Check if the sha256 sum of the given file is valid""" + self.assertTrue(bootstrap.verify(self.src, self.sums, False)) + + def test_invalid_file(self): + """Should verify that the file is invalid""" + self.assertFalse(bootstrap.verify(self.bad_src, self.sums, False)) + + +class ProgramOutOfDate(unittest.TestCase): + """Test if a program is out of date""" + def setUp(self): + self.container = tempfile.mkdtemp() + os.mkdir(os.path.join(self.container, "stage0")) + self.build = bootstrap.RustBuild() + self.build.date = "2017-06-15" + self.build.build_dir = self.container + self.rustc_stamp_path = os.path.join(self.container, "stage0", + ".rustc-stamp") + + def tearDown(self): + rmtree(self.container) + + def test_stamp_path_does_not_exists(self): + """Return True when the stamp file does not exists""" + if os.path.exists(self.rustc_stamp_path): + os.unlink(self.rustc_stamp_path) + self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path)) + + def test_dates_are_different(self): + """Return True when the dates are different""" + with open(self.rustc_stamp_path, "w") as rustc_stamp: + rustc_stamp.write("2017-06-14") + self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path)) + + def test_same_dates(self): + """Return False both dates match""" + with open(self.rustc_stamp_path, "w") as rustc_stamp: + rustc_stamp.write("2017-06-15") + self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path)) + + +if __name__ == '__main__': + SUITE = unittest.TestSuite() + TEST_LOADER = unittest.TestLoader() + SUITE.addTest(doctest.DocTestSuite(bootstrap)) + SUITE.addTests([ + TEST_LOADER.loadTestsFromTestCase(Stage0DataTestCase), + TEST_LOADER.loadTestsFromTestCase(VerifyTestCase), + TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)]) + + RUNNER = unittest.TextTestRunner(verbosity=2) + RUNNER.run(SUITE) diff --git a/src/ci/run.sh b/src/ci/run.sh index 549e804603c0..0531c961f256 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -74,6 +74,12 @@ retry make prepare travis_fold end make-prepare travis_time_finish +travis_fold start bootstrap-test +travis_time_start +python $SRC/src/bootstrap/bootstrap_test.py +travis_fold end bootstrap-test +travis_time_finish + if [ "$TRAVIS_OS_NAME" = "osx" ]; then ncpus=$(sysctl -n hw.ncpu) else From b77ff24060cb8e82a5bf469054b94e5e555f04d9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 18 Jul 2017 23:26:55 +0200 Subject: [PATCH 8/8] Update Cargo to ffab51954ec32d55631c37a8730bb24915fc090b https://github.com/rust-lang/cargo/pull/4123 added the [patch] section of the manifest --- src/Cargo.lock | 36 ++++++++++++++++++++++++++++++++++++ src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3c8d1164863d..04a556705b5a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -192,6 +192,7 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -463,6 +464,11 @@ dependencies = [ name = "fmt_macros" version = "0.0.0" +[[package]] +name = "fnv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "foreign-types" version = "0.2.0" @@ -517,6 +523,18 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "globset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "goto_def" version = "0.1.0" @@ -571,6 +589,21 @@ dependencies = [ "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ignore" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "installer" version = "0.0.0" @@ -2078,6 +2111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" +"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866" "checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" @@ -2085,10 +2119,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feeb1b6840809ef5efcf7a4a990bc4e1b7ee3df8cf9e2379a75aeb2ba42ac9c3" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" "checksum handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbba80e74e9591a5f6a4ffff6b7f9d645759a896e431cfbdc853e9184370294a" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" +"checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/src/tools/cargo b/src/tools/cargo index f709c35a3568..ffab51954ec3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit f709c35a35687b2665eb290695825375be91410b +Subproject commit ffab51954ec32d55631c37a8730bb24915fc090b diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8b7da2267cde..f572ad9cd020 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -18,6 +18,7 @@ static LICENSES: &'static [&'static str] = &[ "MIT/Apache-2.0", "MIT / Apache-2.0", "Apache-2.0/MIT", + "Apache-2.0 / MIT", "MIT OR Apache-2.0", "MIT", "Unlicense/MIT",