├── .gitignore ├── install.sh ├── Cargo.toml ├── README.md ├── .github └── workflows │ └── a-release.yaml ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cargo build --release 4 | cp -v target/release/qit ~/bin 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qit" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | clap = "3.0.0-rc.4" 10 | git2 = "0.14.1" 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qit 2 | 3 | > *Overly opinionated git tooling.* 4 | 5 | qit is a utility that wraps around git in order to make some operations less 6 | painful. 7 | 8 | ## Pretty pictures 9 | 10 | ![](https://amyware.nyc3.digitaloceanspaces.com/2021/12/13/L7JaBjnssyViT.png) 11 | 12 | ![](https://amyware.nyc3.digitaloceanspaces.com/2021/12/13/ojAq3g41ROiYw.png) 13 | 14 | ![](https://amyware.nyc3.digitaloceanspaces.com/2021/12/13/EGTgy0UFXDHJ8.png) 15 | 16 | ## Configuration 17 | 18 | qit believes in minimising configuration / being overly opinionated, so only a 19 | bare minimum of configurability is exposed. 20 | 21 | Configuration is done via environment variables. 22 | 23 | ``` 24 | # Disable emojis in commit messages 25 | QIT_DISABLE_EMOJIS=true 26 | ``` 27 | -------------------------------------------------------------------------------- /.github/workflows/a-release.yaml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | branches: 9 | - "mistress" 10 | 11 | jobs: 12 | release: 13 | runs-on: "ubuntu-latest" 14 | steps: 15 | - name: "Checkout" 16 | uses: "actions/checkout@v2" 17 | - name: "Install latest stable Rust" 18 | uses: "actions-rs/toolchain@v1" 19 | with: 20 | toolchain: "stable" 21 | profile: "minimal" 22 | target: "x86_64-unknown-linux-musl" 23 | - uses: "Swatinem/rust-cache@v2" 24 | with: 25 | key: "release" 26 | cache-on-failure: true 27 | - name: "Install musl-tools" 28 | run: "sudo apt-get update && sudo apt-get install -y musl-tools comerr-dev wget" 29 | - name: "Build static-linked release binary!" 30 | uses: "actions-rs/cargo@v1" 31 | with: 32 | command: "build" 33 | args: "--release" 34 | - name: "Create release" 35 | uses: "softprops/action-gh-release@v1" 36 | env: 37 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 38 | - name: "Upload release assets with gh cli" 39 | run: "xargs -I {} gh release upload ${{ github.ref_name }} target/release/qit" 40 | env: 41 | GH_TOKEN: ${{ github.token }} 42 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::error::Error; 3 | use std::io::{Error as IOError, ErrorKind}; 4 | use std::process::{Command, Stdio}; 5 | 6 | use clap::{App, Arg}; 7 | use git2::Repository; 8 | 9 | type Result = std::result::Result>; 10 | 11 | fn main() -> Result<()> { 12 | let app = App::new("qit") 13 | // Commit 14 | .subcommand( 15 | App::new("commit") 16 | .alias("c") 17 | .about("Commits with a meaningful commit message") 18 | .after_help(" 19 | Format: 20 | [()]: 21 | 22 | Emojis: 23 | chore 🔨 24 | feature ✨ 25 | refactor ♻️ 26 | fix 🐛 27 | test ✅ 28 | style 🎨 29 | doc 📝 30 | deps 📦 31 | deploy 🚀 32 | wip 🚧 33 | 34 | Emojis inspired by https://gitmoji.dev/ 35 | 36 | Examples: 37 | ✨ feature: Add thing 38 | ✨ feature(cli): Improve args 39 | 🔨 chore: Do thing 40 | 🚀 deploy(api): Deploy to production 41 | ") 42 | .arg( 43 | Arg::new("type") 44 | .help("The type of commit") 45 | .possible_values(vec![ 46 | "chore", "feature", "refactor", "fix", "test", "style", "doc", "deps", "deploy", "wip", 47 | ]) 48 | .required(true), 49 | ) 50 | .arg( 51 | Arg::new("area") 52 | .help("The section of the code this commit focuses on") 53 | .long("area") 54 | .short('a') 55 | .takes_value(true) 56 | .required(false), 57 | ) 58 | .arg( 59 | Arg::new("message") 60 | .help("The commit message") 61 | .required(true), 62 | ) 63 | .arg( 64 | Arg::new("no-verify") 65 | .help("git commit --no-verify") 66 | .long("no-verify") 67 | .short('n') 68 | .takes_value(false) 69 | .required(false), 70 | ), 71 | ) 72 | // Push 73 | .subcommand( 74 | App::new("push") 75 | .alias("p") 76 | .about("Pushes the current branch to the remote. Will not push if there are uncommitted changes.") 77 | .arg( 78 | Arg::new("force") 79 | .help("Force push. Ignores uncommitted changes. **WARNING**: This is the same as `git push -f`!") 80 | .long("force") 81 | .short('f') 82 | .takes_value(false), 83 | ), 84 | ) 85 | // Undo 86 | .subcommand( 87 | App::new("undo") 88 | .alias("u") 89 | .about("Undoes the last commit"), 90 | ) 91 | // Log 92 | .subcommand( 93 | App::new("log").alias("l").about("Shows the git log").arg( 94 | Arg::new("short") 95 | .long("short") 96 | .short('s') 97 | .help("Whether to show a shortened git log"), 98 | ), 99 | ) 100 | // Branch 101 | .subcommand( 102 | App::new("switch") 103 | .alias("s") 104 | .about("Switch branches, creating as needed") 105 | .arg( 106 | Arg::new("branch") 107 | .help("The branch to switch to") 108 | .required(true), 109 | ), 110 | ) 111 | ; 112 | 113 | let matches = app.get_matches(); 114 | 115 | match matches.subcommand() { 116 | Some(("commit", args)) => { 117 | let type_ = args.value_of("type").unwrap(); 118 | let area = args.value_of("area"); 119 | let message = args.value_of("message").unwrap(); 120 | let no_verify = args.is_present("no-verify"); 121 | handle(commit(type_, &area, message, no_verify)); 122 | } 123 | Some(("log", args)) => { 124 | let short = args.is_present("short"); 125 | handle(log(short)); 126 | } 127 | Some(("push", args)) => { 128 | let force = args.is_present("force"); 129 | handle(push(force)); 130 | } 131 | Some(("undo", _)) => handle(undo()), 132 | Some(("switch", args)) => handle(switch_branch(args.value_of("branch").unwrap())), 133 | _ => println!("{}", repo_status()?), 134 | } 135 | Ok(()) 136 | } 137 | 138 | fn handle(res: Result<()>) { 139 | match res { 140 | Ok(_) => (), 141 | Err(err) => { 142 | eprintln!("💥 Unable to run command:"); 143 | eprintln!("{}", err); 144 | std::process::exit(1); 145 | } 146 | }; 147 | } 148 | 149 | // Subcommands // 150 | 151 | fn commit(type_: &str, area: &Option<&str>, message: &str, no_verify: bool) -> Result<()> { 152 | // Emojis inspired by https://gitmoji.dev/ 153 | let emoji = match type_ { 154 | "chore" => "🔨", 155 | "feature" => "✨", 156 | "refactor" => "♻️", 157 | "fix" => "🐛", 158 | "test" => "✅", 159 | "style" => "🎨", 160 | "doc" => "📝", 161 | "deps" => "📦", 162 | "deploy" => "🚀", 163 | "wip" => "🚧", 164 | _ => { 165 | panic!("Unknown commit type") 166 | } 167 | }; 168 | let emoji = match env::var("QIT_DISABLE_EMOJIS") { 169 | Ok(value) => { 170 | if value == "true" { 171 | "" 172 | } else { 173 | emoji 174 | } 175 | } 176 | _ => emoji, 177 | }; 178 | let formatted = match area { 179 | Some(area) => format!("{} {}({}): {}", emoji, type_, area, message), 180 | None => format!("{} {}: {}", emoji, type_, message), 181 | }; 182 | let formatted = formatted.trim(); 183 | 184 | Command::new("git") 185 | .arg("add") 186 | .arg("-A") 187 | .arg("*") 188 | .arg(".*") 189 | .spawn()? 190 | .wait()?; 191 | let mut cmd = Command::new("git"); 192 | 193 | cmd.arg("commit"); 194 | if no_verify { 195 | cmd.arg("--no-verify"); 196 | } 197 | 198 | cmd.arg("-am") 199 | .arg(formatted) 200 | .spawn()? 201 | .wait()?; 202 | Ok(()) 203 | } 204 | 205 | fn log(short: bool) -> Result<()> { 206 | let mut cmd = Command::new("git"); 207 | cmd.arg("log"); 208 | if short { 209 | cmd.arg("--oneline"); 210 | } 211 | cmd.spawn()?.wait()?; 212 | Ok(()) 213 | } 214 | 215 | fn push(force: bool) -> Result<()> { 216 | let pending_changes = if let Ok(count) = repo_status() { 217 | count > 0 218 | } else { 219 | false 220 | }; 221 | 222 | if pending_changes && !force { 223 | return Err(IOError::new(ErrorKind::Other, "There are uncommitted changes").into()); 224 | } 225 | let mut cmd = Command::new("git"); 226 | cmd.arg("push"); 227 | if force { 228 | cmd.arg("--force"); 229 | } 230 | cmd.spawn()?.wait()?; 231 | Ok(()) 232 | } 233 | 234 | fn undo() -> Result<()> { 235 | Command::new("git") 236 | .arg("reset") 237 | .arg("--soft") 238 | .arg("HEAD~1") 239 | .spawn()? 240 | .wait()?; 241 | Ok(()) 242 | } 243 | 244 | fn switch_branch(branch: &str) -> Result<()> { 245 | let branch = if branch == "msitress" { 246 | eprintln!("‼️ correcting msitress => mistress"); 247 | "mistress" 248 | } else { 249 | branch 250 | }; 251 | let mut cmd = Command::new("git"); 252 | let cmd = cmd 253 | .arg("checkout") 254 | .arg(branch) 255 | .stdout(Stdio::null()) 256 | .stderr(Stdio::null()); 257 | let output = cmd.spawn()?.wait()?; 258 | if output.success() { 259 | Ok(()) 260 | } else { 261 | Command::new("git") 262 | .arg("checkout") 263 | .arg("-b") 264 | .arg(branch) 265 | .spawn()? 266 | .wait()?; 267 | Ok(()) 268 | } 269 | } 270 | 271 | // Helpers // 272 | 273 | fn repo_status() -> Result { 274 | let repo = Repository::open(".")?; 275 | let modified_files = repo 276 | .statuses(Some(git2::StatusOptions::new().include_untracked(true)))? 277 | .iter() 278 | .filter(|s| !s.status().is_ignored()) 279 | .count(); 280 | Ok(modified_files) 281 | } 282 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "atty" 7 | version = "0.2.14" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 10 | dependencies = [ 11 | "hermit-abi", 12 | "libc", 13 | "winapi", 14 | ] 15 | 16 | [[package]] 17 | name = "autocfg" 18 | version = "1.0.1" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 21 | 22 | [[package]] 23 | name = "bitflags" 24 | version = "1.3.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 27 | 28 | [[package]] 29 | name = "cc" 30 | version = "1.0.72" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" 33 | dependencies = [ 34 | "jobserver", 35 | ] 36 | 37 | [[package]] 38 | name = "cfg-if" 39 | version = "1.0.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 42 | 43 | [[package]] 44 | name = "clap" 45 | version = "3.0.0-rc.4" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "967965e82fc46fee1a88147a7a977a66d615ed5f83eb95b18577b342c08f90ff" 48 | dependencies = [ 49 | "atty", 50 | "bitflags", 51 | "indexmap", 52 | "os_str_bytes", 53 | "strsim", 54 | "termcolor", 55 | "textwrap", 56 | ] 57 | 58 | [[package]] 59 | name = "form_urlencoded" 60 | version = "1.0.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 63 | dependencies = [ 64 | "matches", 65 | "percent-encoding", 66 | ] 67 | 68 | [[package]] 69 | name = "git2" 70 | version = "0.14.1" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "6e7d3b96ec1fcaa8431cf04a4f1ef5caafe58d5cf7bcc31f09c1626adddb0ffe" 73 | dependencies = [ 74 | "bitflags", 75 | "libc", 76 | "libgit2-sys", 77 | "log", 78 | "openssl-probe", 79 | "openssl-sys", 80 | "url", 81 | ] 82 | 83 | [[package]] 84 | name = "hashbrown" 85 | version = "0.11.2" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 88 | 89 | [[package]] 90 | name = "hermit-abi" 91 | version = "0.1.19" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 94 | dependencies = [ 95 | "libc", 96 | ] 97 | 98 | [[package]] 99 | name = "idna" 100 | version = "0.2.3" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 103 | dependencies = [ 104 | "matches", 105 | "unicode-bidi", 106 | "unicode-normalization", 107 | ] 108 | 109 | [[package]] 110 | name = "indexmap" 111 | version = "1.7.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 114 | dependencies = [ 115 | "autocfg", 116 | "hashbrown", 117 | ] 118 | 119 | [[package]] 120 | name = "jobserver" 121 | version = "0.1.24" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" 124 | dependencies = [ 125 | "libc", 126 | ] 127 | 128 | [[package]] 129 | name = "libc" 130 | version = "0.2.111" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "8e167738f1866a7ec625567bae89ca0d44477232a4f7c52b1c7f2adc2c98804f" 133 | 134 | [[package]] 135 | name = "libgit2-sys" 136 | version = "0.13.1+1.4.2" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "43e598aa7a4faedf1ea1b4608f582b06f0f40211eec551b7ef36019ae3f62def" 139 | dependencies = [ 140 | "cc", 141 | "libc", 142 | "libssh2-sys", 143 | "libz-sys", 144 | "openssl-sys", 145 | "pkg-config", 146 | ] 147 | 148 | [[package]] 149 | name = "libssh2-sys" 150 | version = "0.2.23" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" 153 | dependencies = [ 154 | "cc", 155 | "libc", 156 | "libz-sys", 157 | "openssl-sys", 158 | "pkg-config", 159 | "vcpkg", 160 | ] 161 | 162 | [[package]] 163 | name = "libz-sys" 164 | version = "1.1.3" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" 167 | dependencies = [ 168 | "cc", 169 | "libc", 170 | "pkg-config", 171 | "vcpkg", 172 | ] 173 | 174 | [[package]] 175 | name = "log" 176 | version = "0.4.14" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 179 | dependencies = [ 180 | "cfg-if", 181 | ] 182 | 183 | [[package]] 184 | name = "matches" 185 | version = "0.1.9" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 188 | 189 | [[package]] 190 | name = "memchr" 191 | version = "2.4.1" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 194 | 195 | [[package]] 196 | name = "openssl-probe" 197 | version = "0.1.4" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" 200 | 201 | [[package]] 202 | name = "openssl-sys" 203 | version = "0.9.72" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" 206 | dependencies = [ 207 | "autocfg", 208 | "cc", 209 | "libc", 210 | "pkg-config", 211 | "vcpkg", 212 | ] 213 | 214 | [[package]] 215 | name = "os_str_bytes" 216 | version = "6.0.0" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" 219 | dependencies = [ 220 | "memchr", 221 | ] 222 | 223 | [[package]] 224 | name = "percent-encoding" 225 | version = "2.1.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 228 | 229 | [[package]] 230 | name = "pkg-config" 231 | version = "0.3.24" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" 234 | 235 | [[package]] 236 | name = "qit" 237 | version = "0.1.0" 238 | dependencies = [ 239 | "clap", 240 | "git2", 241 | ] 242 | 243 | [[package]] 244 | name = "strsim" 245 | version = "0.10.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 248 | 249 | [[package]] 250 | name = "termcolor" 251 | version = "1.1.2" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 254 | dependencies = [ 255 | "winapi-util", 256 | ] 257 | 258 | [[package]] 259 | name = "textwrap" 260 | version = "0.14.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" 263 | 264 | [[package]] 265 | name = "tinyvec" 266 | version = "1.5.1" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 269 | dependencies = [ 270 | "tinyvec_macros", 271 | ] 272 | 273 | [[package]] 274 | name = "tinyvec_macros" 275 | version = "0.1.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 278 | 279 | [[package]] 280 | name = "unicode-bidi" 281 | version = "0.3.7" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 284 | 285 | [[package]] 286 | name = "unicode-normalization" 287 | version = "0.1.19" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 290 | dependencies = [ 291 | "tinyvec", 292 | ] 293 | 294 | [[package]] 295 | name = "url" 296 | version = "2.2.2" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 299 | dependencies = [ 300 | "form_urlencoded", 301 | "idna", 302 | "matches", 303 | "percent-encoding", 304 | ] 305 | 306 | [[package]] 307 | name = "vcpkg" 308 | version = "0.2.15" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 311 | 312 | [[package]] 313 | name = "winapi" 314 | version = "0.3.9" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 317 | dependencies = [ 318 | "winapi-i686-pc-windows-gnu", 319 | "winapi-x86_64-pc-windows-gnu", 320 | ] 321 | 322 | [[package]] 323 | name = "winapi-i686-pc-windows-gnu" 324 | version = "0.4.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 327 | 328 | [[package]] 329 | name = "winapi-util" 330 | version = "0.1.5" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 333 | dependencies = [ 334 | "winapi", 335 | ] 336 | 337 | [[package]] 338 | name = "winapi-x86_64-pc-windows-gnu" 339 | version = "0.4.0" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 342 | --------------------------------------------------------------------------------