├── .gitignore ├── docs ├── install-binary.md ├── install-source.md ├── index.md ├── why.md └── usage.md ├── Cargo.toml ├── .github └── workflows │ └── ci.yml ├── src ├── errors.rs ├── main.rs ├── git.rs └── git_url_parser.rs ├── mkdocs.yml ├── LICENSE ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /docs/install-binary.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "git-down" 3 | version = "0.3.0-beta" 4 | authors = ["Zikani Nyirenda Mwase ", "Walter Kaunda "] 5 | 6 | [dependencies] 7 | clap = "3.1.8" 8 | fs_extra = "1.2.0" 9 | regex = "1" 10 | tempfile = "3" 11 | 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # GitHub Actions worflow file for git-down 2 | name: git-down GitHub actions CI 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | ci: 14 | name: git-down-test 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | - uses: actions-rs/toolchain@v1 19 | with: 20 | toolchain: stable 21 | - run: cargo build --release 22 | -------------------------------------------------------------------------------- /docs/install-source.md: -------------------------------------------------------------------------------- 1 | Installation from Source 2 | ======================== 3 | 4 | No pre-packaged binaries - you have to build it yourself, sorry. :/ 5 | 6 | You will have to install Rust. I highly recommend using [rustup](https://www.rustup.rs) 7 | 8 | ```sh 9 | $ git clone https://github.com/zikani03/git-down.git 10 | $ cd git-down 11 | $ cargo build --release 12 | $ mv target/release/git-down ~/bin/git-down 13 | ``` 14 | 15 | Assuming your `~/bin` is on your PATH you can now use it from the shell as `git-down` -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Debug, Display, Formatter, Result}; 2 | use std::io; 3 | 4 | #[derive(Debug)] 5 | pub struct GitDownError { 6 | pub message: String, 7 | } 8 | 9 | impl Display for GitDownError { 10 | fn fmt(&self, formatter: &mut Formatter) -> Result { 11 | write!(formatter, "GitDownError: {}", self.message) 12 | } 13 | } 14 | 15 | impl From for GitDownError { 16 | fn from(error: io::Error) -> Self { 17 | GitDownError { 18 | message: error.to_string(), 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | Git Down 2 | ======== 3 | 4 | `git-down` lets you download one or multiple directories from a Git repository without the 5 | hassle of cloning or downloading the whole repository, with one simple command. 6 | 7 | # Example Usage 8 | 9 | ```sh 10 | $ git-down https://github.com/twbs/bootstrap.git:master dist src 11 | ``` 12 | 13 | Or use [supported shortcuts](./usage.md#shortcuts-for-supported-services) 14 | 15 | ```sh 16 | $ git-down gh:twbs/bootstrap.git:master dist src 17 | ``` 18 | 19 | # License 20 | 21 | This project is licensed under the terms of the MIT license. -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Site configuration 2 | site_name: git-down 3 | site_description: Download files and directories from Git repositories like a boss 4 | site_author: Zikani Nyirenda Mwase 5 | site_url: https://labs.zikani.me/git-down 6 | repo_name: zikani03/git-down 7 | repo_url: https://github.com/zikani03/git-down 8 | # edit_uri: edit/master/docs/ 9 | # docs_dir: docs 10 | 11 | # Theme Configuration 12 | theme: 13 | name: material 14 | 15 | # Navigation 16 | nav: 17 | - Home: index.md 18 | - Usage: usage.md 19 | - Installation: 20 | # - From binary: install-binary.md 21 | - From source: install-source.md 22 | - Why git-down?: why.md 23 | 24 | # Extensions 25 | markdown_extensions: 26 | # - markdown_include.include: 27 | # base_path: docs 28 | - admonition 29 | - codehilite 30 | - footnotes 31 | - meta 32 | - pymdownx.details 33 | - pymdownx.tabbed 34 | - pymdownx.superfences 35 | - pymdownx.emoji: 36 | emoji_index: !!python/name:materialx.emoji.twemoji 37 | emoji_generator: !!python/name:materialx.emoji.to_svg 38 | - toc: 39 | permalink: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zikani Nyirenda Mwase and Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/why.md: -------------------------------------------------------------------------------- 1 | It will save you time. Currently all of the ways to get just one directory from a repository 2 | require either _too much_ clicking or typing! 3 | 4 | If you want to download just one (or multiple) directory from a Git repository - 5 | like a `dist` directory of a project like bootstrap - you have several ways of 6 | doing so, including: 7 | 8 | **Download the archive and extract** 9 | 10 | The easiest and most straight-forward approach is to download the archive 11 | of the repo, extract the files and get the files/directory you want. 12 | This works best if you can get the archive via a web interface via a *Download* 13 | button/link - which can be annoying to find in some products (BitBucket!). 14 | 15 | **Shallow clone and mv** 16 | 17 | Another way is to do a shallow clone and get the directories you want using a move command. 18 | It's just too many commands and typing! 19 | 20 | For example, getting the dist directory from bootstrap you would do something like: 21 | 22 | ```sh 23 | $ git clone --depth 1 https://github.com/twbs/boostrap.git 24 | $ cd bootstrap 25 | $ mv ./dist ~/stuff/boostrap-latest 26 | ``` 27 | 28 | C'mon, you don't have the time to be doing all that. 29 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // git-down 2 | // Author: zikani03 3 | // 4 | extern crate clap; 5 | extern crate fs_extra; 6 | extern crate regex; 7 | extern crate tempfile; 8 | 9 | use std::fs; 10 | use std::path::{Path, PathBuf}; 11 | 12 | use clap::{Arg, Command}; 13 | 14 | mod errors; 15 | mod git; 16 | mod git_url_parser; 17 | 18 | // git-down main 19 | fn main() -> Result<(), errors::GitDownError> { 20 | let matches = Command::new("git-down") 21 | .version("0.3.0") 22 | .about("Download files from a git repo like a boss") 23 | .arg( 24 | Arg::new("directory") 25 | .short('d') 26 | .long("directory") 27 | .takes_value(true) 28 | .help("Download into this directory instead of the default one"), 29 | ) 30 | .arg(Arg::new("url").required(true)) 31 | .arg( 32 | Arg::new("files") 33 | .multiple_occurrences(true) 34 | .max_occurrences(10) 35 | .required(true), 36 | ) 37 | .get_matches(); 38 | 39 | let url = matches.value_of("url").unwrap(); 40 | let targets: Vec = matches 41 | .values_of("files") 42 | .unwrap() 43 | .map(|file| String::from(file)) 44 | .collect(); 45 | 46 | // Clone repository 47 | let git_url = git_url_parser::parse_url(&url)?; 48 | let git_dir = git::sparse_checkout(git_url.clone(), targets)?; 49 | 50 | let dest_path = if matches.is_present("directory") { 51 | PathBuf::from(matches.value_of("directory").unwrap()) 52 | } else { 53 | PathBuf::from(&git_url.name) 54 | }; 55 | 56 | move_files(&git_dir.contents(), &dest_path); 57 | 58 | Ok(()) 59 | } 60 | 61 | fn move_files(source_paths: &Vec, dest_path: &Path) { 62 | let options = fs_extra::dir::CopyOptions::new(); 63 | 64 | if !dest_path.exists() { 65 | fs::create_dir(dest_path).expect("Cannot create destination directory"); 66 | } 67 | 68 | let dest = dest_path.to_str().unwrap().to_string(); 69 | let mut sources: Vec = Vec::new(); 70 | 71 | for path in source_paths { 72 | sources.push(path.to_str().unwrap().to_string()); 73 | } 74 | 75 | fs_extra::move_items(&sources, &dest, &options) 76 | .expect(&format!("Failed to move files to {}", dest)); 77 | } 78 | -------------------------------------------------------------------------------- /src/git.rs: -------------------------------------------------------------------------------- 1 | use std::fs::remove_dir_all; 2 | use std::ops::Drop; 3 | use std::path::PathBuf; 4 | use std::process::Command; 5 | 6 | use crate::errors::GitDownError; 7 | use crate::git_url_parser::GitUrl; 8 | 9 | #[derive(Debug)] 10 | pub struct GitDir { 11 | remote_url: GitUrl, // URL to source repository 12 | target_files: Vec, // Files/folders to pull from remote 13 | local_dir: tempfile::TempDir, // Local partial copy of remote repository 14 | } 15 | 16 | impl GitDir { 17 | pub fn path(&self) -> Result<&str, GitDownError> { 18 | let path = self.local_dir.path().to_str(); 19 | match path { 20 | Some(p) => Ok(p), 21 | None => Err(GitDownError { 22 | message: String::from("Failed to read temp dir"), 23 | }), 24 | } 25 | } 26 | 27 | pub fn contents(&self) -> Vec { 28 | let mut paths: Vec = Vec::new(); 29 | let path = self.local_dir.path(); 30 | 31 | for filename in &self.target_files { 32 | let path_buf = path.join(filename); 33 | 34 | paths.push(path_buf); 35 | } 36 | 37 | paths 38 | } 39 | } 40 | 41 | impl Drop for GitDir { 42 | fn drop(&mut self) { 43 | remove_dir_all(self.local_dir.path()).unwrap(); 44 | } 45 | } 46 | 47 | pub fn sparse_checkout( 48 | remote_url: GitUrl, 49 | target_files: Vec, 50 | ) -> Result, GitDownError> { 51 | // TempDir deletes directory once it goes out of scope hence 52 | // boxing GitDir to prevent having copies outside of this 53 | // with a dangling local_dir 54 | let dir = Box::new(GitDir { 55 | remote_url, 56 | target_files, 57 | local_dir: tempfile::tempdir()?, 58 | }); 59 | 60 | println!("Cloning {}:{} into {}", dir.remote_url.url, dir.remote_url.branch, dir.path()?); 61 | exec_git(&dir, &["clone", "--filter=tree:0", "--no-checkout", &dir.remote_url.url, "."])?; 62 | exec_git(&dir, &["sparse-checkout", "init", "--cone"])?; 63 | 64 | let mut checkout_args = Vec::from(["sparse-checkout", "set"]); 65 | for path in &dir.target_files { 66 | checkout_args.push(path); 67 | } 68 | 69 | exec_git(&dir, &checkout_args)?; 70 | exec_git(&dir, &["checkout"])?; 71 | 72 | return Ok(dir); 73 | } 74 | 75 | fn exec_git(git_dir: &GitDir, git_command: &[&str]) -> Result<(), GitDownError> { 76 | println!("Running git {}...", git_command[0]); 77 | let mut command = Command::new("git"); 78 | let mut child = command 79 | .args(["-C", git_dir.path()?]) 80 | .args(git_command) 81 | .spawn()?; 82 | child.wait()?; 83 | 84 | Ok(()) 85 | } 86 | -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | Usage 2 | ===== 3 | 4 | It's really easy to use. 5 | 6 | ```sh 7 | $ git-down -d FILES 8 | ``` 9 | 10 | The `-d ` option above is optional. If not specified the files 11 | will be downloaded into a directory under the name of the target repository. 12 | 13 | > We're using the bootstrap repo as an example for how to use the command but it works with 14 | any repository. 15 | 16 | For example, running the following command will create a `bootstrap-dist` directory in the current 17 | working directory containing bootstrap's `dist` directory. 18 | 19 | ```sh 20 | $ git-down -d bootstrap-dist https://github.com/twbs/bootstrap.git:master dist 21 | ``` 22 | 23 | If bootstrap-dist above is not specified, a directory named bootstrap will be created 24 | instead. 25 | 26 | ## CLI 27 | 28 | ``` 29 | git-down 0.3.0 30 | Download files from a git repo like a boss 31 | 32 | USAGE: 33 | git-down [OPTIONS] ... 34 | 35 | ARGS: 36 | 37 | ... 38 | 39 | OPTIONS: 40 | -d, --directory Download into this directory instead of the default one 41 | -h, --help Print help information 42 | -V, --version Print version information 43 | ``` 44 | 45 | 46 | 47 | 48 | ## Download multiple directories 49 | 50 | You can use git-down to download multiple directories from the same repository. 51 | 52 | For example if you wanted to download both the dist and src directories from the Bootstrap repo you would 53 | use the following command. 54 | 55 | ```sh 56 | $ git-down https://github.com/twbs/bootstrap.git:master dist src 57 | ``` 58 | 59 | Get only the css directory 60 | 61 | ```sh 62 | $ git-down -d bootstrap-css gh:tbws/bootstrap:master dist/css 63 | ``` 64 | 65 | Get the css and img directories 66 | 67 | ```sh 68 | $ git-down -d boostrap-css-img gh:tbws/bootstrap:master dist/css dist/img 69 | ``` 70 | 71 | ## Shortcuts for Supported Services 72 | 73 | Shortcuts are intended to reduce keystrokes by allowing you to download from popular Git hosting 74 | services without typing out the full URL of the repository. When using shortcuts the parts of the _source_ are separated using colons (:). 75 | 76 | The following are working examples you can use for downloading a directory from 77 | supported services: 78 | 79 | ### `gh:` GitHub 80 | 81 | The following example command will download the dist directory from bootstrap repo 82 | into boostrap-latest from the GitHub repository. 83 | 84 | ```sh 85 | $ git-down -d bootstrap-latest gh:tbws/bootstrap:master dist 86 | ``` 87 | 88 | ### `bb:` BitBucket 89 | 90 | ```sh 91 | $ git-down -d sqlalchemy-examples bb:zzzeek/sqlalchemy:master examples 92 | ``` 93 | 94 | ### `gl:` GitLab 95 | 96 | ```sh 97 | $ git-down -d gitlab-scripts gl:gitlab-org/gitlab-ce:master scripts 98 | ``` 99 | 100 | ### `sf:` SourceForge 101 | 102 | ```sh 103 | $ git-down -d nagioscore-sample-config sf:nagios/nagios-core:master sample-config 104 | ``` 105 | -------------------------------------------------------------------------------- /src/git_url_parser.rs: -------------------------------------------------------------------------------- 1 | use regex::{Captures, Regex}; 2 | 3 | use crate::errors::GitDownError; 4 | 5 | #[derive(Debug, Clone)] 6 | pub struct GitUrl { 7 | pub url: String, // Full URL to repository (whether expanded from shortcut or as received from user 8 | pub name: String, // Name of the repository extracted from url above 9 | pub branch: String, // Target branch specified in the url 10 | } 11 | 12 | pub fn parse_url(url: &str) -> Result { 13 | if is_shortcut_url(url) { 14 | return parse_shortcut_url(url); 15 | } 16 | 17 | parse_http_url(url) 18 | } 19 | 20 | pub fn is_shortcut_url(url: &str) -> bool { 21 | // FIXME: Do not rely on hardcoded forms of the shortcuts. 22 | let regex = Regex::new(r"^(bb|gh|gl|sf):.*$").unwrap(); 23 | 24 | regex.is_match(url) 25 | } 26 | 27 | fn parse_shortcut_url(url: &str) -> Result { 28 | let regex = Regex::new( 29 | r"^(?P\w+):(?P[^.]+)/(?P[^.]+)(\.git)?(:(?P.*))", 30 | ) 31 | .unwrap(); 32 | let captures = match regex.captures(url) { 33 | Some(value) => value, 34 | None => { 35 | return Err(GitDownError { 36 | message: format!("Invalid url: {}", url), 37 | }) 38 | } 39 | }; 40 | 41 | let alias = read_url_part(&captures, "alias")?; 42 | let base_url = resolve_url_host_alias(&alias)?; 43 | let user = read_url_part(&captures, "user")?; 44 | let name = read_url_part(&captures, "repo_name")?; 45 | let branch = read_url_part(&captures, "branch")?; 46 | 47 | Ok(GitUrl { 48 | url: format!("{}/{}/{}", base_url, user, name), 49 | name, 50 | branch, 51 | }) 52 | } 53 | 54 | fn resolve_url_host_alias(alias: &str) -> Result { 55 | // TODO: Maybe have the aliasing done in some configuration file 56 | let host = match alias { 57 | "gh" => "https://github.com", 58 | "bb" => "https://bitbucket.org", 59 | "gl" => "https://gitlab.org", 60 | "sf" => "https://git.code.sf.net/p/", 61 | _ => { 62 | return Err(GitDownError { 63 | message: format!("Invalid host alias: {}", alias), 64 | }) 65 | } 66 | }; 67 | 68 | Ok(String::from(host)) 69 | } 70 | 71 | fn read_url_part(captures: &Captures, name: &str) -> Result { 72 | match captures.name(name) { 73 | Some(value) => Ok(value.as_str().to_string()), 74 | None => { 75 | return Err(GitDownError { 76 | message: format!("Invalid url: Missing '{}'", String::from(name)), 77 | }); 78 | } 79 | } 80 | } 81 | 82 | fn parse_http_url(url: &str) -> Result { 83 | let regex = Regex::new(r"^(?P.*/(?P[^.:/]+)(\.git)?)/?:(?P[^.]+)$").unwrap(); 84 | let captures = match regex.captures(url) { 85 | Some(value) => value, 86 | None => { 87 | return Err(GitDownError { 88 | message: format!("Invalid url: {}", url), 89 | }) 90 | } 91 | }; 92 | 93 | let branchless_url = read_url_part(&captures, "url")?; 94 | let name = read_url_part(&captures, "name")?; 95 | let branch = read_url_part(&captures, "branch")?; 96 | 97 | Ok(GitUrl { 98 | url: String::from(branchless_url), 99 | name, 100 | branch, 101 | }) 102 | } 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Git Down 2 | ======== 3 | 4 | `git-down` lets you download one or multiple directories from a Git repository without the 5 | hassle of cloning or downloading the whole repository, with one simple command. 6 | 7 | ## Usage 8 | 9 | It's really easy to use. 10 | 11 | ```sh 12 | $ git-down -d FILES 13 | ``` 14 | 15 | The `-d ` option above is optional. If not specified the files 16 | will be downloaded into a directory under the name of the target repository. 17 | 18 | > We're using the bootstrap repo as an example for how to use the command but it works with 19 | any repository. 20 | 21 | For example, running the following command will create a `bootstrap-dist` directory in the current 22 | working directory containing bootstrap's `dist` directory. 23 | 24 | ```sh 25 | $ git-down -d bootstrap-dist https://github.com/twbs/bootstrap.git:master dist 26 | ``` 27 | 28 | If bootstrap-dist above is not specified, a directory named bootstrap will be created 29 | instead. 30 | 31 | ### Download multiple directories 32 | 33 | You can use git-down to download multiple directories from the same repository. 34 | 35 | For example if you wanted to download both the dist and src directories from the Bootstrap repo you would 36 | use the following command. 37 | 38 | ```sh 39 | $ git-down https://github.com/twbs/bootstrap.git:master dist src 40 | ``` 41 | 42 | ### Shortcuts 43 | 44 | Shortcuts are intended to reduce keystrokes by allowing you to download from popular Git hosting 45 | services without typing out the full URL of the repository. 46 | 47 | When using shortcuts the parts of the _source_ are separated using colons (:). 48 | 49 | The following are working examples you can use for downloading a directory from 50 | supported services: 51 | 52 | **GitHub** 53 | 54 | The following example command will download the dist directory from bootstrap repo 55 | into boostrap-latest from the GitHub repository. 56 | 57 | ```sh 58 | $ git-down -d bootstrap-latest gh:tbws/bootstrap:master dist 59 | ``` 60 | 61 | Get only the css directory 62 | 63 | ```sh 64 | $ git-down -d bootstrap-css gh:tbws/bootstrap:master dist/css 65 | ``` 66 | 67 | Get the css and img directories 68 | 69 | ```sh 70 | $ git-down -d boostrap-css-img gh:tbws/bootstrap:master dist/css dist/img 71 | ``` 72 | 73 | **BitBucket** 74 | 75 | ```sh 76 | $ git-down -d sqlalchemy-examples bb:zzzeek/sqlalchemy:master examples 77 | ``` 78 | 79 | **GitLab** 80 | 81 | ```sh 82 | $ git-down -d gitlab-scripts gl:gitlab-org/gitlab-ce:master scripts 83 | ``` 84 | 85 | **SourceForge** 86 | 87 | ```sh 88 | $ git-down -d nagioscore-sample-config sf:nagios/nagios-core:master sample-config 89 | ``` 90 | 91 | ## Why do I need this in my life? 92 | 93 | It will save you time. Currently all of the ways to get just one directory from a repository 94 | require either _too much_ clicking or typing! 95 | 96 | If you want to download just one (or multiple) directory from a Git repository - 97 | like a `dist` directory of a project like bootstrap - you have several ways of 98 | doing so, including: 99 | 100 | **Download the archive and extract** 101 | 102 | The easiest and most straight-forward approach is to download the archive 103 | of the repo, extract the files and get the files/directory you want. 104 | This works best if you can get the archive via a web interface via a *Download* 105 | button/link - which can be annoying to find in some products (BitBucket!). 106 | 107 | **Shallow clone and mv** 108 | 109 | Another way is to do a shallow clone and get the directories you want using a move command. 110 | It's just too many commands and typing! 111 | 112 | For example, getting the dist directory from bootstrap you would do something like: 113 | 114 | ```sh 115 | $ git clone --depth 1 https://github.com/twbs/boostrap.git 116 | $ cd bootstrap 117 | $ mv ./dist ~/stuff/boostrap-latest 118 | ``` 119 | 120 | C'mon, you don't have the time to be doing all that. 121 | 122 | ## Installation 123 | 124 | No pre-packaged binaries - you have to build it yourself, sorry. :/ 125 | 126 | You will have to install Rust. I highly recommend using [rustup](https://www.rustup.rs) 127 | 128 | ```sh 129 | $ git clone https://github.com/zikani03/git-down.git 130 | $ cd git-down 131 | $ cargo build --release 132 | $ mv target/release/git-down ~/bin/git-down 133 | ``` 134 | 135 | Assuming your `~/bin` is on your PATH you can now use it from the shell as `git-down` 136 | 137 | ## Planned Features 138 | 139 | ### From a different commit, tag, revision 140 | 141 | This would be nice, me thinks :) 142 | 143 | ```sh 144 | $ git-down -f v3.3.2 gh:twbs/bootstrap:dist bootstrap-3.3.2 145 | ``` 146 | 147 | Now, git down to business! 148 | 149 | # LICENCE 150 | 151 | MIT 152 | 153 | --- 154 | Copyright (c) 2017, Zikani Nyirenda Mwase 155 | -------------------------------------------------------------------------------- /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 = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "atty" 16 | version = "0.2.14" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 19 | dependencies = [ 20 | "hermit-abi", 21 | "libc", 22 | "winapi", 23 | ] 24 | 25 | [[package]] 26 | name = "autocfg" 27 | version = "1.1.0" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 30 | 31 | [[package]] 32 | name = "bitflags" 33 | version = "1.3.2" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 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.1.8" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" 48 | dependencies = [ 49 | "atty", 50 | "bitflags", 51 | "indexmap", 52 | "os_str_bytes", 53 | "strsim", 54 | "termcolor", 55 | "textwrap", 56 | ] 57 | 58 | [[package]] 59 | name = "fastrand" 60 | version = "1.7.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" 63 | dependencies = [ 64 | "instant", 65 | ] 66 | 67 | [[package]] 68 | name = "fs_extra" 69 | version = "1.2.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" 72 | 73 | [[package]] 74 | name = "git-down" 75 | version = "0.3.0-beta" 76 | dependencies = [ 77 | "clap", 78 | "fs_extra", 79 | "regex", 80 | "tempfile", 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 = "indexmap" 100 | version = "1.8.1" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" 103 | dependencies = [ 104 | "autocfg", 105 | "hashbrown", 106 | ] 107 | 108 | [[package]] 109 | name = "instant" 110 | version = "0.1.12" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 113 | dependencies = [ 114 | "cfg-if", 115 | ] 116 | 117 | [[package]] 118 | name = "libc" 119 | version = "0.2.122" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" 122 | 123 | [[package]] 124 | name = "memchr" 125 | version = "2.4.1" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 128 | 129 | [[package]] 130 | name = "os_str_bytes" 131 | version = "6.0.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" 134 | dependencies = [ 135 | "memchr", 136 | ] 137 | 138 | [[package]] 139 | name = "redox_syscall" 140 | version = "0.2.13" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" 143 | dependencies = [ 144 | "bitflags", 145 | ] 146 | 147 | [[package]] 148 | name = "regex" 149 | version = "1.5.5" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" 152 | dependencies = [ 153 | "aho-corasick", 154 | "memchr", 155 | "regex-syntax", 156 | ] 157 | 158 | [[package]] 159 | name = "regex-syntax" 160 | version = "0.6.25" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 163 | 164 | [[package]] 165 | name = "remove_dir_all" 166 | version = "0.5.3" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 169 | dependencies = [ 170 | "winapi", 171 | ] 172 | 173 | [[package]] 174 | name = "strsim" 175 | version = "0.10.0" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 178 | 179 | [[package]] 180 | name = "tempfile" 181 | version = "3.3.0" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 184 | dependencies = [ 185 | "cfg-if", 186 | "fastrand", 187 | "libc", 188 | "redox_syscall", 189 | "remove_dir_all", 190 | "winapi", 191 | ] 192 | 193 | [[package]] 194 | name = "termcolor" 195 | version = "1.1.3" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 198 | dependencies = [ 199 | "winapi-util", 200 | ] 201 | 202 | [[package]] 203 | name = "textwrap" 204 | version = "0.15.0" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" 207 | 208 | [[package]] 209 | name = "winapi" 210 | version = "0.3.9" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 213 | dependencies = [ 214 | "winapi-i686-pc-windows-gnu", 215 | "winapi-x86_64-pc-windows-gnu", 216 | ] 217 | 218 | [[package]] 219 | name = "winapi-i686-pc-windows-gnu" 220 | version = "0.4.0" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 223 | 224 | [[package]] 225 | name = "winapi-util" 226 | version = "0.1.5" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 229 | dependencies = [ 230 | "winapi", 231 | ] 232 | 233 | [[package]] 234 | name = "winapi-x86_64-pc-windows-gnu" 235 | version = "0.4.0" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 238 | --------------------------------------------------------------------------------