Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#32] Add tag option to download a specific tool version #61

Merged
merged 2 commits into from
Sep 3, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ owner = "XAMPPRocky" # GitHub username
repo = "tokei" # GitHub repository
exe_name = "tokei" # Executable name inside the asset

# uncomment to download a specific version or tag
# tag = "12.1.1"
Comment on lines +125 to +126
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating the documentation as well! 👏🏻


# Asset name to download on linux OSes
asset_name.linux = "x86_64-unknown-linux-musl"

Expand Down
4 changes: 4 additions & 0 deletions src/config/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ pub struct ConfigAsset {

/// Name of the specific asset to download
pub asset_name: AssetName,

/// Release tag to download
/// Defaults to the latest release
pub tag: Option<String>,
}

impl Config {
Expand Down
7 changes: 7 additions & 0 deletions src/config/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ fn decode_config_asset(table: &Map<String, Value>) -> ConfigAsset {
let repo = str_by_key(table, "repo");
let exe_name = str_by_key(table, "exe_name");
let asset_name = decode_asset_name(table);
let tag = str_by_key(table, "tag");

ConfigAsset {
owner,
repo,
exe_name,
asset_name,
tag,
}
}

Expand Down Expand Up @@ -161,6 +163,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
},
)]),
};
Expand Down Expand Up @@ -193,6 +196,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
},
),
(
Expand All @@ -206,6 +210,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
},
),
]),
Expand Down Expand Up @@ -239,6 +244,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
},
)]),
};
Expand Down Expand Up @@ -275,6 +281,7 @@ mod tests {
macos: Some("C3-PO".to_owned()),
windows: Some("IG-88".to_owned()),
},
tag: None,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test single_full_tool checks all the fields in a single TOML table of a tool. So let's add tag to the TOML text and expect Some(...) in this last test

},
)]),
};
Expand Down
22 changes: 22 additions & 0 deletions src/model/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ impl ToolError {
}
}

/// Determines whether to download the latest version of a tool or a
/// specific version of it.
#[derive(Debug, PartialEq, Eq)]
pub enum ToolInfoTag {
/// Download latest
Latest,
/// Download a specific version
Specific(String),
}

impl ToolInfoTag {
pub fn as_specific_tag(&self) -> Option<&str> {
match self {
Self::Latest => None,
Self::Specific(version) => Some(&version),
}
}
}

/// All info about installing a tool from GitHub releases
#[derive(Debug, PartialEq, Eq)]
pub struct ToolInfo {
Expand All @@ -40,4 +59,7 @@ pub struct ToolInfo {

/// Asset name depending on the OS
pub asset_name: AssetName,

/// Version tag
pub tag: ToolInfoTag,
}
29 changes: 25 additions & 4 deletions src/sync/configure.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::config::schema::ConfigAsset;
use crate::model::asset_name::AssetName;
use crate::model::tool::{Tool, ToolError, ToolInfo};
use crate::model::tool::{Tool, ToolError, ToolInfo, ToolInfoTag};
use crate::sync::db::lookup_tool;

pub fn configure_tool(tool_name: &str, config_asset: &ConfigAsset) -> Tool {
Expand Down Expand Up @@ -32,6 +32,11 @@ fn full_configure(config_asset: &ConfigAsset) -> Option<ToolInfo> {
let owner = config_asset.owner.clone()?;
let repo = config_asset.repo.clone()?;
let exe_name = config_asset.exe_name.clone()?;
let tag = config_asset
.tag
.clone()
.map(|version| ToolInfoTag::Specific(version))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure but I believe this simplification should compile 🤔

Suggested change
.map(|version| ToolInfoTag::Specific(version))
.map(ToolInfoTag::Specific)

.unwrap_or(ToolInfoTag::Latest);

Some(ToolInfo {
owner,
Expand All @@ -42,6 +47,7 @@ fn full_configure(config_asset: &ConfigAsset) -> Option<ToolInfo> {
macos: config_asset.asset_name.macos.clone(),
windows: config_asset.asset_name.windows.clone(),
},
tag,
})
}

Expand Down Expand Up @@ -78,6 +84,11 @@ impl ToolInfo {
.clone()
.or_else(|| self.asset_name.windows.clone()),
},
tag: config_asset
.tag
.clone()
.map(|version| ToolInfoTag::Specific(version))
.unwrap_or(ToolInfoTag::Latest),
}
}
}
Expand All @@ -99,6 +110,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
};

assert_eq!(
Expand All @@ -120,6 +132,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
};

assert_eq!(
Expand All @@ -141,6 +154,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
};

assert_eq!(
Expand All @@ -164,6 +178,7 @@ mod tests {
macos: None,
windows: None,
},
tag: Some(String::from("1.2.3")),
};

assert_eq!(
Expand All @@ -185,6 +200,7 @@ mod tests {
macos: Some(String::from("my-macos")),
windows: Some(String::from("yours-windows")),
},
tag: Some(String::from("1.2.3")),
};

assert_eq!(
Expand All @@ -197,7 +213,8 @@ mod tests {
linux: Some("my-linux".to_string()),
macos: Some("my-macos".to_string()),
windows: Some("yours-windows".to_string()),
}
},
tag: ToolInfoTag::Specific("1.2.3".to_string()),
})
);
}
Expand All @@ -215,6 +232,7 @@ mod tests {
macos: None,
windows: None,
},
tag: None,
};

