Skip to content

Commit 64fc213

Browse files
authored
Merge pull request #456 from GuillaumeGomez/clone-gcc
Add clone-gcc command
2 parents 2262073 + 6560fec commit 64fc213

File tree

6 files changed

+157
-36
lines changed

6 files changed

+157
-36
lines changed

build_system/src/clone_gcc.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use crate::config::ConfigInfo;
2+
use crate::utils::{git_clone, run_command_with_output};
3+
4+
use std::path::{Path, PathBuf};
5+
6+
fn show_usage() {
7+
println!(
8+
r#"
9+
`clone-gcc` command help:
10+
11+
--out-path : Location where the GCC repository will be cloned (default: `./gcc`)"#
12+
);
13+
ConfigInfo::show_usage();
14+
println!(" --help : Show this help");
15+
}
16+
17+
#[derive(Default)]
18+
struct Args {
19+
out_path: PathBuf,
20+
config_info: ConfigInfo,
21+
}
22+
23+
impl Args {
24+
fn new() -> Result<Option<Self>, String> {
25+
let mut command_args = Self::default();
26+
27+
let mut out_path = None;
28+
29+
// We skip binary name and the `clone-gcc` command.
30+
let mut args = std::env::args().skip(2);
31+
32+
while let Some(arg) = args.next() {
33+
match arg.as_str() {
34+
"--out-path" => match args.next() {
35+
Some(path) if !path.is_empty() => out_path = Some(path),
36+
_ => {
37+
return Err("Expected an argument after `--out-path`, found nothing".into())
38+
}
39+
},
40+
"--help" => {
41+
show_usage();
42+
return Ok(None);
43+
}
44+
arg => {
45+
if !command_args.config_info.parse_argument(arg, &mut args)? {
46+
return Err(format!("Unknown option {}", arg));
47+
}
48+
}
49+
}
50+
}
51+
command_args.out_path = match out_path {
52+
Some(p) => p.into(),
53+
None => PathBuf::from("./gcc"),
54+
};
55+
return Ok(Some(command_args));
56+
}
57+
}
58+
59+
pub fn run() -> Result<(), String> {
60+
let Some(args) = Args::new()? else {
61+
return Ok(());
62+
};
63+
64+
let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
65+
if result.ran_clone {
66+
let gcc_commit = args.config_info.get_gcc_commit()?;
67+
println!("Checking out GCC commit `{}`...", gcc_commit);
68+
run_command_with_output(
69+
&[&"git", &"checkout", &gcc_commit],
70+
Some(Path::new(&result.repo_dir)),
71+
)?;
72+
} else {
73+
println!(
74+
"There is already a GCC folder in `{}`, leaving things as is...",
75+
args.out_path.display()
76+
);
77+
}
78+
Ok(())
79+
}

build_system/src/config.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,7 @@ impl ConfigInfo {
192192
command
193193
}
194194

