chshersh / tool-sync

🧰 Download pre-built binaries of all your favourite tools with a single command
https://crates.io/crates/tool-sync
Mozilla Public License 2.0
69 stars 16 forks source link

groundwork for shellcheck #146

Open hdhoang opened 1 year ago

hdhoang commented 1 year ago

hello again!

SC has only 1 public release, and well integrated in distro package managers. But it brings up some fun challenges too:

tar tf shellcheck-v0.8.0.linux.x86_64.tar.xz
shellcheck-v0.8.0/LICENSE.txt
shellcheck-v0.8.0/README.txt
shellcheck-v0.8.0/shellcheck

The windows zip puts shellcheck.exe in toplevel, so it works for me right away.

For the dir guessing, i attempted suffix trimming:

    let platforms = [".x86_64", ".linux"];
    let mut raw_asset = asset_name;
    for p in platforms {
        raw_asset = raw_asset.trim_end_matches(p)
    }
    vec![
        [raw_asset, &exe_name].iter().collect(),
    // .... original guesses

but the platforms list, as well as other projects' delimiter styles will make this complex fast. What do you think about using glob for finding the executable?


For xz, i plan to:

  1. Use early-return in Archive::from to avoid rightward drift, and match more tar types
  2. switch on the tar_path extension to use different types as tar_decoder, return error for unsupported compression
  3. rename TarGz type to be more general TarBall

How do you like this?

cheers

chshersh commented 1 year ago

@hdhoang Thanks for writing the detailed implementation plan! The ${project}-v${version} naming scheme is used in hlint as well (another CLI tool I use and would like to support) so it makes sense to support it.

Ideally, I would like to have a separate PR for .xz support. But we need an asset to actually test it and so far shellcheck is the only tool that uses .xz. So, in an ideal world, I'd like to have three separate PRs:

  1. Support xz (with the early-return and other refactorings as you suggest)
  2. Support the new project naming scheme
  3. Support shellcheck

But we need something to test this so a single PR for this case is acceptable 👌🏻

but the platforms list, as well as other projects' delimiter styles will make this complex fast. What do you think about using glob for finding the executable?

The path part is rather simple: ${project}-v${version}. So I think that glob would be an overkill. We only need to get the version and combine it with the project name.

This should be enough for shellcheck and hlint:

So I imagine, the final function would look like this:

// List of potential paths where an executable can be inside the archive
fn exe_paths(exe_name: &str, asset_name: &str, tool_name: &str, version: &str) -> Vec<PathBuf> {
    let exe_name = mk_exe_name(exe_name);
    let content_dirs =
        mk_asset_dir_name(tool_name, version); // returns two elements here: with 'v' and without 'v' prefix

    vec![
        [asset_name, &exe_name].iter().collect(),
        [&exe_name].iter().collect(),
        ["bin", &exe_name].iter().collect(),
        [asset_name, "bin", &exe_name].iter().collect(),
        [content_dir, &exe_name].iter().collect(),
    ] ... combine with [content_dir, &exe_name] for each content dir
}