1
Fork 0

Move submodule initialization to bootstrap.py

This commit is contained in:
Tatsuyuki Ishi 2017-05-13 14:21:35 +09:00
parent e119a63901
commit 510d6b8afb
2 changed files with 37 additions and 121 deletions

View file

@ -14,6 +14,7 @@ import contextlib
import datetime
import hashlib
import os
import re
import shutil
import subprocess
import sys
@ -297,8 +298,10 @@ class RustBuild(object):
def get_toml(self, key):
for line in self.config_toml.splitlines():
if line.startswith(key + ' ='):
return self.get_string(line)
match = re.match(r'^{}\s*=(.*)$'.format(key), line)
if match is not None:
value = match.group(1)
return self.get_string(value) or value.strip()
return None
def get_mk(self, key):
@ -329,6 +332,8 @@ class RustBuild(object):
def get_string(self, line):
start = line.find('"')
if start == -1:
return None
end = start + 1 + line[start + 1:].find('"')
return line[start + 1:end]
@ -386,7 +391,7 @@ class RustBuild(object):
args.append("--frozen")
self.run(args, env)
def run(self, args, env):
def run(self, args, env=None):
proc = subprocess.Popen(args, env=env)
ret = proc.wait()
if ret != 0:
@ -529,6 +534,32 @@ class RustBuild(object):
return "{}-{}".format(cputype, ostype)
def update_submodules(self):
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":
return
print('Updating submodules')
self.run(["git", "-C", self.rust_root, "submodule", "-q", "sync"])
# FIXME: nobody does, but this won't work well with whitespace in
# submodule path
submodules = [s.split()[1] for s in subprocess.check_output(
["git", "config", "--file", os.path.join(
self.rust_root, ".gitmodules"), "--get-regexp", "path"]).splitlines()]
for module in submodules:
if module.endswith(b"llvm") and \
(self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT')):
continue
if module.endswith(b"jemalloc") and \
(self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')):
continue
self.run(["git", "-C", self.rust_root,
"submodule", "update", "--init", module])
self.run(["git", "-C", self.rust_root, "submodule", "-q",
"foreach", "git", "reset", "-q", "--hard"])
self.run(["git", "-C", self.rust_root, "submodule",
"-q", "foreach", "git", "clean", "-qdfx"])
def bootstrap():
parser = argparse.ArgumentParser(description='Build rust')
parser.add_argument('--config')
@ -597,6 +628,8 @@ def bootstrap():
else:
rb._download_url = 'https://static.rust-lang.org'
rb.update_submodules()
# Fetch/build the bootstrap
rb.build = rb.build_triple()
rb.download_stage0()

View file

@ -82,7 +82,7 @@ use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::Read;
use std::path::{Component, PathBuf, Path};
use std::path::{PathBuf, Path};
use std::process::Command;
use build_helper::{run_silent, run_suppressed, output, mtime};
@ -285,129 +285,12 @@ impl Build {
self.verbose(&format!("auto-detected local-rebuild {}", local_release));
self.local_rebuild = true;
}
self.verbose("updating submodules");
self.update_submodules();
self.verbose("learning about cargo");
metadata::build(self);
step::run(self);
}
/// Updates all git submodules that we have.
///
/// This will detect if any submodules are out of date an run the necessary
/// commands to sync them all with upstream.
fn update_submodules(&self) {
struct Submodule<'a> {
path: &'a Path,
state: State,
}
enum State {
// The submodule may have staged/unstaged changes
MaybeDirty,
// Or could be initialized but never updated
NotInitialized,
// The submodule, itself, has extra commits but those changes haven't been commited to
// the (outer) git repository
OutOfSync,
}
if !self.src_is_git || !self.config.submodules {
return
}
let git = || {
let mut cmd = Command::new("git");
cmd.current_dir(&self.src);
return cmd
};
let git_submodule = || {
let mut cmd = Command::new("git");
cmd.current_dir(&self.src).arg("submodule");
return cmd
};
// FIXME: this takes a seriously long time to execute on Windows and a
// nontrivial amount of time on Unix, we should have a better way
// of detecting whether we need to run all the submodule commands
// below.
let out = output(git_submodule().arg("status"));
let mut submodules = vec![];
for line in out.lines() {
// NOTE `git submodule status` output looks like this:
//
// -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
// +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
// e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
//
// The first character can be '-', '+' or ' ' and denotes the `State` of the submodule
// Right next to this character is the SHA-1 of the submodule HEAD
// And after that comes the path to the submodule
let path = Path::new(line[1..].split(' ').skip(1).next().unwrap());
let state = if line.starts_with('-') {
State::NotInitialized
} else if line.starts_with('+') {
State::OutOfSync
} else if line.starts_with(' ') {
State::MaybeDirty
} else {
panic!("unexpected git submodule state: {:?}", line.chars().next());
};
submodules.push(Submodule { path: path, state: state })
}
self.run(git_submodule().arg("sync"));
for submodule in submodules {
// If using llvm-root then don't touch the llvm submodule.
if submodule.path.components().any(|c| c == Component::Normal("llvm".as_ref())) &&
self.config.target_config.get(&self.config.build)
.and_then(|c| c.llvm_config.as_ref()).is_some()
{
continue
}
if submodule.path.components().any(|c| c == Component::Normal("jemalloc".as_ref())) &&
!self.config.use_jemalloc
{
continue
}
// `submodule.path` is the relative path to a submodule (from the repository root)
// `submodule_path` is the path to a submodule from the cwd
// use `submodule.path` when e.g. executing a submodule specific command from the
// repository root
// use `submodule_path` when e.g. executing a normal git command for the submodule
// (set via `current_dir`)
let submodule_path = self.src.join(submodule.path);
match submodule.state {
State::MaybeDirty => {
// drop staged changes
self.run(git().current_dir(&submodule_path)
.args(&["reset", "--hard"]));
// drops unstaged changes
self.run(git().current_dir(&submodule_path)
.args(&["clean", "-fdx"]));
},
State::NotInitialized => {
self.run(git_submodule().arg("init").arg(submodule.path));
self.run(git_submodule().arg("update").arg(submodule.path));
},
State::OutOfSync => {
// drops submodule commits that weren't reported to the (outer) git repository
self.run(git_submodule().arg("update").arg(submodule.path));
self.run(git().current_dir(&submodule_path)
.args(&["reset", "--hard"]));
self.run(git().current_dir(&submodule_path)
.args(&["clean", "-fdx"]));
},
}
}
}
/// Clear out `dir` if `input` is newer.
///
/// After this executes, it will also ensure that `dir` exists.