added zip support, pkg-fmt override

swapped CI to build zips for windows
This commit is contained in:
ryan 2021-04-08 18:39:54 +12:00
parent 94ad0db41d
commit 1c25b1346f
7 changed files with 160 additions and 24 deletions

View file

@ -22,15 +22,19 @@ jobs:
- target: x86_64-unknown-linux-gnu - target: x86_64-unknown-linux-gnu
os: ubuntu-latest os: ubuntu-latest
output: cargo-binstall output: cargo-binstall
archive: tgz
- target: x86_64-apple-darwin - target: x86_64-apple-darwin
os: macos-latest os: macos-latest
output: cargo-binstall output: cargo-binstall
archive: tgz
- target: armv7-unknown-linux-gnueabihf - target: armv7-unknown-linux-gnueabihf
os: ubuntu-20.04 os: ubuntu-20.04
output: cargo-binstall output: cargo-binstall
archive: tgz
- target: x86_64-pc-windows-msvc - target: x86_64-pc-windows-msvc
os: windows-latest os: windows-latest
output: cargo-binstall.exe output: cargo-binstall.exe
archive: zip
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -93,28 +97,33 @@ jobs:
command: build command: build
args: --target ${{ matrix.target }} --release args: --target ${{ matrix.target }} --release
- name: Copy / Rename utility - name: Copy and rename utility
run: | run: cp target/${{ matrix.target }}/release/${{ matrix.output }} ${{ matrix.output }}
cp target/${{ matrix.target }}/release/${{ matrix.output }} ${{ matrix.output }}
tar -czvf cargo-binstall-${{ matrix.target }}.tgz ${{ matrix.output }} - name: Create archive (tgz)
if: ${{ matrix.target != 'x86_64-pc-windows-msvc' }}
run: tar -czvf cargo-binstall-${{ matrix.target }}.tgz ${{ matrix.output }}
- name: Create archive (zip)
if: ${{ matrix.target == 'x86_64-pc-windows-msvc' }}
run: tar.exe -a -c -f cargo-binstall-${{ matrix.target }}.zip ${{ matrix.output }}
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:
name: cargo-binstall-${{ matrix.target }}.tgz name: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }}
path: cargo-binstall-${{ matrix.target }}.tgz path: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }}
- name: Upload binary to release - name: Upload binary to release
if: ${{ startsWith(github.ref, 'refs/tags/v') }} if: ${{ startsWith(github.ref, 'refs/tags/v') }}
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: cargo-binstall-${{ matrix.target }}.tgz file: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }}
asset_name: cargo-binstall-${{ matrix.target }}.tgz asset_name: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }}
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true
test: test:
name: Test name: Test
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

83
Cargo.lock generated
View file

@ -1,10 +1,12 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "adler" name = "adler32"
version = "0.2.3" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
@ -88,12 +90,39 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "0.5.6" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]]
name = "bzip2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
dependencies = [
"bzip2-sys",
"libc",
]
[[package]]
name = "bzip2-sys"
version = "0.1.10+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]] [[package]]
name = "cargo-binstall" name = "cargo-binstall"
version = "0.1.0" version = "0.1.0"
@ -120,6 +149,7 @@ dependencies = [
"tinytemplate", "tinytemplate",
"tokio", "tokio",
"xz2", "xz2",
"zip",
] ]
[[package]] [[package]]
@ -338,11 +368,11 @@ dependencies = [
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.19" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 0.1.10",
"crc32fast", "crc32fast",
"libc", "libc",
"miniz_oxide", "miniz_oxide",
@ -838,12 +868,11 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.3" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [ dependencies = [
"adler", "adler32",
"autocfg",
] ]
[[package]] [[package]]
@ -1541,6 +1570,26 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "thiserror"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.0.1" version = "1.0.1"
@ -1952,3 +2001,17 @@ checksum = "c179869f34fc7c01830d3ce7ea2086bc3a07e0d35289b667d0a8bf910258926c"
dependencies = [ dependencies = [
"lzma-sys", "lzma-sys",
] ]
[[package]]
name = "zip"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8264fcea9b7a036a4a5103d7153e988dbc2ebbafb34f68a3c2d404b6b82d74b6"
dependencies = [
"byteorder",
"bzip2",
"crc32fast",
"flate2",
"thiserror",
"time",
]

