Skip to content

Commit

Permalink
[chshersh#63] Added tag support in download progress (chshersh#64)
Browse files Browse the repository at this point in the history
Resolves chshersh#63

Added a `max_tag_size` on `SyncProgress` to prepare the output message
for tags
that are longer than normal.

```bash
$ cargo run -- --config test-tools.toml sync
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/tool --config test-tools.toml sync`
⛔  bat     asdkjhkasdjfaksjdfhk;j [error] https://api.github.com/repos/sharkdp/bat/releases/tags/asdkjhkasdjfaksjdfhk;j: status code 404
✅  exa     v0.10.1                Completed!
✅  fd      v8.4.0                 Completed!
✅  ripgrep 13.0.0                 Completed!


$ cat test-tools.toml 
# This file was automatically generated by tool-sync
#
store_directory = "./bins"

    [bat]
        owner =     "sharkdp"
        repo =      "bat"
        exe_name =  "bat"
        tag =       "asdkjhkasdjfaksjdfhk;j"
    [exa]
        owner =     "ogham"
        repo =      "exa"
        exe_name =  "exa"
        tag =       "v0.10.1"
    [fd]
        owner =     "sharkdp"
        repo =      "fd"
        exe_name =  "fd"
        tag =       "v8.4.0"
    [ripgrep]
        owner =     "BurntSushi"
        repo =      "ripgrep"
        exe_name =  "rg"
        tag =       "13.0.0"
```
  • Loading branch information
MitchellBerend authored Sep 7, 2022
1 parent c790adc commit eeed4bb
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 13 deletions.
7 changes: 6 additions & 1 deletion src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ For more details, refer to the official documentation:
let store_directory = config.ensure_store_directory();

let tools: Vec<String> = config.tools.keys().cloned().collect();
let sync_progress = SyncProgress::new(tools);
let tags: Vec<String> = config
.tools
.values()
.map(|config_asset| config_asset.tag.clone().unwrap_or_else(|| "latest".into()))
.collect();
let sync_progress = SyncProgress::new(tools, tags);
let installer = Installer::mk(store_directory, sync_progress);

for (tool_name, config_asset) in config.tools.iter() {
Expand Down
4 changes: 2 additions & 2 deletions src/sync/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ mod tests {
asset_name: "ASSET_NAME",
version: &ToolInfoTag::Latest.to_str_version(),
pb_msg: &ProgressBar::hidden(),
sync_progress: &SyncProgress::new(vec!["tool".to_string()]),
sync_progress: &SyncProgress::new(vec!["tool".to_string()], vec!["latest".to_string()]),
};

assert_eq!(
Expand All @@ -154,7 +154,7 @@ mod tests {
asset_name: "ASSET_NAME",
version: &ToolInfoTag::Specific("SPECIFIC_TAG".to_string()).to_str_version(),
pb_msg: &ProgressBar::hidden(),
sync_progress: &SyncProgress::new(vec!["tool".to_string()]),
sync_progress: &SyncProgress::new(vec!["tool".to_string()], vec!["latest".to_string()]),
};

assert_eq!(
Expand Down
8 changes: 5 additions & 3 deletions src/sync/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ impl Installer {
}

pub fn install(&self, tool_name: &str, config_asset: &ConfigAsset) {
let pb_msg = self.sync_progress.create_message_bar(tool_name);
let tag: String = config_asset.tag.clone().unwrap_or_else(|| "latest".into());
let pb_msg = self.sync_progress.create_message_bar(tool_name, &tag);

match configure_tool(tool_name, config_asset) {
Tool::Known(tool_info) => match self.sync_single_tool(&tool_info, &pb_msg) {
Expand All @@ -50,11 +51,12 @@ impl Installer {
}
Err(e) => {
self.sync_progress
.failure(pb_msg, tool_name, format!("[error] {}", e));
.failure(pb_msg, tool_name, &tag, format!("[error] {}", e));
}
},
Tool::Error(e) => {
self.sync_progress.failure(pb_msg, tool_name, e.display());
self.sync_progress
.failure(pb_msg, tool_name, &tag, e.display());
}
}
}
Expand Down
72 changes: 65 additions & 7 deletions src/sync/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,57 @@ use indicatif::{MultiProgress, ProgressBar, ProgressStyle};

pub struct SyncProgress {
max_tool_size: usize,
max_tag_size: usize,
multi_progress: MultiProgress,
}

const SUCCESS: Emoji<'_, '_> = Emoji("✅ ", "OK ");
const FAILURE: Emoji<'_, '_> = Emoji("⛔ ", "NO ");
const PROCESS: Emoji<'_, '_> = Emoji("📥 ", ".. ");
const MIN_TAG_SIZE: usize = 8;

impl SyncProgress {
/// Creates new `SyncProgress` from a list of tools.
/// !!! The given `Vec` must be non-empty !!!
pub fn new(tools: Vec<String>) -> SyncProgress {
pub fn new(tools: Vec<String>, tags: Vec<String>) -> SyncProgress {
// unwrap is safe here because 'new' is called with a non-empty vector
let max_tool_size = tools.iter().map(|tool| tool.len()).max().unwrap();

// putting a default of 8 here since tags like v0.10.10 is already 8
let max_tag_size = tags
.iter()
.map(|tag| std::cmp::max(tag.len(), MIN_TAG_SIZE))
.max()
.unwrap_or(MIN_TAG_SIZE);

let multi_progress = MultiProgress::new();

SyncProgress {
max_tool_size,
max_tag_size,
multi_progress,
}
}

fn fmt_prefix(&self, emoji: Emoji, tool_name: &str, tag_name: &str) -> String {
let aligned_tool = format!(
"{:width$} {:<8}",
"{:tool_width$} {:tag_width$}",
tool_name,
tag_name,
width = self.max_tool_size
tool_width = self.max_tool_size,
tag_width = self.max_tag_size,
);

format!("{}{}", emoji, aligned_tool)
}

pub fn create_message_bar(&self, tool_name: &str) -> ProgressBar {
pub fn create_message_bar(&self, tool_name: &str, tag_name: &str) -> ProgressBar {
let message_style = ProgressStyle::with_template("{prefix:.bold.dim} {msg}").unwrap();

self.multi_progress.add(
ProgressBar::new(100)
.with_style(message_style)
.with_prefix(self.fmt_prefix(PROCESS, tool_name, "")),
.with_prefix(self.fmt_prefix(PROCESS, tool_name, tag_name)),
)
}

Expand All @@ -66,11 +77,58 @@ impl SyncProgress {
pb.finish();
}

pub fn failure(&self, pb: ProgressBar, tool_name: &str, err_msg: String) {
pb.set_prefix(self.fmt_prefix(FAILURE, tool_name, ""));
pub fn failure(&self, pb: ProgressBar, tool_name: &str, tag_name: &str, err_msg: String) {
pb.set_prefix(self.fmt_prefix(FAILURE, tool_name, tag_name));

let failure_msg = format!("{}", style(err_msg).red());
pb.set_message(failure_msg);
pb.finish();
}
}

#[cfg(test)]
mod tests {
use super::SyncProgress;

#[test]
fn test_max_tag_size_specific() {
let tags: Vec<String> = vec![
String::from("v10.10.100"),
String::from("latest"),
String::from("latest"),
];
let tools: Vec<String> = vec![
String::from("ripgrep"),
String::from("bat"),
String::from("exa"),
];

let progres = SyncProgress::new(tools, tags);

// v10.10.100 is 10 characters
assert_eq!(progres.max_tag_size, 10);
// ripgrep is 7 characters
assert_eq!(progres.max_tool_size, 7);
}

#[test]
fn test_max_tag_size_latest() {
let tags: Vec<String> = vec![
String::from("latest"),
String::from("latest"),
String::from("latest"),
];
let tools: Vec<String> = vec![
String::from("ripgrep"),
String::from("bat"),
String::from("exa"),
];

let progres = SyncProgress::new(tools, tags);

// latest is 6 characters so it should default to 8
assert_eq!(progres.max_tag_size, 8);
// ripgrep is 7 characters
assert_eq!(progres.max_tool_size, 7);
}
}

0 comments on commit eeed4bb

Please sign in to comment.