├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md └── src ├── cli.yml ├── functions.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | /PKGBUILD* 4 | *.pkg.tar.xz 5 | *.log 6 | *.tar.gz 7 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "atty" 13 | version = "0.2.11" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "backtrace" 23 | version = "0.3.46" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | dependencies = [ 26 | "backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 27 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 28 | "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", 29 | "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 30 | ] 31 | 32 | [[package]] 33 | name = "backtrace-sys" 34 | version = "0.1.37" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | dependencies = [ 37 | "cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", 38 | "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "bitflags" 43 | version = "1.0.4" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "blackarch-devtools" 48 | version = "0.5.0" 49 | dependencies = [ 50 | "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 53 | ] 54 | 55 | [[package]] 56 | name = "cc" 57 | version = "1.0.52" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | 60 | [[package]] 61 | name = "cfg-if" 62 | version = "0.1.10" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | 65 | [[package]] 66 | name = "clap" 67 | version = "2.33.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | dependencies = [ 70 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 74 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 76 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 77 | "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 78 | ] 79 | 80 | [[package]] 81 | name = "failure" 82 | version = "0.1.8" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | dependencies = [ 85 | "backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)", 86 | ] 87 | 88 | [[package]] 89 | name = "libc" 90 | version = "0.2.69" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | 93 | [[package]] 94 | name = "redox_syscall" 95 | version = "0.1.54" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | 98 | [[package]] 99 | name = "redox_termios" 100 | version = "0.1.1" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | dependencies = [ 103 | "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", 104 | ] 105 | 106 | [[package]] 107 | name = "rustc-demangle" 108 | version = "0.1.16" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | 111 | [[package]] 112 | name = "strsim" 113 | version = "0.8.0" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | 116 | [[package]] 117 | name = "termcolor" 118 | version = "1.0.4" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | dependencies = [ 121 | "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 122 | ] 123 | 124 | [[package]] 125 | name = "termion" 126 | version = "1.5.1" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | dependencies = [ 129 | "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", 130 | "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", 131 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 132 | ] 133 | 134 | [[package]] 135 | name = "textwrap" 136 | version = "0.11.0" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | dependencies = [ 139 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 140 | ] 141 | 142 | [[package]] 143 | name = "unicode-width" 144 | version = "0.1.5" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | 147 | [[package]] 148 | name = "vec_map" 149 | version = "0.8.1" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | 152 | [[package]] 153 | name = "which" 154 | version = "3.1.1" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", 159 | ] 160 | 161 | [[package]] 162 | name = "winapi" 163 | version = "0.3.7" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | dependencies = [ 166 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 167 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 168 | ] 169 | 170 | [[package]] 171 | name = "winapi-i686-pc-windows-gnu" 172 | version = "0.4.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | 175 | [[package]] 176 | name = "winapi-util" 177 | version = "0.1.2" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | dependencies = [ 180 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 181 | ] 182 | 183 | [[package]] 184 | name = "winapi-x86_64-pc-windows-gnu" 185 | version = "0.4.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | 188 | [[package]] 189 | name = "wincolor" 190 | version = "1.0.1" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | dependencies = [ 193 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 194 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 195 | ] 196 | 197 | [[package]] 198 | name = "yaml-rust" 199 | version = "0.3.5" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | 202 | [metadata] 203 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 204 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" 205 | "checksum backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" 206 | "checksum backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399" 207 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" 208 | "checksum cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" 209 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 210 | "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 211 | "checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 212 | "checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" 213 | "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" 214 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 215 | "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 216 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 217 | "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" 218 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" 219 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 220 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 221 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 222 | "checksum which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" 223 | "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 224 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 225 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 226 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 227 | "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" 228 | "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" 229 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blackarch-devtools" 3 | version = "0.5.0" 4 | authors = ["Eduard Toloza "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | termcolor = "1.0.4" 9 | clap = {version = "2.33.0", features = ["yaml"]} 10 | which = "3.1.1" 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blackarch-devtools 2 | Development framework for the BlackArch Linux distribution written in Rust. 3 | 4 | # What is it? 5 | It's a development framework for BlackArch Linux developers that allow you to: set up a chroot enviroment, build packages in chroot environments, build packages with dependencies that aren't in the repos, sync the working chroot copy with the root chroot copy, test packages in the chroot enviroment and more things. 6 | 7 | # Installation 8 | If you want to install it, you can do that manually compiling the source or using the precompiled binary. 9 | 10 | Prerequisites: 11 | - [devtools](https://www.archlinux.org/packages/extra/any/devtools/) 12 | 13 | You can install the prerequisites with `# pacman -S devtools` 14 | 15 | **Manually:** You need to have [Rust](https://www.archlinux.org/packages/extra/x86_64/rust/) installed in your computer first. Install it with `# pacman -S rust` 16 | 17 | ``` 18 | $ git clone https://github.com/Edu4rdSHL/blackarch-devtools.git 19 | $ cd blackarch-devtools 20 | $ cargo build --release 21 | $ sudo cp target/release/blackarch-devtools /usr/bin/blackarch-devtools 22 | $ blackarch-devtools 23 | ``` 24 | 25 | **Using the binary:** 26 | 27 | ``` 28 | $ wget https://github.com/Edu4rdSHL/blackarch-devtools/releases/latest/download/blackarch-devtools 29 | $ chmod +x blackarch-devtools 30 | $ sudo cp blackarch-devtools /usr/bin/blackarch-devtools 31 | $ blackarch-devtools 32 | ``` 33 | 34 | **Using BlackArch repo** 35 | 36 | ``` 37 | $ sudo pacman -S blackarch-devtools-toolkit 38 | $ ba-dev 39 | ``` 40 | 41 | # Usage 42 | 43 | The available options are: 44 | 45 | ``` 46 | USAGE: 47 | blackarch-devtools [FLAGS] [OPTIONS] 48 | 49 | FLAGS: 50 | -b, --build Build package from PKGBUILD in clean chroot environment. 51 | -h, --help Prints help information 52 | -s, --setup Setup the clean chroot environment (automatically setup blackarch keyring). 53 | -t, --test Install and test package in clean chroot environment. 54 | -u, --update Update chroot environment before building. 55 | -V, --version Prints version information 56 | -v Sets the level of verbosity 57 | 58 | OPTIONS: 59 | -e, --executable 60 | Name of the binary file provided by the package that you're installing in the chroot environment. 61 | 62 | -I, --install-missing ... 63 | Build package files that aren't available in repos. You can specify it multiple times. 64 | 65 | -p, --package Build package to install in the clean chroot environment. 66 | ``` 67 | Flags doesn't require arguments, options require. 68 | 69 | If you have found an issue or want to make a feature request, please use the [issue tracker](https://github.com/Edu4rdSHL/blackarch-devtools/issues). 70 | -------------------------------------------------------------------------------- /src/cli.yml: -------------------------------------------------------------------------------- 1 | name: blackarch-devtools 2 | version: "0.4.0" 3 | author: Eduard Tolosa 4 | about: Development tools for BlackArch Linux 5 | settings: 6 | - ArgRequiredElseHelp 7 | - StrictUtf8 8 | args: 9 | - setup: 10 | short: s 11 | long: setup 12 | help: Setup the clean chroot environment (automatically setup blackarch keyring). 13 | takes_value: false 14 | - build: 15 | short: b 16 | long: build 17 | help: Build package from PKGBUILD in clean chroot environment. 18 | takes_value: false 19 | conflicts_with: 20 | - install-missing 21 | - package: 22 | short: p 23 | long: package 24 | help: Build package to install in the clean chroot environment. 25 | takes_value: true 26 | requires: 27 | - executable 28 | - executable: 29 | short: e 30 | long: executable 31 | help: Execute the command to test the package in the chroot environment. 32 | takes_value: true 33 | multiple: true 34 | requires: 35 | - package 36 | - install-missing: 37 | short: I 38 | long: install-missing 39 | help: Build package files that aren't available in repos. You can specify it multiple times. 40 | multiple: true 41 | takes_value: true 42 | - update: 43 | short: u 44 | long: update 45 | help: Update chroot environment before building. 46 | takes_value: false 47 | - verbose: 48 | short: v 49 | multiple: true 50 | help: Sets the level of verbosity 51 | -------------------------------------------------------------------------------- /src/functions.rs: -------------------------------------------------------------------------------- 1 | // Crate termcolor 2 | use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; 3 | 4 | // Standard imports 5 | use std::io::Write; 6 | use std::path::Path; 7 | use std::process; 8 | use std::process::Command; 9 | use std::{env, fs}; 10 | 11 | pub fn get_vars(get_var: &str) -> String { 12 | let home_dir: String = env::var("HOME").expect("Failed to read HOME system variable."); 13 | let chroot_dir: String = [&home_dir, "/blackarch_chroot"].concat(); 14 | let devtools_mkarchroot = String::from("/usr/bin/mkarchroot"); 15 | let devtools_nspawn = String::from("/usr/bin/arch-nspawn"); 16 | let blackarch_instance: String = String::from("blackarch"); 17 | let chroot_root: String = [&chroot_dir, "/root/"].concat(); 18 | let chroot_blackarch: String = [&chroot_dir, "/blackarch/"].concat(); 19 | let devtools_makechrootpkg: String = String::from("/usr/bin/makechrootpkg"); 20 | let pacman: String = String::from("/usr/bin/pacman"); 21 | if get_var == "home_dir" { 22 | home_dir 23 | } else if get_var == "chroot_dir" { 24 | chroot_dir 25 | } else if get_var == "mkarchroot" { 26 | devtools_mkarchroot 27 | } else if get_var == "nspawn" { 28 | devtools_nspawn 29 | } else if get_var == "chroot_root" { 30 | chroot_root 31 | } else if get_var == "chroot_blackarch" { 32 | chroot_blackarch 33 | } else if get_var == "blackarch_instance" { 34 | blackarch_instance 35 | } else if get_var == "makechrootpkg" { 36 | devtools_makechrootpkg 37 | } else if get_var == "pacman" { 38 | pacman 39 | } else { 40 | String::from("Error returning the value.") 41 | } 42 | } 43 | 44 | pub fn coloring(color: &str) -> termcolor::StandardStream { 45 | let mut stdout = StandardStream::stdout(ColorChoice::Always); 46 | if color == "green" { 47 | stdout 48 | .set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Green))) 49 | .unwrap(); 50 | stdout 51 | } else if color == "yellow" { 52 | stdout 53 | .set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Yellow))) 54 | .unwrap(); 55 | stdout 56 | } else if color == "red" { 57 | stdout 58 | .set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Red))) 59 | .unwrap(); 60 | stdout 61 | } else { 62 | stdout 63 | .set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::White))) 64 | .unwrap(); 65 | stdout 66 | } 67 | } 68 | 69 | pub fn setup_chroot() { 70 | let chroot_dir = get_vars("chroot_dir"); 71 | if Path::new(&chroot_dir).exists() { 72 | if Path::new(&chroot_dir).is_dir() { 73 | writeln!(coloring("red"), "The directory {} already exists in the system, remove it or try with a different path.", &chroot_dir).unwrap(); 74 | process::exit(1); 75 | } else if Path::new(&chroot_dir).is_file() { 76 | writeln!( 77 | coloring("red"), 78 | "The file {} already exists in the system, remove it or try a different path.", 79 | &chroot_dir 80 | ) 81 | .unwrap(); 82 | process::exit(1); 83 | } 84 | } else { 85 | writeln!( 86 | coloring("yellow"), 87 | "Creating chroot directory with name: {}", 88 | &chroot_dir 89 | ) 90 | .unwrap(); 91 | fs::create_dir(&chroot_dir) 92 | .expect("An error as ocurred while creating the chroot directoy."); 93 | writeln!(coloring("yellow"), "Setting up chroot environment...").unwrap(); 94 | let devtools_mkarchroot = get_vars("mkarchroot"); 95 | let devtools_nspawn = get_vars("nspawn"); 96 | let chroot_root = get_vars("chroot_root"); 97 | if Path::new(&devtools_mkarchroot).exists() { 98 | let up_chroot = Command::new(&devtools_mkarchroot) 99 | .args(&[&chroot_root, "base", "base-devel"]) 100 | .status() 101 | .expect("Failed to setup chroot environment."); 102 | if up_chroot.success() { 103 | writeln!(coloring("yellow"), "Enabling multilib repos...").unwrap(); 104 | Command::new(&devtools_nspawn).args(&[&chroot_root, "/bin/sh", "-c", "echo -e '\n[multilib]\nInclude = /etc/pacman.d/mirrorlist\n' | sudo tee -a /etc/pacman.conf > /dev/null"]).status().expect("Failed enabling multilib repos."); 105 | writeln!(coloring("yellow"), "Changing makepkg.conf to use zstd...").unwrap(); 106 | Command::new(&devtools_nspawn) 107 | .args(&[ 108 | &chroot_root, 109 | "/bin/sh", 110 | "-c", 111 | "sed -i 's/^PKGEXT.*/PKGEXT='\\''.pkg.tar.zst'\\''/g' /etc/makepkg.conf", 112 | ]) 113 | .status() 114 | .expect("Failed to change makepkg.conf"); 115 | writeln!( 116 | coloring("yellow"), 117 | "Configuring BlackArch Linux repo in the chroot environment..." 118 | ) 119 | .unwrap(); 120 | let get_strap = Command::new(&devtools_nspawn) 121 | .args(&[&chroot_root, "curl", "-O", "https://blackarch.org/strap.sh"]) 122 | .status() 123 | .expect("Failed to retrieve strap.sh from blackarch.org"); 124 | if get_strap.success() { 125 | let strap_exec = Command::new(&devtools_nspawn) 126 | .args(&[&chroot_root, "sh", "strap.sh"]) 127 | .status() 128 | .expect("Failed to exec strap.sh"); 129 | if strap_exec.success() { 130 | Command::new(&devtools_nspawn) 131 | .args(&[&chroot_root, "rm", "strap.sh"]) 132 | .status() 133 | .expect("Error deleting strap.sh from chroot environment."); 134 | sync_chroot(); 135 | writeln!(coloring("green"), "Chroot environment setup complete!").unwrap(); 136 | } else { 137 | writeln!( 138 | coloring("red"), 139 | "Can't install strap.sh into {}!", 140 | &chroot_root 141 | ) 142 | .unwrap(); 143 | } 144 | } else { 145 | writeln!( 146 | coloring("red"), 147 | "Failed to retrieve strap.sh from blackarch.org!" 148 | ) 149 | .unwrap(); 150 | } 151 | } else { 152 | writeln!( 153 | coloring("red"), 154 | "Failed to install base packages into chroot environment." 155 | ) 156 | .unwrap(); 157 | } 158 | } else { 159 | writeln!( 160 | coloring("red"), 161 | "Executable file {} not found, install the devtools package from repos.", 162 | &devtools_mkarchroot 163 | ) 164 | .unwrap(); 165 | } 166 | } 167 | } 168 | 169 | pub fn update_chroot_packages() { 170 | writeln!(coloring("green"), "Updating the chroot environment...").unwrap(); 171 | let devtools_nspawn = get_vars("nspawn"); 172 | let chroot_root = get_vars("chroot_root"); 173 | let update_packages = Command::new(&devtools_nspawn) 174 | .args(&[&chroot_root, "/bin/sh", "-c", "pacman --noconfirm -Syuu"]) 175 | .status() 176 | .expect("Failed updating chroot environment"); 177 | if update_packages.success() { 178 | sync_chroot(); 179 | writeln!(coloring("green"), "Chroot environment updated correctly!").unwrap(); 180 | } else { 181 | writeln!( 182 | coloring("red"), 183 | "An error as ocurred while updating the chroot environment." 184 | ) 185 | .unwrap(); 186 | } 187 | } 188 | 189 | pub fn build_package() { 190 | sync_chroot(); 191 | if which::which("pkgcheck").is_ok() { 192 | writeln!(coloring("yellow"), "Checking PKGBUILD with pkgcheck...").unwrap(); 193 | if Command::new("pkgcheck") 194 | .arg("PKGBUILD") 195 | .status() 196 | .expect("Failed to execute pkgcheck command") 197 | .success() 198 | { 199 | writeln!(coloring("green"), "No errors detected with pkgcheck!").unwrap(); 200 | } else { 201 | writeln!( 202 | coloring("red"), 203 | "Some errors were detected, please fix them before pushing!" 204 | ) 205 | .unwrap(); 206 | } 207 | } else { 208 | writeln!( 209 | coloring("yellow"), 210 | "Consideer installing pkgcheck with pip install pkgcheck-arch --user for automatic PKGBUILD syntax error checking." 211 | ) 212 | .unwrap() 213 | } 214 | let devtools_makechrootpkg = get_vars("makechrootpkg"); 215 | let chroot_dir = get_vars("chroot_dir"); 216 | let blackarch_instance = get_vars("blackarch_instance"); 217 | let build_package = Command::new(&devtools_makechrootpkg) 218 | .args(&["-l", &blackarch_instance, "-r", &chroot_dir]) 219 | .status() 220 | .expect("Failed to build the package."); 221 | if build_package.success() { 222 | writeln!(coloring("green"), "Package built sucessfully!").unwrap(); 223 | } else { 224 | writeln!(coloring("red"), "Failed to build the package.").unwrap(); 225 | } 226 | } 227 | 228 | pub fn build_package_with_missing_deps(missing: &[&str]) { 229 | sync_chroot(); 230 | let chroot_blackarch = get_vars("chroot_blackarch"); 231 | let devtools_nspawn = get_vars("nspawn"); 232 | for missing in missing.iter() { 233 | let copy_path: String = [ 234 | &chroot_blackarch, 235 | "root/", 236 | &missing 237 | .split("/") 238 | .last() 239 | .expect("Failed to get package name."), 240 | ] 241 | .concat(); 242 | Command::new("sudo") 243 | .args(&["cp", &missing, ©_path]) 244 | .spawn() 245 | .expect("Failed to copy missing packages."); 246 | } 247 | writeln!( 248 | coloring("yellow"), 249 | "Installing missing packages: {:?}", 250 | missing 251 | ) 252 | .unwrap(); 253 | let install_missing = Command::new(&devtools_nspawn) 254 | .args(&[ 255 | &chroot_blackarch, 256 | "/bin/sh", 257 | "-c", 258 | "pacman -U --noconfirm root/*", 259 | ]) 260 | .status() 261 | .expect("Failed to install missing packages."); 262 | if install_missing.success() { 263 | let devtools_makechrootpkg = get_vars("makechrootpkg"); 264 | let chroot_dir = get_vars("chroot_dir"); 265 | let blackarch_instance = get_vars("blackarch_instance"); 266 | let build_package = Command::new(&devtools_makechrootpkg) 267 | .args(&["-l", &blackarch_instance, "-r", &chroot_dir]) 268 | .status() 269 | .expect("Failed to build the package."); 270 | if build_package.success() { 271 | writeln!(coloring("green"), "Package built sucessfully!").unwrap(); 272 | } else { 273 | writeln!(coloring("red"), "Failed to build the package.").unwrap(); 274 | } 275 | Command::new(&devtools_nspawn).args(&[&chroot_blackarch, "/bin/sh", "-c", "rm -rf root/*"]); 276 | } 277 | } 278 | 279 | pub fn sync_chroot() { 280 | let chroot_blackarch = get_vars("chroot_blackarch"); 281 | let chroot_root = get_vars("chroot_root"); 282 | let chroot_dir = get_vars("chroot_dir"); 283 | writeln!( 284 | coloring("green"), 285 | "Syncing chroot copy {} with {} ...", 286 | &chroot_blackarch, 287 | &chroot_root 288 | ) 289 | .unwrap(); 290 | if Path::new(&chroot_dir).exists() { 291 | if Path::new(&chroot_blackarch).exists() { 292 | let fs_type = Command::new("stat") 293 | .args(&["-f", "-c", "%T", &chroot_blackarch]) 294 | .output() 295 | .expect("Failed to read filesystem type"); 296 | let fs_id_hex = Command::new("stat") 297 | .args(&["-c", "%i", &chroot_blackarch]) 298 | .output() 299 | .expect("Failed to read filesystem ID"); 300 | if String::from_utf8_lossy(&fs_type.stdout) == "btrfs" 301 | && String::from_utf8_lossy(&fs_id_hex.stdout) == "256" 302 | { 303 | Command::new("sudo") 304 | .args(&["btrfs", "subvolume", "delete", &chroot_blackarch]) 305 | .status() 306 | .expect("Failed to delete chroot copy."); 307 | Command::new("sudo") 308 | .args(&[ 309 | "btrfs", 310 | "subvolume", 311 | "snapshot", 312 | &chroot_root, 313 | &chroot_blackarch, 314 | ]) 315 | .spawn() 316 | .expect("Failed to create chroot copy."); 317 | } else { 318 | let make_chroot_copy = Command::new("sudo") 319 | .args(&[ 320 | "rsync", 321 | "-a", 322 | "--delete", 323 | "-q", 324 | "-W", 325 | "-x", 326 | &chroot_root, 327 | &chroot_blackarch, 328 | ]) 329 | .status() 330 | .expect("Failed to create copy of root chroot environment."); 331 | if make_chroot_copy.success() { 332 | writeln!(coloring("green"), "Chroot environment is ready!").unwrap(); 333 | } else { 334 | writeln!( 335 | coloring("red"), 336 | "Failed to create copy of root chroot environment." 337 | ) 338 | .unwrap(); 339 | } 340 | } 341 | } else { 342 | let create_chroot_copy = Command::new("sudo") 343 | .args(&["mkdir", &chroot_blackarch]) 344 | .status() 345 | .expect("Failed to create working copy of chroot environment."); 346 | if create_chroot_copy.success() { 347 | let make_chroot_copy = Command::new("sudo") 348 | .args(&[ 349 | "rsync", 350 | "-a", 351 | "--delete", 352 | "-q", 353 | "-W", 354 | "-x", 355 | &chroot_root, 356 | &chroot_blackarch, 357 | ]) 358 | .status() 359 | .expect("Failed to create chroot copy."); 360 | if make_chroot_copy.success() { 361 | writeln!(coloring("green"), "Chroot environment is ready!").unwrap(); 362 | } else { 363 | writeln!( 364 | coloring("red"), 365 | "Failed to create copy of root chroot environment." 366 | ) 367 | .unwrap(); 368 | } 369 | } 370 | } 371 | } else { 372 | writeln!( 373 | coloring("red"), 374 | "Chroot environment doesn't exists. Please use the -s option first." 375 | ) 376 | .unwrap(); 377 | } 378 | } 379 | 380 | pub fn test_package(package: &str, executable: &str) { 381 | let pacman = get_vars("pacman"); 382 | let chroot_blackarch = get_vars("chroot_blackarch"); 383 | let devtools_nspawn = get_vars("nspawn"); 384 | let install_package = Command::new("sudo") 385 | .args(&[ 386 | &pacman, 387 | "--root", 388 | &chroot_blackarch, 389 | "-U", 390 | "--noconfirm", 391 | &package, 392 | ]) 393 | .status() 394 | .expect("Failed to install the package in the chroot environment."); 395 | if install_package.success() { 396 | writeln!( 397 | coloring("green"), 398 | "Package {} installed correctly! Testing it now...", 399 | &package 400 | ) 401 | .unwrap(); 402 | Command::new("sudo") 403 | .args(&[&devtools_nspawn, &chroot_blackarch, "sh", "-c", &executable]) 404 | .status() 405 | .expect( 406 | "Something went wrong while trying to execute the binary in the chroot environment.", 407 | ); 408 | } else { 409 | writeln!( 410 | coloring("red"), 411 | "Package {} wasn't installed in the chroot environment, please check the package name.", 412 | &package 413 | ) 414 | .unwrap(); 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // Crate clap 2 | #[macro_use] 3 | extern crate clap; 4 | use clap::App; 5 | 6 | // Functions module 7 | mod functions; 8 | 9 | fn main() { 10 | let yaml = load_yaml!("cli.yml"); 11 | let matches = App::from_yaml(yaml).get_matches(); 12 | if matches.is_present("setup") { 13 | functions::setup_chroot(); 14 | } else if matches.is_present("build") { 15 | functions::build_package(); 16 | } else if matches.is_present("update") { 17 | functions::update_chroot_packages(); 18 | } else if matches.is_present("package") { 19 | let package = matches 20 | .value_of("package") 21 | .expect("Failed to convert in a valid String") 22 | .to_string(); 23 | let executable: Vec<&str> = matches.values_of("executable").unwrap().collect(); 24 | functions::test_package(&package, &executable.join(" ")); 25 | } else if matches.is_present("install-missing") { 26 | let missing_deps: Vec<&str> = matches.values_of("install-missing").unwrap().collect(); 27 | functions::build_package_with_missing_deps(&missing_deps.as_slice()); 28 | } 29 | } 30 | --------------------------------------------------------------------------------