From e4c1b8a397f8c5b4e544db87ebfe76802439e44b Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Tue, 10 May 2022 13:20:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B0=81=E8=A3=85=20git=20cargo=20?= =?UTF-8?q?=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xtask/src/arch.rs | 33 ++++------ xtask/src/cargo.rs | 69 +++++++++++++++++++++ xtask/src/git.rs | 90 +++++++++++++++------------ xtask/src/main.rs | 148 +++++++++++++++++++++++---------------------- xtask/src/wget.rs | 16 +++-- 5 files changed, 217 insertions(+), 139 deletions(-) create mode 100644 xtask/src/cargo.rs diff --git a/xtask/src/arch.rs b/xtask/src/arch.rs index c7cceac8..5cd54911 100644 --- a/xtask/src/arch.rs +++ b/xtask/src/arch.rs @@ -1,5 +1,6 @@ -use super::{dir, git, wget::wget, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE}; -use clap::{Args, Subcommand}; +use crate::{ + cargo::Cargo, dir, git::Git, wget::wget, CommandExt, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE, +}; use dircpy::copy_dir; use std::{ ffi::OsStr, @@ -276,17 +277,13 @@ fn install_fs_fuse() { .map(|out| out.stdout.starts_with(b"rcore-fs-fuse")) { println!("Rcore-fs-fuse is already installed."); - return; - } - #[rustfmt::skip] - let install = Command::new("cargo") - .arg("install").arg("rcore-fs-fuse") - .arg("--git").arg("https://github.com/rcore-os/rcore-fs") - .arg("--rev").arg("1a3246b") - .arg("--force") - .status(); - if !install.unwrap().success() { - panic!("FAILED: install rcore-fs-fuse"); + } else { + Cargo::new("install") + .args(&["install", "rcore-fs-fuse"]) + .args(&["--git", "https://github.com/rcore-os/rcore-fs"]) + .args(&["--rev", "1a3246b"]) + .arg("--force") + .expect("FAILED: install rcore-fs-fuse"); } } @@ -296,16 +293,10 @@ fn clone_libc_test() { const URL: &str = "https://github.com/rcore-os/libc-test.git"; if Path::new(DIR).is_dir() { - let pull = git::pull().current_dir(DIR).status(); - if !pull.unwrap().success() { - panic!("FAILED: git pull"); - } + Git::pull().current_dir(DIR).expect("FAILED: git pull"); } else { dir::clear(DIR).unwrap(); - let clone = git::clone(URL, Some(DIR)).status(); - if !clone.unwrap().success() { - panic!("FAILED: git clone {URL}"); - } + Git::clone(URL, Some(DIR)).expect(&format!("FAILED: git clone {URL}")); } } diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs new file mode 100644 index 00000000..f775d5d2 --- /dev/null +++ b/xtask/src/cargo.rs @@ -0,0 +1,69 @@ +use crate::CommandExt; +use std::{ffi::OsStr, process::Command}; + +pub(crate) struct Cargo { + cmd: Command, +} + +impl AsMut for Cargo { + fn as_mut(&mut self) -> &mut Command { + &mut self.cmd + } +} + +impl CommandExt for Cargo {} + +impl Cargo { + pub fn new(sub: &(impl AsRef + ?Sized)) -> Self { + let mut git = Self { + cmd: Command::new("cargo"), + }; + git.arg(sub); + git + } + + pub fn update() -> Self { + Self::new("update") + } + + pub fn fmt() -> Self { + Self::new("fmt") + } + + pub fn clippy() -> Self { + Self::new("clippy") + } + + pub fn all_features(&mut self) -> &mut Self { + self.arg("--all-features"); + self + } + + pub fn features(&mut self, default: bool, feats: I) -> &mut Self + where + I: IntoIterator, + S: AsRef, + { + if !default { + self.arg("--no-default-features"); + } + + let mut iter = feats.into_iter(); + if let Some(feat) = iter.next() { + self.arg("--features"); + let mut feats = feat.as_ref().to_os_string(); + for feat in iter { + feats.push(" "); + feats.push(feat); + } + self.arg(feats); + } + + self + } + + pub fn target(&mut self, target: impl AsRef) -> &mut Self { + self.arg("--target").arg(target); + self + } +} diff --git a/xtask/src/git.rs b/xtask/src/git.rs index f5b20c67..68543e7d 100644 --- a/xtask/src/git.rs +++ b/xtask/src/git.rs @@ -1,51 +1,63 @@ //! 操作 git。 +use crate::CommandExt; use std::{ffi::OsStr, process::Command}; -fn git(sub: &(impl AsRef + ?Sized)) -> Command { - let mut cmd = Command::new("git"); - cmd.arg(sub); - cmd +pub(super) struct Git { + cmd: Command, } -/// git lfs ... -pub fn lfs() -> Command { - git("lfs") -} - -/// git config [[--global]] ... -pub fn config(global: bool) -> Command { - let mut cmd = git("config"); - if global { - cmd.arg("--global"); - }; - cmd -} - -/// git clone [[dir]] ... -pub fn clone( - repo: &(impl AsRef + ?Sized), - dir: Option<&(impl AsRef + ?Sized)>, -) -> Command { - let mut cmd = git("clone"); - cmd.arg(repo); - if let Some(dir) = dir { - cmd.arg(dir); +impl AsMut for Git { + fn as_mut(&mut self) -> &mut Command { + &mut self.cmd } - cmd } -/// git pull ... -pub fn pull() -> Command { - git("pull") -} +impl CommandExt for Git {} -/// git submodule update --init. -pub fn submodule_update(init: bool) -> Command { - let mut cmd = git("submodule"); - cmd.arg("update"); - if init { - cmd.arg("--init"); +impl Git { + fn new(sub: &(impl AsRef + ?Sized)) -> Self { + let mut git = Self { + cmd: Command::new("git"), + }; + git.arg(sub); + git + } + + pub fn lfs() -> Self { + Self::new("lfs") + } + + pub fn config(global: bool) -> Self { + let mut git = Self::new("config"); + if global { + git.arg("--global"); + }; + git + } + + pub fn clone( + repo: &(impl AsRef + ?Sized), + dir: Option<&(impl AsRef + ?Sized)>, + ) -> Self { + let mut git = Self::new("clone"); + git.arg(repo); + if let Some(dir) = dir { + git.arg(dir); + } + git + } + + pub fn pull() -> Self { + Self::new("pull") + } + + pub fn submodule_update(init: bool) -> Self { + let mut git = Self::new("submodule"); + git.arg("update"); + if init { + git.arg("--init"); + } + git } - cmd } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ceaef50e..04d1fb36 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,17 +1,23 @@ #![feature(path_file_prefix)] #![feature(exit_status_error)] -use clap::{Args, Parser, Subcommand}; +#[macro_use] +extern crate clap; + +use clap::Parser; use clap_verbosity_flag::Verbosity; -use std::{fs::read_to_string, net::Ipv4Addr, process::Command}; +use std::{ffi::OsStr, fs::read_to_string, net::Ipv4Addr, path::Path, process::Command}; mod arch; +mod cargo; mod dir; mod dump; mod git; mod wget; use arch::Arch; +use cargo::Cargo; +use git::Git; const ALPINE_WEBSITE: &str = "https://dl-cdn.alpinelinux.org/alpine/v3.12/releases"; const ALPINE_ROOTFS_VERSION: &str = "3.12.0"; @@ -106,34 +112,21 @@ fn main() { /// 初始化 LFS。 fn make_git_lfs() { - if !git::lfs() + if !Git::lfs() .arg("version") + .as_mut() .output() .map_or(false, |out| out.stdout.starts_with(b"git-lfs/")) { panic!("Cannot find git lfs, see https://git-lfs.github.com/ for help."); } - git::lfs() - .arg("install") - .status() - .unwrap() - .exit_ok() - .expect("FAILED: git lfs install"); - git::lfs() - .arg("pull") - .status() - .unwrap() - .exit_ok() - .expect("FAILED: git lfs pull"); + Git::lfs().arg("install").expect("FAILED: git lfs install"); + Git::lfs().arg("pull").expect("FAILED: git lfs pull"); } /// 更新子项目。 fn git_submodule_update(init: bool) { - git::submodule_update(init) - .status() - .unwrap() - .exit_ok() - .expect("FAILED: git submodule update --init"); + Git::submodule_update(init).expect("FAILED: git submodule update --init"); } /// 更新工具链和依赖。 @@ -145,12 +138,7 @@ fn update_all() { .unwrap() .exit_ok() .expect("FAILED: rustup update"); - Command::new("cargo") - .arg("update") - .status() - .unwrap() - .exit_ok() - .expect("FAILED: cargo update"); + Cargo::update().expect("FAILED: cargo update"); } /// 设置 git 代理。 @@ -164,73 +152,87 @@ fn set_git_proxy(global: bool, port: u16) { }) .expect("FAILED: detect DNS"); let proxy = format!("socks5://{dns}:{port}"); - #[rustfmt::skip] - git::config(global) - .arg("http.proxy").arg(&proxy) - .status().unwrap() - .exit_ok().expect("FAILED: git config --unset http.proxy"); - #[rustfmt::skip] - git::config(global) - .arg("https.proxy").arg(&proxy) - .status().unwrap() - .exit_ok().expect("FAILED: git config --unset https.proxy"); + Git::config(global) + .args(&["http.proxy", &proxy]) + .expect("FAILED: git config --unset http.proxy"); + Git::config(global) + .args(&["http.proxy", &proxy]) + .expect("FAILED: git config --unset https.proxy"); println!("git proxy = {proxy}"); } /// 移除 git 代理。 fn unset_git_proxy(global: bool) { - #[rustfmt::skip] - git::config(global) - .arg("--unset").arg("http.proxy") - .status().unwrap() - .exit_ok().expect("FAILED: git config --unset http.proxy"); - #[rustfmt::skip] - git::config(global) - .arg("--unset").arg("https.proxy") - .status().unwrap() - .exit_ok().expect("FAILED: git config --unset https.proxy"); + Git::config(global) + .args(&["--unset", "http.proxy"]) + .expect("FAILED: git config --unset http.proxy"); + Git::config(global) + .args(&["--unset", "https.proxy"]) + .expect("FAILED: git config --unset https.proxy"); println!("git proxy ="); } /// 风格检查。 fn check_style() { println!("fmt -----------------------------------------"); - #[rustfmt::skip] - Command::new("cargo").arg("fmt") + Cargo::fmt() .arg("--all") .arg("--") .arg("--check") - .status() - .unwrap(); + .expect("FAILED: cargo update"); println!("clippy --------------------------------------"); - #[rustfmt::skip] - Command::new("cargo").arg("clippy") - .arg("--all-features") - .status() - .unwrap(); + Cargo::clippy() + .all_features() + .expect("FAILED: cargo clippy"); println!("clippy x86_64 zircon smp=1 ------------------"); - #[rustfmt::skip] - Command::new("cargo").arg("clippy") - .arg("--no-default-features") - .arg("--features").arg("zircon") - .arg("--target").arg("x86_64.json") - .arg("-Z").arg("build-std=core,alloc") - .arg("-Z").arg("build-std-features=compiler-builtins-mem") + Cargo::clippy() + .features(false, &["zircon"]) + .target("x86_64.json") + .args(&["-Z", "build-std=core,alloc"]) + .args(&["-Z", "build-std-features=compiler-builtins-mem"]) .current_dir("zCore") .env("SMP", "1") - .status() - .unwrap(); + .expect(""); println!("clippy riscv64 linux smp=4 ------------------"); - #[rustfmt::skip] - Command::new("cargo").arg("clippy") - .arg("--no-default-features") - .arg("--features").arg("linux board-qemu") - .arg("--target").arg("riscv64.json") - .arg("-Z").arg("build-std=core,alloc") - .arg("-Z").arg("build-std-features=compiler-builtins-mem") + Cargo::clippy() + .features(false, &["linux", "board-qemu"]) + .target("riscv64.json") + .args(&["-Z", "build-std=core,alloc"]) + .args(&["-Z", "build-std-features=compiler-builtins-mem"]) .current_dir("zCore") .env("SMP", "4") .env("PLATFORM", "board-qemu") - .status() - .unwrap(); + .expect(""); +} + +trait CommandExt: AsMut { + fn arg(&mut self, s: impl AsRef) -> &mut Self { + self.as_mut().arg(s); + self + } + + fn args(&mut self, args: I) -> &mut Self + where + I: IntoIterator, + S: AsRef, + { + for arg in args { + self.arg(arg); + } + self + } + + fn current_dir(&mut self, dir: impl AsRef) -> &mut Self { + self.as_mut().current_dir(dir); + self + } + + fn env(&mut self, key: impl AsRef, val: impl AsRef) -> &mut Self { + self.as_mut().env(key, val); + self + } + + fn expect(&mut self, msg: &str) { + self.as_mut().status().unwrap().exit_ok().expect(msg); + } } diff --git a/xtask/src/wget.rs b/xtask/src/wget.rs index 4ac8f8a0..33bda7b4 100644 --- a/xtask/src/wget.rs +++ b/xtask/src/wget.rs @@ -1,4 +1,5 @@ -use std::{fs, path::Path, process::Command}; +use crate::dir; +use std::{fs, path::Path, process::Command}; pub fn wget(url: &str, dst: &(impl AsRef + ?Sized)) { let dst = dst.as_ref(); @@ -9,13 +10,16 @@ pub fn wget(url: &str, dst: &(impl AsRef + ?Sized)) { let temp: usize = rand::random(); let temp_name = format!("/tmp/{temp}"); let temp_name = Path::new(&temp_name); - Command::new("wget") + let res = Command::new("wget") .arg(url) .arg("-O") .arg(temp_name) .status() - .unwrap() - .exit_ok() - .expect("FAILED: wget {url}"); - fs::rename(temp_name, dst).unwrap(); + .unwrap(); + if res.success() { + fs::rename(temp_name, dst).unwrap(); + } else { + dir::rm(dst).unwrap(); + panic!("FAILED: wget {url}"); + } }