195-
fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
196-
let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
197-
195+
pub fn get_gcc_commit(&self) -> Result<String, String> {
198196
let commit_hash_file = self.compute_path("libgccjit.version");
199197
let content = fs::read_to_string(&commit_hash_file).map_err(|_| {
200198
format!(
@@ -212,7 +210,14 @@ impl ConfigInfo {
212210
commit,
213211
));
214212
}
215-
let output_dir = output_dir.join(commit);
213+
Ok(commit.to_string())
214+
}
215+
216+
fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
217+
let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
218+
let commit = self.get_gcc_commit()?;
219+
220+
let output_dir = output_dir.join(&commit);
216221
if !output_dir.is_dir() {
217222
std::fs::create_dir_all(&output_dir).map_err(|err| {
218223
format!(

build_system/src/main.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::process;
44
mod build;
55
mod cargo;
66
mod clean;
7+
mod clone_gcc;
78
mod config;
89
mod info;
910
mod prepare;
@@ -27,19 +28,21 @@ fn usage() {
2728
"\
2829
Available commands for build_system:
2930
30-
cargo : Run cargo command
31-
clean : Run clean command
32-
prepare : Run prepare command
33-
build : Run build command
34-
test : Run test command
35-
info: : Run info command
36-
--help : Show this message"
31+
cargo : Run cargo command
32+
clean : Run clean command
33+
prepare : Run prepare command
34+
build : Run build command
35+
test : Run test command
36+
info : Run info command
37+
clone-gcc : Run clone-gcc command
38+
--help : Show this message"
3739
);
3840
}
3941

4042
pub enum Command {
4143
Cargo,
4244
Clean,
45+
CloneGcc,
4346
Prepare,
4447
Build,
4548
Test,
@@ -58,6 +61,7 @@ fn main() {
5861
Some("build") => Command::Build,
5962
Some("test") => Command::Test,
6063
Some("info") => Command::Info,
64+
Some("clone-gcc") => Command::CloneGcc,
6165
Some("--help") => {
6266
usage();
6367
process::exit(0);
@@ -77,6 +81,7 @@ fn main() {
7781
Command::Build => build::run(),
7882
Command::Test => test::run(),
7983
Command::Info => info::run(),
84+
Command::CloneGcc => clone_gcc::run(),
8085
} {
8186
eprintln!("Command failed to run: {e}");
8287
process::exit(1);

build_system/src/prepare.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::rustc_info::get_rustc_path;
22
use crate::utils::{
3-
cargo_install, git_clone, remove_file, run_command, run_command_with_output, walk_dir,
3+
cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir,
44
};
55

66
use std::fs;
@@ -152,7 +152,7 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
152152
where
153153
F: Fn(&Path) -> Result<(), String>,
154154
{
155-
let clone_result = git_clone(repo_url, Some(&Path::new(crate::BUILD_DIR)), false)?;
155+
let clone_result = git_clone_root_dir(repo_url, &Path::new(crate::BUILD_DIR), false)?;
156156
if !clone_result.ran_clone {
157157
println!("`{}` has already been cloned", clone_result.repo_name);
158158
}

build_system/src/test.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::build;
22
use crate::config::{Channel, ConfigInfo};
33
use crate::utils::{
4-
get_toolchain, git_clone, remove_file, run_command, run_command_with_env,
4+
get_toolchain, git_clone, git_clone_root_dir, remove_file, run_command, run_command_with_env,
55
run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
66
};
77

@@ -487,15 +487,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
487487
);
488488
let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust");
489489
// If the repository was already cloned, command will fail, so doesn't matter.
490-
let _ = run_command_with_output_and_env(
491-
&[
492-
&"git",
493-
&"clone",
494-
&"https://github.com/rust-lang/rust.git",
495-
&rust_dir_path,
496-
],
497-
None,
498-
Some(env),
490+
let _ = git_clone(
491+
"https://github.com/rust-lang/rust.git",
492+
Some(&rust_dir_path),
493+
false,
499494
);
500495
let rust_dir: Option<&Path> = Some(&rust_dir_path);
501496
run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?;
@@ -720,7 +715,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
720715

721716
let run_tests = |projects_path, iter: &mut dyn Iterator<Item = &&str>| -> Result<(), String> {
722717
for project in iter {
723-
let clone_result = git_clone(project, Some(projects_path), true)?;
718+
let clone_result = git_clone_root_dir(project, projects_path, true)?;
724719
let repo_path = Path::new(&clone_result.repo_dir);
725720
run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?;
726721
run_cargo_command(&[&"test"], Some(repo_path), env, args)?;

build_system/src/utils.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::HashMap;
22
use std::ffi::OsStr;
33
use std::fmt::Debug;
44
use std::fs;
5-
use std::path::Path;
5+
use std::path::{Path, PathBuf};
66
use std::process::{Command, ExitStatus, Output};
77

88
fn get_command_inner(
@@ -254,20 +254,12 @@ pub struct CloneResult {
254254
pub repo_dir: String,
255255
}
256256

257-
pub fn git_clone(
257+
fn git_clone_inner(
258258
to_clone: &str,
259-
dest: Option<&Path>,
259+
dest: &Path,
260260
shallow_clone: bool,
261+
repo_name: String,
261262
) -> Result<CloneResult, String> {
262-
let repo_name = to_clone.split('/').last().unwrap();
263-
let repo_name = match repo_name.strip_suffix(".git") {
264-
Some(n) => n.to_string(),
265-
None => repo_name.to_string(),
266-
};
267-
268-
let dest = dest
269-
.map(|dest| dest.join(&repo_name))
270-
.unwrap_or_else(|| Path::new(&repo_name).into());
271263
if dest.is_dir() {
272264
return Ok(CloneResult {
273265
ran_clone: false,
@@ -289,6 +281,51 @@ pub fn git_clone(
289281
})
290282
}
291283

284+
fn get_repo_name(url: &str) -> String {
285+
let repo_name = url.split('/').last().unwrap();
286+
match repo_name.strip_suffix(".git") {
287+
Some(n) => n.to_string(),
288+
None => repo_name.to_string(),
289+
}
290+
}
291+
292+
pub fn git_clone(
293+
to_clone: &str,
294+
dest: Option<&Path>,
295+
shallow_clone: bool,
296+
) -> Result<CloneResult, String> {
297+
let repo_name = get_repo_name(to_clone);
298+
let tmp: PathBuf;
299+
300+
let dest = match dest {
301+
Some(dest) => dest,
302+
None => {
303+
tmp = repo_name.clone().into();
304+
&tmp
305+
}
306+
};
307+
git_clone_inner(to_clone, dest, shallow_clone, repo_name)
308+
}
309+
310+
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
311+
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
312+
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
313+
/// `a/b`.
314+
pub fn git_clone_root_dir(
315+
to_clone: &str,
316+
dest_parent_dir: &Path,
317+
shallow_clone: bool,
318+
) -> Result<CloneResult, String> {
319+
let repo_name = get_repo_name(to_clone);
320+
321+
git_clone_inner(
322+
to_clone,
323+
&dest_parent_dir.join(&repo_name),
324+
shallow_clone,
325+
repo_name,
326+
)
327+
}
328+
292329
pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
293330
where
294331
P: AsRef<Path>,

0 commit comments

Comments
 (0)