]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-installer/src/combiner.rs
New upstream version 1.24.1+dfsg1
[rustc.git] / src / tools / rust-installer / src / combiner.rs
CommitLineData
22607d1e
XL
1// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use std::io::{Read, Write};
12use std::path::Path;
13use flate2::read::GzDecoder;
14use tar::Archive;
15
16use errors::*;
17use super::Scripter;
18use super::Tarballer;
19use util::*;
20
21actor!{
22 #[derive(Debug)]
23 pub struct Combiner {
24 /// The name of the product, for display
25 product_name: String = "Product",
26
27 /// The name of the package, tarball
28 package_name: String = "package",
29
30 /// The directory under lib/ where the manifest lives
31 rel_manifest_dir: String = "packagelib",
32
33 /// The string to print after successful installation
34 success_message: String = "Installed.",
35
36 /// Places to look for legacy manifests to uninstall
37 legacy_manifest_dirs: String = "",
38
39 /// Installers to combine
40 input_tarballs: String = "",
41
42 /// Directory containing files that should not be installed
43 non_installed_overlay: String = "",
44
45 /// The directory to do temporary work
46 work_dir: String = "./workdir",
47
48 /// The location to put the final image and tarball
49 output_dir: String = "./dist",
50 }
51}
52
53impl Combiner {
54 /// Combine the installer tarballs
55 pub fn run(self) -> Result<()> {
56 create_dir_all(&self.work_dir)?;
57
58 let package_dir = Path::new(&self.work_dir).join(&self.package_name);
59 if package_dir.exists() {
60 remove_dir_all(&package_dir)?;
61 }
62 create_dir_all(&package_dir)?;
63
64 // Merge each installer into the work directory of the new installer
65 let components = create_new_file(package_dir.join("components"))?;
66 for input_tarball in self.input_tarballs.split(',').map(str::trim).filter(|s| !s.is_empty()) {
67 // Extract the input tarballs
ff7c6d11
XL
68 let tar = GzDecoder::new(open_file(&input_tarball)?);
69 Archive::new(tar).unpack(&self.work_dir)
22607d1e
XL
70 .chain_err(|| format!("unable to extract '{}' into '{}'",
71 &input_tarball, self.work_dir))?;
72
73 let pkg_name = input_tarball.trim_right_matches(".tar.gz");
74 let pkg_name = Path::new(pkg_name).file_name().unwrap();
75 let pkg_dir = Path::new(&self.work_dir).join(&pkg_name);
76
77 // Verify the version number
78 let mut version = String::new();
79 open_file(pkg_dir.join("rust-installer-version"))
80 .and_then(|mut file| file.read_to_string(&mut version).map_err(Error::from))
81 .chain_err(|| format!("failed to read version in '{}'", input_tarball))?;
82 if version.trim().parse() != Ok(::RUST_INSTALLER_VERSION) {
83 bail!("incorrect installer version in {}", input_tarball);
84 }
85
86 // Copy components to the new combined installer
87 let mut pkg_components = String::new();
88 open_file(pkg_dir.join("components"))
89 .and_then(|mut file| file.read_to_string(&mut pkg_components).map_err(Error::from))
90 .chain_err(|| format!("failed to read components in '{}'", input_tarball))?;
91 for component in pkg_components.split_whitespace() {
92 // All we need to do is copy the component directory. We could
93 // move it, but rustbuild wants to reuse the unpacked package
94 // dir for OS-specific installers on macOS and Windows.
95 let component_dir = package_dir.join(&component);
96 create_dir(&component_dir)?;
97 copy_recursive(&pkg_dir.join(&component), &component_dir)?;
98
99 // Merge the component name
100 writeln!(&components, "{}", component)
101 .chain_err(|| "failed to write new components")?;
102 }
103 }
104 drop(components);
105
106 // Write the installer version
107 let version = package_dir.join("rust-installer-version");
108 writeln!(create_new_file(version)?, "{}", ::RUST_INSTALLER_VERSION)
109 .chain_err(|| "failed to write new installer version")?;
110
111 // Copy the overlay
112 if !self.non_installed_overlay.is_empty() {
113 copy_recursive(self.non_installed_overlay.as_ref(), &package_dir)?;
114 }
115
116 // Generate the install script
117 let output_script = package_dir.join("install.sh");
118 let mut scripter = Scripter::default();
119 scripter.product_name(self.product_name)
120 .rel_manifest_dir(self.rel_manifest_dir)
121 .success_message(self.success_message)
122 .legacy_manifest_dirs(self.legacy_manifest_dirs)
123 .output_script(path_to_str(&output_script)?);
124 scripter.run()?;
125
126 // Make the tarballs
127 create_dir_all(&self.output_dir)?;
128 let output = Path::new(&self.output_dir).join(&self.package_name);
129 let mut tarballer = Tarballer::default();
130 tarballer.work_dir(self.work_dir)
131 .input(self.package_name)
132 .output(path_to_str(&output)?);
133 tarballer.run()?;
134
135 Ok(())
136 }
137}