Skip to content

Commit

Permalink
[cleanup:app] added readme, minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
alok8bb committed Aug 7, 2021
1 parent 7cdc249 commit 44402e1
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 31 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
name = "cloneit"
version = "0.1.0"
edition = "2018"

authors = ["Alok <alok8bb@gmail.com>"]
description = "A commandline tool to download specific GitHub directories or files"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# cloneit

A cli tool to download specific GitHub directories or files.

# Installation

### From git

```bash
git clone https://github.com/alok8bb/cloneit
cd cloneit
cargo install build --release
```

# Usage

```
cloneit 1.0
Alok P <alok8bb@gmail.com>
Download specific GitHub directories or files
USAGE:
cloneit [FLAGS] <URL>
ARGS:
<URL> URL to the GitHub directory
FLAGS:
-h, --help Prints help information
-l Generate download link to zipped file
-V, --version Prints version information
-z Download zipped directory
```

# Examples

### Downloading

```bash
$ cloneit https://github.com/alok8bb/cloneit
```

```bash
$ cloneit https://github.com/alok8bb/cloneit/tree/master/src
```

```bash
$ cloneit https://github.com/alok8bb/cloneit/tree/master/src/main.rs
```

### Zipped File - WIP

```bash
$ cloneit -z https://github.com/alok8bb/cloneit
```

# Todo

- [ ] Downloading zipped directories
- [ ] Uploading File
- [ ] Advanced Error Handling
- [ ] Code Refactoring
6 changes: 3 additions & 3 deletions src/cli.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: cit
name: cloneit
version: "1.0"
author: Alok P <alok8bb@gmail.com>
about: Clone specific GitHub directories
about: Download specific GitHub directories or files
args:
- URL:
about: URL to the GitHub directory
Expand All @@ -10,7 +10,7 @@ args:
- zip:
short: z
multiple: false
about: Clone zipped directory
about: Download zipped directory
- link:
short: l
multiple: false
Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async fn main() {

println!(
"{} {}Validating url...",
style("[1/2]").bold().dim(),
style("[1/3]").bold().dim(),
output::LOOKING_GLASS
);
let path = match utils::parser::parse_url(url.unwrap()) {
Expand All @@ -36,14 +36,14 @@ async fn main() {

println!(
"{} {}Downloading...",
style("[2/2]").bold().dim(),
style("[2/3]").bold().dim(),
output::TRUCK
);

match utils::parser::fetch_data(data).await {
Err(err) => println!("{}", err.to_string().red()),
Ok(_) => println!(
"{} {}Cloned Successfully.",
"{} {}Downloaded Successfully.",
style("[3/3]").bold().dim(),
output::SPARKLES
),
Expand Down
5 changes: 1 addition & 4 deletions src/utils/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,7 @@ pub async fn fetch_data(data: Directory) -> Result<(), Box<dyn Error>> {
let path = format!("./{}", data.root);
fs::create_dir(&path)?;

match requests::get_dir(url, &client, Path::new(&path)).await {
Err(err) => println!("{}", err.to_string()),
Ok(_) => (),
};
requests::get_dir(url, &client, Path::new(&path)).await?;

Ok(())
}
40 changes: 20 additions & 20 deletions src/utils/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::path::Path;
use std::{error::Error, fs};
use tokio::io::AsyncWriteExt;

pub type ApiData = Vec<ApiDatum>;
pub type ApiData = Vec<ApiOjbect>;

#[derive(Serialize, Deserialize, Debug)]
pub struct ApiDatum {
pub struct ApiOjbect {
name: String,
path: String,
sha: String,
Expand All @@ -34,22 +34,23 @@ pub struct Links {

#[async_recursion]
pub async fn get_dir(url: String, client: &Client, dir: &Path) -> Result<(), Box<dyn Error>> {
let res = client
let res: String = client
.get(url)
.header("User-Agent", "request")
.send()
.await?
.text()
.await?;

// Check if single file was given (download directly)
if res.starts_with("{") {
let data: ApiDatum = serde_json::from_str(&res)?;
let ojb: ApiOjbect = serde_json::from_str(&res)?;

get_filedata(data.download_url.unwrap(), client, data.name, dir).await?;
get_filedata(ojb.download_url.unwrap(), client, ojb.name, dir).await?;
} else {
let res_data: ApiData = serde_json::from_str(&res)?;
let api_data: ApiData = serde_json::from_str(&res)?;

for obj in res_data {
for obj in api_data {
if obj.api_datum_type == "dir" {
let dir_name = dir.join(obj.name);
fs::create_dir(&dir_name)?;
Expand All @@ -67,19 +68,18 @@ pub async fn get_dir(url: String, client: &Client, dir: &Path) -> Result<(), Box
pub async fn get_filedata(
url: String,
client: &Client,
file_name: String,
filename: String,
dir: &Path,
) -> Result<(), Box<dyn Error>> {
let download_size = {
let resp = client.head(url.as_str()).send().await?;
if resp.status().is_success() {
resp.headers() // Gives is the HeaderMap
.get(header::CONTENT_LENGTH) // Gives us an Option containing the HeaderValue
.and_then(|ct_len| ct_len.to_str().ok()) // Unwraps the Option as &str
.and_then(|ct_len| ct_len.parse().ok()) // Parses the Option as u64
.unwrap_or(0) // Fallback to 0
resp.headers()
.get(header::CONTENT_LENGTH)
.and_then(|ct_len| ct_len.to_str().ok())
.and_then(|ct_len| ct_len.parse().ok())
.unwrap_or(0)
} else {
// We return an Error if something goes wrong here
return Err(
format!("Couldn't download URL: {}. Error: {:?}", url, resp.status(),).into(),
);
Expand All @@ -91,21 +91,21 @@ pub async fn get_filedata(

progress_bar.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:60.cyan/blue}] {bytes}/{total_bytes} - {wide_msg}")
.template("{spinner:.green} [{elapsed_precise}] [{bar:60.cyan/blue}] {bytes}/{total_bytes} {msg}")
.progress_chars("- C * "),
);
progress_bar.set_message(file_name.clone());
progress_bar.set_message(filename.clone());

let mut outfile = tokio::fs::File::create(dir.join(file_name.clone())).await?;
let mut outfile = tokio::fs::File::create(dir.join(filename.clone())).await?;

let mut download = req.send().await?;
while let Some(chunk) = download.chunk().await? {
progress_bar.inc(chunk.len() as u64); // Increase ProgressBar by chunk size
progress_bar.inc(chunk.len() as u64); // Increase Progressbar

outfile.write(&chunk).await?; // Write chunk to output file
outfile.write(&chunk).await?;
}

progress_bar.finish_with_message(file_name);
progress_bar.finish_with_message(filename);

Ok(())
}

0 comments on commit 44402e1

Please sign in to comment.