#channel #release #artefact

rust_release_artefact

Safely extract installable files from Rust release artefacts

4 releases

Uses old Rust 2015

0.1.3 May 8, 2018
0.1.2 May 8, 2018
0.1.1 May 1, 2018
0.1.0 Apr 19, 2018

#1539 in Data structures

MIT/Apache

5MB
586 lines

rust_release_artefact: Extract and install Rust release artefacts

Repository: https://gitlab.com/Screwtapello/rust_release_artefact

Documentation: https://docs.rs/rust_release_artefact

TODO

  • Update ExtractedArtefact::new() to use walkdir to search for artefact marker files.
  • Would it be neater to toss the first path-component of archives, rather than extracting it and having to rummage around to find the artefact metadata?

lib.rs:

Safely extract installable files from Rust release artefacts.

Introduction

Each new release of the Rust toolchain includes a number of components—some required, some optional—that can be combined together. These components are made available as artefacts in a standard format that includes the files to be installed, as well as metadata describing them. Installing a component is therefore more complex than just extracting an archive, since not all files should be placed in the destination.

This library interprets a Rust artefact's metadata, and provides a list of the components it contains, as well as the specific list of installable files in each component.

Once you've downloaded an artefact, use ExtractedArtefact::from_tar_gz() or ExtractedArtefact::from_tar_xz() to extract it and retrieve the metadata (the place you got the artefact from should tell you which format it's in). If you have previously extracted an artefact, you can re-read the metadata directly using ExtractedArtefact::new().

First Example

 extern crate rust_release_artefact as rra;

 use std::error;
 use std::fs;
 use std::io;
 use std::path;

 fn install_from_tar_gz(
     artefact_path: &path::Path,
     stage: &path::Path,
     component_name: &str,
     dest_root: &path::Path,
 ) -> Result<(), Box<error::Error>> {
     // Open the file containing the artefact.
     let handle = fs::File::open(artefact_path)?;

     // Extract it to the given staging path and read the metadata.
     // We're assuming the staging path is already canonicalized, and
     // the artefact is in .tar.gz format.
     let extracted_artefact = rra::ExtractedArtefact::from_tar_gz(
         io::BufReader::new(handle),
         stage,
     )?;

     // Get the requested component from the artefact.
     let component = extracted_artefact.components
         .get(component_name)
         .ok_or("Could not find component")?;

     println!(
         "Installing component {} version {} to {:?}",
         component_name,
         extracted_artefact.version,
         dest_root,
     );

     // Install the component into the destination.
     // We're also assuming dest_root is already canonicalized.
     component.install_to(dest_root)?;

     // All done!
     Ok(())
 }

Capabilities

Extract downloaded artefacts

Once you have downloaded a release artefact, you can extract it into a staging area with the ExtractedArtefact::from_tar_gz() or ExtractedArtefact::from_tar_xz() functions (depending on the format).

 extern crate rust_release_artefact as rra;

 use std::fs;
 use std::io;
 use std::path;

 # fn example() -> Result<(), Box<std::error::Error>> {
 let handle = fs::File::open("path/to/artefact.tar.gz")?;

 // Make sure the staging area exists.
 let staging_area = path::Path::new("path/to/staging/area");
 fs::create_dir_all(&staging_area)?;

 // Canonicalize the staging area path, so Windows can handle long path
 // names.
 let staging_area = staging_area.canonicalize()?;

 let extracted_artefact = rra::ExtractedArtefact::from_tar_gz(
     io::BufReader::new(handle),
     staging_area,
 )?;
 # Ok(())
 # }

Read artefact metadata

An ExtractedArtefact struct represents the artefact's metadata, including the components in this artefact and the complete list of installable files in each component.

 # extern crate rust_release_artefact as rra;
 # fn example() -> Result<(), Box<std::error::Error>> {
 # let extracted_artefact = rra::ExtractedArtefact::new("src")?;

 println!("Version: {:?}", extracted_artefact.version);
 println!("Git commit hash: {:?}", extracted_artefact.git_commit_hash);

 for (name, component) in &extracted_artefact.components {
     println!("Component: {:?} in {:?}", name, component.root);
     for path in &component.files {
         println!("  - {:?}", path);
     }
 }
 # Ok(())
 # }

Install components to a given destination

The Component struct represents an installable component of the artefact, whose files are in the artefact's staging area, ready to be installed to a target location. The handy Component::install_to() method does exactly that.

 # extern crate rust_release_artefact as rra;
 # fn example() -> Result<(), Box<std::error::Error>> {
 # let extracted_artefact = rra::ExtractedArtefact::new("src")?;
 let component = extracted_artefact.components.get("my-component")
     .ok_or("no such component?")?;

 // Make sure the destination exists.
 let destination = std::path::Path::new("path/to/install/destination");
 std::fs::create_dir_all(&destination)?;

 // Canonicalize the staging area path, so Windows can handle long path
 // names.
 let destination = destination.canonicalize()?;

 component.install_to(destination)?;
 # Ok(())
 # }

Dependencies

~4–13MB
~169K SLoC