feat: 封装 git cargo 命令

This commit is contained in:
YdrMaster 2022-05-10 13:20:56 +08:00
parent 207449af67
commit e4c1b8a397
5 changed files with 217 additions and 139 deletions

View File

@ -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}"));
}
}

69
xtask/src/cargo.rs Normal file
View File

@ -0,0 +1,69 @@
use crate::CommandExt;
use std::{ffi::OsStr, process::Command};
pub(crate) struct Cargo {
cmd: Command,
}
impl AsMut<Command> for Cargo {
fn as_mut(&mut self) -> &mut Command {
&mut self.cmd
}
}
impl CommandExt for Cargo {}
impl Cargo {
pub fn new(sub: &(impl AsRef<OsStr> + ?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<S, I>(&mut self, default: bool, feats: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
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<OsStr>) -> &mut Self {
self.arg("--target").arg(target);
self
}
}

View File

@ -1,51 +1,63 @@
//! 操作 git。
use crate::CommandExt;
use std::{ffi::OsStr, process::Command};
fn git(sub: &(impl AsRef<OsStr> + ?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<OsStr> + ?Sized),
dir: Option<&(impl AsRef<OsStr> + ?Sized)>,
) -> Command {
let mut cmd = git("clone");
cmd.arg(repo);
if let Some(dir) = dir {
cmd.arg(dir);
impl AsMut<Command> 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<OsStr> + ?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<OsStr> + ?Sized),
dir: Option<&(impl AsRef<OsStr> + ?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
}

View File

@ -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<Command> {
fn arg(&mut self, s: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().arg(s);
self
}
fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
for arg in args {
self.arg(arg);
}
self
}
fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self {
self.as_mut().current_dir(dir);
self
}
fn env(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().env(key, val);
self
}
fn expect(&mut self, msg: &str) {
self.as_mut().status().unwrap().exit_ok().expect(msg);
}
}

View File

@ -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<Path> + ?Sized)) {
let dst = dst.as_ref();
@ -9,13 +10,16 @@ pub fn wget(url: &str, dst: &(impl AsRef<Path> + ?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}");
}
}