diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 512d4d8c5b792..71c1c61e3d97e 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -303,6 +303,19 @@ def default_build_triple(): return "{}-{}".format(cputype, ostype) +@contextlib.contextmanager +def output(filepath): + tmp = filepath + '.tmp' + with open(tmp, 'w') as f: + yield f + try: + os.remove(filepath) # PermissionError/OSError on Win32 if in use + os.rename(tmp, filepath) + except OSError: + shutil.copy2(tmp, filepath) + os.remove(tmp) + + class RustBuild(object): """Provide all the methods required to build Rust""" def __init__(self): @@ -346,7 +359,7 @@ def download_stage0(self): 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: + with output(self.rustc_stamp()) as rust_stamp: rust_stamp.write(self.date) # This is required so that we don't mix incompatible MinGW @@ -363,7 +376,7 @@ def download_stage0(self): filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) self._download_stage0_helper(filename, "cargo") self.fix_executable("{}/bin/cargo".format(self.bin_root())) - with open(self.cargo_stamp(), 'w') as cargo_stamp: + with output(self.cargo_stamp()) as cargo_stamp: cargo_stamp.write(self.date) def _download_stage0_helper(self, filename, pattern): @@ -776,7 +789,7 @@ def bootstrap(help_triggered): if build.use_vendored_sources: if not os.path.exists('.cargo'): os.makedirs('.cargo') - with open('.cargo/config', 'w') as cargo_config: + with output('.cargo/config') as cargo_config: cargo_config.write(""" [source.crates-io] replace-with = 'vendored-sources' diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 80fa96509bd87..9fdba044f4be3 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -432,7 +432,7 @@ def configure_section(lines, config): # order that we read it in. p("") p("writing `config.toml` in current directory") -with open('config.toml', 'w') as f: +with bootstrap.output('config.toml') as f: for section in section_order: if section == 'target': for target in targets: @@ -442,7 +442,7 @@ def configure_section(lines, config): for line in sections[section]: f.write(line + "\n") -with open('Makefile', 'w') as f: +with bootstrap.output('Makefile') as f: contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') contents = open(contents).read() contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/')