View file

@ -10,9 +10,11 @@ license = "GPL-3.0"
[package.metadata.binstall] [package.metadata.binstall]
pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ target }.tgz" pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ target }.{ format }"
bin-dir = "{ bin }{ format }" bin-dir = "{ bin }{ format }"
[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
pkg-fmt = "zip"
[dependencies] [dependencies]
crates_io_api = "0.6.1" crates_io_api = "0.6.1"
@ -25,7 +27,7 @@ simplelog = "0.9.0"
anyhow = "1.0.40" anyhow = "1.0.40"
reqwest = "0.10.10" reqwest = "0.10.10"
tempdir = "0.3.7" tempdir = "0.3.7"
flate2 = "1.0.19" flate2 = "1.0.14"
tar = "0.4.30" tar = "0.4.30"
cargo_toml = "0.8.1" cargo_toml = "0.8.1"
serde = { version = "1.0.119", features = [ "derive" ] } serde = { version = "1.0.119", features = [ "derive" ] }
@ -36,6 +38,7 @@ serde_derive = "1.0.118"
crates-index = "0.16.2" crates-index = "0.16.2"
semver = "0.11.0" semver = "0.11.0"
xz2 = "0.1.6" xz2 = "0.1.6"
zip = "0.5.11"
[dev-dependencies] [dev-dependencies]
env_logger = "0.8.2" env_logger = "0.8.2"

View file

@ -41,6 +41,7 @@ yes
- [x] Tgz - [x] Tgz
- [x] Txz - [x] Txz
- [x] Tar - [x] Tar
- [x] Zip
- [x] Bin - [x] Bin
- Extraction / Transformation - Extraction / Transformation
- [x] Extract from subdirectory in archive (ie. support archives with platform or target subdirectories) - [x] Extract from subdirectory in archive (ie. support archives with platform or target subdirectories)
@ -79,12 +80,18 @@ Template variables use the format `{ VAR }` where `VAR` is the name of the varia
- `bin` is the name of a specific binary, inferred from the crate configuration - `bin` is the name of a specific binary, inferred from the crate configuration
- `target` is the rust target name (defaults to your architecture, but can be overridden using the `--target` command line option if required(). - `target` is the rust target name (defaults to your architecture, but can be overridden using the `--target` command line option if required().
Package format can be overridden on a per-target basis, for example, if your `x86_64-pc-windows-msvc` builds use `zip` archives this can be set via:
```
[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
pkg-fmt = "zip"
```
### Defaults ### Defaults
By default `binstall` is setup to work with github releases, and expects to find: By default `binstall` is setup to work with github releases, and expects to find:
- an archive named `{ name }-{ target }-v{ version }.tgz` - an archive named `{ name }-{ target }-v{ version }.{ format }`
- so that this does not overwrite different targets or versions when manually downloaded - so that this does not overwrite different targets or versions when manually downloaded
- located at `{ repo }/releases/download/v{ version }/` - located at `{ repo }/releases/download/v{ version }/`
- compatible with github tags / releases - compatible with github tags / releases

View file

@ -7,7 +7,7 @@ use cargo_toml::{Manifest};
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use tar::Archive; use tar::Archive;
use xz2::read::XzDecoder; use xz2::read::XzDecoder;
use zip::read::ZipArchive;
use crate::{Meta}; use crate::{Meta};
@ -77,6 +77,15 @@ pub fn extract<S: AsRef<Path>, P: AsRef<Path>>(source: S, fmt: PkgFmt, path: P)
txz.unpack(path)?; txz.unpack(path)?;
}, },
PkgFmt::Zip => {
// Extract to install dir
debug!("Decompressing from archive '{:?}' to `{:?}`", source.as_ref(), path.as_ref());
let dat = std::fs::File::open(source)?;
let mut zip = ZipArchive::new(dat)?;
zip.extract(path)?;
},
PkgFmt::Bin => { PkgFmt::Bin => {
debug!("Copying data from archive '{:?}' to `{:?}`", source.as_ref(), path.as_ref()); debug!("Copying data from archive '{:?}' to `{:?}`", source.as_ref(), path.as_ref());
// Copy to install dir // Copy to install dir

View file

@ -1,3 +1,6 @@
use std::collections::HashMap;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use strum_macros::{Display, EnumString, EnumVariantNames}; use strum_macros::{Display, EnumString, EnumVariantNames};
use tinytemplate::TinyTemplate; use tinytemplate::TinyTemplate;
@ -21,6 +24,7 @@ pub const DEFAULT_BIN_PATH: &'static str = "{ name }-{ target }-v{ version }/{ b
/// Binary format enumeration /// Binary format enumeration
/// This defaults to .zip on windows and .tgz on all other platforms
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Display, EnumString, EnumVariantNames)] #[derive(Display, EnumString, EnumVariantNames)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
@ -32,6 +36,8 @@ pub enum PkgFmt {
Tgz, Tgz,
/// Download format is TAR + XZ /// Download format is TAR + XZ
Txz, Txz,
/// Download format is Zip
Zip,
/// Download format is raw / binary /// Download format is raw / binary
Bin, Bin,
} }
@ -68,6 +74,9 @@ pub struct PkgMeta {
/// Public key for package verification (base64 encoded) /// Public key for package verification (base64 encoded)
pub pub_key: Option<String>, pub pub_key: Option<String>,
/// Target specific overrides
pub overrides: HashMap<String, PkgOverride>,
} }
impl Default for PkgMeta { impl Default for PkgMeta {
@ -77,10 +86,39 @@ impl Default for PkgMeta {
pkg_fmt: PkgFmt::default(), pkg_fmt: PkgFmt::default(),
bin_dir: DEFAULT_BIN_PATH.to_string(), bin_dir: DEFAULT_BIN_PATH.to_string(),
pub_key: None, pub_key: None,
overrides: HashMap::new(),
} }
} }
} }
impl PkgMeta {
/// Merge configuration overrides into object
pub fn merge(&mut self, pkg_override: &PkgOverride) {
if let Some(o) = pkg_override.pkg_fmt {
self.pkg_fmt = o;
}
}
}
/// Target specific overrides for binary installation
///
/// Exposed via `[package.metadata.TARGET]` in `Cargo.toml`
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", default)]
pub struct PkgOverride {
/// Format for package downloads
pub pkg_fmt: Option<PkgFmt>,
}
impl Default for PkgOverride {
fn default() -> Self {
Self {
pkg_fmt: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct BinMeta { pub struct BinMeta {

View file

@ -97,11 +97,18 @@ async fn main() -> Result<(), anyhow::Error> {
let manifest = load_manifest_path(manifest_path.join("Cargo.toml"))?; let manifest = load_manifest_path(manifest_path.join("Cargo.toml"))?;
let package = manifest.package.unwrap(); let package = manifest.package.unwrap();
let (meta, binaries) = ( let (mut meta, binaries) = (
package.metadata.map(|m| m.binstall ).flatten().unwrap_or(PkgMeta::default()), package.metadata.map(|m| m.binstall ).flatten().unwrap_or(PkgMeta::default()),
manifest.bin, manifest.bin,
); );
// Merge any overrides
if let Some(o) = meta.overrides.remove(&opts.target) {
meta.merge(&o);
}
debug!("Found metadata: {:?}", meta);
// Generate context for URL interpolation // Generate context for URL interpolation
let ctx = Context { let ctx = Context {
name: opts.name.clone(), name: opts.name.clone(),