Skip to content

Commit

Permalink
Skip recreating links when not necessary (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptibell authored Jun 14, 2024
1 parent 9abc4bb commit 3bacb01
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 80 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Fixed `tarmac` not installing correctly on non-arm systems due to its name containing `arm`
- Fixed `tarmac` not installing correctly on non-arm systems due to its name containing `arm` ([#26])
- Fixed OS permission errors during `rokit install` for tools that are currently running ([#27])

[#26]: https://github.com/filiptibell/rokit/pull/26
[#27]: https://github.com/filiptibell/rokit/pull/27

## `0.1.1` - June 9th, 2024

Expand Down
81 changes: 81 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ filepath = "0.1"
flate2 = "1.0"
goblin = "0.8"
once_cell = "1.8"
postcard = { version = "1.0", features = ["alloc"] }
semver = { version = "1.0", features = ["serde"] }
tar = "0.4"
tempfile = "3.3"
Expand Down
9 changes: 9 additions & 0 deletions lib/result.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io::Error as IoError;
use std::path::PathBuf;

use postcard::Error as PostcardError;
use serde_json::Error as JsonError;
use thiserror::Error;
use tokio::task::JoinError;
Expand All @@ -27,6 +28,8 @@ pub enum RokitError {
Io(Box<IoError>),
#[error("JSON error: {0}")]
Json(Box<JsonError>),
#[error("Postcard error: {0}")]
Postcard(Box<PostcardError>),
#[error("Zip file error: {0}")]
Zip(Box<ZipError>),
#[error("GitHub error: {0}")]
Expand Down Expand Up @@ -67,6 +70,12 @@ impl From<JsonError> for RokitError {
}
}

impl From<PostcardError> for RokitError {
fn from(err: PostcardError) -> Self {
RokitError::Postcard(err.into())
}
}

impl From<ZipError> for RokitError {
fn from(err: ZipError) -> Self {
RokitError::Zip(err.into())
Expand Down
97 changes: 97 additions & 0 deletions lib/storage/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use serde::{Deserialize, Serialize};

use crate::result::RokitResult;

const ROKIT_META_TRAILER: [u8; 10] = *b"ROKIT_LINK";
const ROKIT_META_VERSION: u16 = 1;

const CARGO_VERSION: &str = env!("CARGO_PKG_VERSION");

// FUTURE: We could probably accept impl Read + Seek / impl Write instead
// of [u8] for the metadata functions here to make things faster. For now
// it is fine because the Rokit links are pretty small (just a few MB).

/**
Metadata for a Rokit link - typically used for storing version
information and skipping unnecessary work (recreating the link).
Metadata, as bytes, is stored in the following
format to make it easy to read and write:
- Contents
- Contents length (4 bytes)
- Metadata version (2 bytes)
- Metadata trailer (10 bytes)
This makes for a full 16 bytes for our little
metadata block + whatever contents it stores.
*/
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct RokitLinkMetadata {
pub(crate) version: String,
}

impl RokitLinkMetadata {
/**
Creates new metadata with the current version of Rokit.
*/
pub(crate) fn current() -> Self {
Self {
version: CARGO_VERSION.to_string(),
}
}

/**
Checks if the metadata is for the current version of Rokit.
*/
pub(crate) fn is_current(&self) -> bool {
self.version == CARGO_VERSION
}

/**
Parses metadata from the end of a file.
*/
pub(crate) fn parse_from(contents: impl AsRef<[u8]>) -> Option<RokitLinkMetadata> {
let contents = contents.as_ref();
let len = contents.len();

if contents.ends_with(&ROKIT_META_TRAILER) && len >= 16 {
let meta_version = u16::from_le_bytes([contents[len - 12], contents[len - 11]]);
let meta_len = u32::from_le_bytes([
contents[len - 16],
contents[len - 15],
contents[len - 14],
contents[len - 13],
]) as usize;
if len < (16 + meta_len) {
return None;
}
// FUTURE: Handle multiple metadata versions?
if meta_version == ROKIT_META_VERSION {
return postcard::from_bytes(&contents[(len - 16 - meta_len)..(len - 16)]).ok();
}
}

None
}

/**
Appends metadata to the end of a file.
*/
pub(crate) fn append_to(&self, contents: impl Into<Vec<u8>>) -> RokitResult<Vec<u8>> {
let mut contents = contents.into();

let metadata_bytes = postcard::to_allocvec(self)?;
let metadata_len =
u32::try_from(metadata_bytes.len()).expect("rokit does not support metadata > 4GB");
let metadata_version = ROKIT_META_VERSION.to_le_bytes();
let metadata_len = metadata_len.to_le_bytes();

contents.extend_from_slice(&metadata_bytes);
contents.extend_from_slice(&metadata_len);
contents.extend_from_slice(&metadata_version);
contents.extend_from_slice(&ROKIT_META_TRAILER);

Ok(contents)
}
}
1 change: 1 addition & 0 deletions lib/storage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod home;
mod metadata;
mod tool_cache;
mod tool_storage;

Expand Down
Loading

0 comments on commit 3bacb01

Please sign in to comment.