assert_eq!(
Expand All @@ -227,7 +245,8 @@ mod tests {
linux: Some("unknown-linux-musl".to_string()),
macos: Some("apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
}
},
tag: ToolInfoTag::Latest,
})
);
}
Expand All @@ -245,6 +264,7 @@ mod tests {
macos: Some(String::from("my-macos")),
windows: Some(String::from("yours-windows")),
},
tag: Some(String::from("3.2.1")),
};

assert_eq!(
Expand All @@ -257,7 +277,8 @@ mod tests {
linux: Some("my-linux".to_string()),
macos: Some("my-macos".to_string()),
windows: Some("yours-windows".to_string()),
}
},
tag: ToolInfoTag::Specific("3.2.1".to_string()),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really appreciate updated tests 🙏🏻

})
);
}
Expand Down
9 changes: 8 additions & 1 deletion src/sync/db.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::model::asset_name::AssetName;
use crate::model::tool::ToolInfo;
use crate::model::tool::{ToolInfo, ToolInfoTag};

/// Get info about known tools from a hardcoded database
pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
Expand All @@ -13,6 +13,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("x86_64-apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
},
tag: ToolInfoTag::Latest,
}),
"difftastic" => Some(ToolInfo {
owner: "Wilfred".to_string(),
Expand All @@ -23,6 +24,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("x86_64-apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
},
tag: ToolInfoTag::Latest,
}),
"exa" => Some(ToolInfo {
owner: "ogham".to_string(),
Expand All @@ -33,6 +35,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("macos-x86_64".to_string()),
windows: None,
},
tag: ToolInfoTag::Latest,
}),
"fd" => Some(ToolInfo {
owner: "sharkdp".to_string(),
Expand All @@ -43,6 +46,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("x86_64-apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
},
tag: ToolInfoTag::Latest,
}),
"ripgrep" => Some(ToolInfo {
owner: "BurntSushi".to_string(),
Expand All @@ -53,6 +57,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
},
tag: ToolInfoTag::Latest,
}),
"tool-sync" => Some(ToolInfo {
owner: "chshersh".to_string(),
Expand All @@ -63,6 +68,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
macos: Some("x86_64-apple-darwin".to_string()),
windows: Some("x86_64-pc-windows-msvc".to_string()),
},
tag: ToolInfoTag::Latest,
}),
// "tokei" => Some(ToolInfo {
// owner: "XAMPPRocky".to_string(),
Expand All @@ -73,6 +79,7 @@ pub fn lookup_tool(tool_name: &str) -> Option<ToolInfo> {
// macos: Some("apple-darwin".to_string()),
// windows: Some("x86_64-pc-windows-msvc".to_string()),
// }
// tag: ToolInfoTag::Latest,
// }),
_ => None,
}
Expand Down
59 changes: 54 additions & 5 deletions src/sync/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Downloader<'a> {
pub owner: &'a str,
pub repo: &'a str,
pub asset_name: &'a str,
pub specific_tag: &'a Option<&'a str>,
pub pb_msg: &'a ProgressBar,
pub sync_progress: &'a SyncProgress,
}
Expand All @@ -24,11 +25,20 @@ pub struct DownloadInfo {

impl<'a> Downloader<'a> {
fn release_url(&self) -> String {
format!(
"https://api.github.com/repos/{owner}/{repo}/releases/latest",
owner = self.owner,
repo = self.repo
)
if let Some(tag) = self.specific_tag {
format!(
"https://api.github.com/repos/{owner}/{repo}/releases/tags/{tag}",
owner = self.owner,
repo = self.repo,
tag = tag,
)
} else {
format!(
"https://api.github.com/repos/{owner}/{repo}/releases/latest",
owner = self.owner,
repo = self.repo,
)
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose a slight simplification to this logic. Let's rename as_specific_tag to to_str_version and make this function return String.

This way, this formatting could be just:

format!(
    "https://api.github.com/repos/{owner}/{repo}/releases/{version}",
    owner = self.owner,
    repo = self.repo,
    version = tag.to_str_version(),
)

}

fn asset_url(&self, asset_id: u32) -> String {
Expand Down Expand Up @@ -118,3 +128,42 @@ pub fn add_auth_header(req: ureq::Request) -> ureq::Request {
Ok(token) => req.set("Authorization", &format!("token {}", token)),
}
}

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

#[test]
fn release_url_with_no_specific_tag_is_correct() {
let downloader = Downloader {
owner: "OWNER",
repo: "REPO",
asset_name: "ASSET_NAME",
specific_tag: &None,
pb_msg: &ProgressBar::hidden(),
sync_progress: &SyncProgress::new(vec!["tool".to_string()]),
};

assert_eq!(
downloader.release_url(),
"https://api.github.com/repos/OWNER/REPO/releases/latest"
);
}

#[test]
fn release_url_with_specific_tag_is_correct() {
let downloader = Downloader {
owner: "OWNER",
repo: "REPO",
asset_name: "ASSET_NAME",
specific_tag: &Some("SPECIFIC_TAG"),
pb_msg: &ProgressBar::hidden(),
sync_progress: &SyncProgress::new(vec!["tool".to_string()]),
};

assert_eq!(
downloader.release_url(),
"https://api.github.com/repos/OWNER/REPO/releases/tags/SPECIFIC_TAG"
);
}
}
1 change: 1 addition & 0 deletions src/sync/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl Installer {
let downloader = Downloader {
owner: &tool_info.owner,
repo: &tool_info.repo,
specific_tag: &tool_info.tag.as_specific_tag(),
sync_progress: &self.sync_progress,
pb_msg,
asset_name,
Expand Down