Skip to content

Replace astral-tokio-tar with tar-codec - #2547

Draft
j178 wants to merge 1 commit into
masterfrom
tar-codec
Draft

Replace astral-tokio-tar with tar-codec#2547
j178 wants to merge 1 commit into
masterfrom
tar-codec

Conversation

@j178

@j178 j178 commented Aug 12, 2026

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI lite review requested due to automatic review settings August 12, 2026 09:44
@j178 j178 added the internal Internal changes label Aug 12, 2026
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.64%. Comparing base (98e2252) to head (f062cf6).

Files with missing lines Patch % Lines
crates/prek/src/archive.rs 90.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2547      +/-   ##
==========================================
- Coverage   93.65%   93.64%   -0.01%     
==========================================
  Files         134      134              
  Lines       28886    28892       +6     
==========================================
+ Hits        27052    27055       +3     
- Misses       1834     1837       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates tar extraction in crates/prek from astral-tokio-tar to tar-codec, updating the extraction implementation and dependency set accordingly.

Changes:

  • Replaced .tar.gz / .tar.xz extraction implementation to use tar-codec with an explicit decode/extract policy.
  • Updated error typing around zip/tar extraction to use dedicated Zip/Tar variants.
  • Swapped Cargo dependencies from tokio-tar (astral-tokio-tar) to tar-codec and updated the lockfile.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
crates/prek/src/archive.rs Switch tar extraction implementation to tar-codec, add extraction policy helpers, and adjust error variants.
crates/prek/Cargo.toml Replace tokio-tar dependency with tar-codec.
Cargo.toml Add tar-codec workspace dependency and remove astral-tokio-tar override.
Cargo.lock Lockfile updates reflecting dependency replacement and transitive additions/removals.
Suppressed comments (4)

crates/prek/src/archive.rs:275

  • The untar_in doc comment says it returns a list of unpacked files and sizes, but the function returns Result<(), _>. This is misleading for callers and future maintainers.
/// Unpack the given tar archive into the destination directory.
///
/// Returns the list of unpacked files and their sizes.
async fn untar_in<R: AsyncRead + Unpin>(

crates/prek/src/archive.rs:299

  • This comment references uv, which doesn’t appear to be part of this crate/module. That makes the rationale hard to trust and likely indicates copy/paste from another codebase.
    // Keep tar-codec's defaults, including name validation, hardlink rejection, and rejection of
    // pre-existing link targets. uv extracts archives into new temporary directories.

crates/prek/src/archive.rs:45

  • The Zip/Tar error messages claim the archive is "invalid", but these From conversions will also be used for non-format failures (e.g. destination write errors, policy rejections). Using a more general message avoids misdiagnosis in user-facing errors.
    #[error("Invalid zip file structure")]
    Zip(#[from] async_zip::error::ZipError),
    #[error("Invalid tar file")]
    Tar(#[from] ExtractError<DecodeError>),

crates/prek/src/archive.rs:318

  • Tar extraction behavior changed significantly (new tar-codec decode/extract policies, Windows symlink policy). The only test in this module covers unsupported extensions, so regressions in .tar.gz/.tar.xz extraction would go unnoticed.
/// Unpack a `.tar.gz` archive into the target directory, without requiring `Seek`.
///
/// This is useful for unpacking files as they're being downloaded.
pub async fn untar_gz<R: AsyncRead + Unpin>(
    reader: R,
    target: impl AsRef<Path>,
) -> Result<(), Error> {
    let reader = BufReader::with_capacity(DEFAULT_BUF_SIZE, reader);
    let reader = GzipDecoder::new(reader);
    untar_in(reader, target.as_ref()).await.map_err(Error::from)
}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/prek/src/archive.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f062cf6eb6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


/// Unpack the given tar archive into the destination directory.
///
/// Returns the list of unpacked files and their sizes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Correct the untar_in return documentation

This documentation promises a list of unpacked files and their sizes, but untar_in returns Result<(), ExtractError<DecodeError>> and exposes no such metadata. This gives future callers a false contract; remove the claim or return the documented information.

AGENTS.md reference: AGENTS.md:L13-L15

Useful? React with 👍 / 👎.

@prek-ci-bot

prek-ci-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

📦 Cargo Bloat Comparison

Binary size change: +2.30% (30.4 MiB → 31.1 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text     Size             Crate Name
 1.0%   2.1% 332.0KiB        aws_lc_sys aws_lc_0_43_0_aes_gcm_encrypt_avx512
 1.0%   2.1% 332.0KiB        aws_lc_sys aws_lc_0_43_0_aes_gcm_decrypt_avx512
 0.3%   0.6%  86.0KiB              prek <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.4%  58.3KiB              prek prek::run::{closure#0}
 0.2%   0.4%  55.0KiB              prek <<prek::config::Config as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.2%   0.3%  49.4KiB annotate_snippets annotate_snippets::renderer::render::render
 0.1%   0.3%  40.7KiB              prek prek::cli::run::run::run::{closure#0}
 0.1%   0.2%  34.2KiB              prek <prek::cli::RunOptions as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  30.9KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  30.5KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  28.9KiB              prek <prek::languages::deno::installer::DenoInstaller>::download::{closure#0}
 0.1%   0.2%  28.6KiB    cargo_metadata <&mut serde_json::de::Deserializer<serde_json::read::StrRead> as serde_core::de::Deserializer>::deserialize_struct::<<cargo_metadata::Package as serde_core::de::Deserialize>::deserialize::__Visitor>
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_43_0_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_43_0_edwards25519_scalarmuldouble
 0.1%   0.2%  27.5KiB              prek <prek::languages::ruby::installer::RubyInstaller>::download::{closure#0}
 0.1%   0.2%  27.2KiB              prek <<prek::config::RemoteHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  26.7KiB              prek <prek::languages::mise::installer::MiseInstaller>::download::{closure#0}
 0.1%   0.2%  26.5KiB              prek prek::cli::try_repo::try_repo::{closure#0}
 0.1%   0.2%  24.9KiB               xml <xml::reader::parser::PullParser>::dispatch_token
 0.1%   0.2%  24.5KiB              prek <prek::languages::bun::installer::BunInstaller>::download::{closure#0}
43.5%  88.8%  13.5MiB                   And 27471 smaller methods. Use -n N to show more.
48.9% 100.0%  15.2MiB                   .text section size, the file size is 31.1MiB

Base Branch Results

 File  .text     Size             Crate Name
 1.1%   2.2% 332.0KiB        aws_lc_sys aws_lc_0_43_0_aes_gcm_encrypt_avx512
 1.1%   2.2% 332.0KiB        aws_lc_sys aws_lc_0_43_0_aes_gcm_decrypt_avx512
 0.3%   0.6%  86.0KiB              prek <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.4%  57.4KiB              prek prek::run::{closure#0}
 0.2%   0.4%  55.0KiB              prek <<prek::config::Config as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.2%   0.3%  49.4KiB annotate_snippets annotate_snippets::renderer::render::render
 0.1%   0.3%  46.2KiB              prek <prek::languages::ruby::installer::RubyInstaller>::install::{closure#0}
 0.1%   0.3%  39.2KiB              prek prek::cli::run::run::run::{closure#0}
 0.1%   0.2%  34.8KiB              prek <prek::languages::node::installer::NodeInstaller>::install::{closure#0}
 0.1%   0.2%  34.3KiB              prek <prek::cli::RunOptions as clap_builder::derive::Args>::augment_args
 0.1%   0.2%  33.0KiB              prek <prek::languages::golang::installer::GoInstaller>::install::{closure#0}
 0.1%   0.2%  31.9KiB              prek <prek::languages::bun::installer::BunInstaller>::install::{closure#0}
 0.1%   0.2%  30.9KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  30.5KiB     granit_parser <granit_parser::scanner::Scanner<granit_parser::input::str::StrInput>>::fetch_more_tokens
 0.1%   0.2%  29.2KiB              prek <prek::languages::deno::installer::DenoInstaller>::download::{closure#0}
 0.1%   0.2%  28.6KiB    cargo_metadata <&mut serde_json::de::Deserializer<serde_json::read::StrRead> as serde_core::de::Deserializer>::deserialize_struct::<<cargo_metadata::Package as serde_core::de::Deserialize>::deserialize::__Visitor>
 0.1%   0.2%  28.0KiB        aws_lc_sys aws_lc_0_43_0_edwards25519_scalarmuldouble_alt
 0.1%   0.2%  27.5KiB        aws_lc_sys aws_lc_0_43_0_edwards25519_scalarmuldouble
 0.1%   0.2%  27.2KiB              prek <<prek::config::RemoteHook as serde_core::de::Deserialize>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map::<<serde_saphyr::de::deserializer::YamlDeserializer as serde_core::de::Deserializer>::deserialize_map::MA>
 0.1%   0.2%  27.2KiB              prek <prek::languages::mise::installer::MiseInstaller>::download::{closure#0}
42.9%  88.3%  13.0MiB                   And 26809 smaller methods. Use -n N to show more.
48.6% 100.0%  14.8MiB                   .text section size, the file size is 30.4MiB

@prek-ci-bot

prek-ci-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

⚡️ Hyperfine Benchmarks

Summary: 0 regressions, 0 improvements above the 10% threshold.

Environment
  • OS: Linux 6.17.0-1020-azure
  • CPU: 4 cores
  • prek version: prek 0.4.13+4 (52ae92e 2026-08-12)
  • Rust version: rustc 1.97.1 (8bab26f4f 2026-07-14)
  • Hyperfine version: hyperfine 1.20.0
CLI Commands

Benchmarking basic commands in the main repo:

prek --version

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base --version 1.8 ± 0.1 1.7 2.0 1.01 ± 0.06
prek-head --version 1.8 ± 0.1 1.6 2.1 1.00

prek list

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base list 8.0 ± 0.2 7.7 8.4 1.02 ± 0.03
prek-head list 7.8 ± 0.2 7.5 8.4 1.00

prek validate-config .pre-commit-config.yaml

⏭️ Skipped: .pre-commit-config.yaml not found

prek sample-config

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base sample-config 2.1 ± 0.1 2.0 2.3 1.00
prek-head sample-config 2.1 ± 0.0 2.0 2.2 1.00 ± 0.04
Cold vs Warm Runs

Comparing first run (cold) vs subsequent runs (warm cache):

prek run --all-files (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 28.8 ± 1.0 27.3 30.7 1.01 ± 0.04
prek-head run --all-files 28.6 ± 0.5 27.7 29.2 1.00

prek run --all-files (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 29.4 ± 2.7 27.5 40.0 1.04 ± 0.10
prek-head run --all-files 28.3 ± 0.8 26.6 29.5 1.00
Full Hook Suite

Running the builtin hook suite on the benchmark workspace:

prek run --all-files (full builtin hook suite)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --all-files 28.5 ± 0.7 26.8 29.9 1.00 ± 0.04
prek-head run --all-files 28.4 ± 0.8 26.6 30.4 1.00
Individual Hook Performance

Benchmarking each hook individually on the test repo:

prek run trailing-whitespace --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run trailing-whitespace --all-files 9.8 ± 0.2 9.3 10.5 1.01 ± 0.04
prek-head run trailing-whitespace --all-files 9.7 ± 0.3 9.3 10.3 1.00

prek run end-of-file-fixer --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run end-of-file-fixer --all-files 8.3 ± 0.3 7.9 9.1 1.00
prek-head run end-of-file-fixer --all-files 8.4 ± 0.3 7.9 9.1 1.02 ± 0.05

prek run check-json --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-json --all-files 6.2 ± 0.2 5.8 6.8 1.01 ± 0.05
prek-head run check-json --all-files 6.1 ± 0.2 5.7 6.6 1.00

prek run check-yaml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-yaml --all-files 6.2 ± 0.2 5.9 6.5 1.01 ± 0.04
prek-head run check-yaml --all-files 6.1 ± 0.1 5.8 6.3 1.00

prek run check-toml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-toml --all-files 6.0 ± 0.1 5.7 6.3 1.00
prek-head run check-toml --all-files 6.1 ± 0.2 5.7 6.5 1.01 ± 0.04

prek run check-xml --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-xml --all-files 5.9 ± 0.1 5.6 6.3 1.00 ± 0.03
prek-head run check-xml --all-files 5.9 ± 0.1 5.7 6.2 1.00

prek run detect-private-key --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run detect-private-key --all-files 8.3 ± 0.5 7.5 9.7 1.00 ± 0.07
prek-head run detect-private-key --all-files 8.2 ± 0.3 7.7 9.0 1.00

prek run fix-byte-order-marker --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run fix-byte-order-marker --all-files 10.6 ± 0.4 10.0 11.3 1.00
prek-head run fix-byte-order-marker --all-files 10.6 ± 0.5 9.5 11.8 1.00 ± 0.06
Installation Performance

Benchmarking hook installation (fast path hooks skip Python setup):

prek install-hooks (cold - no cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 3.7 ± 0.1 3.6 4.0 1.02 ± 0.04
prek-head install-hooks 3.7 ± 0.1 3.6 3.8 1.00

prek install-hooks (warm - with cache)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base install-hooks 3.8 ± 0.1 3.7 3.9 1.03 ± 0.03
prek-head install-hooks 3.7 ± 0.1 3.6 3.8 1.00
File Filtering/Scoping Performance

Testing different file selection modes:

prek run (staged files only)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run 18.1 ± 0.3 17.7 18.9 1.00
prek-head run 18.1 ± 0.3 17.6 18.8 1.00 ± 0.02

prek run --files '*.json' (specific file type)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --files '*.json' 4.1 ± 0.1 4.0 4.3 1.00
prek-head run --files '*.json' 4.1 ± 0.1 4.0 4.3 1.01 ± 0.03
Workspace Discovery & Initialization

Benchmarking hook discovery and initialization overhead:

prek run --dry-run --all-files (measures init overhead)

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run --dry-run --all-files 5.5 ± 0.1 5.3 5.7 1.01 ± 0.03
prek-head run --dry-run --all-files 5.4 ± 0.1 5.3 5.5 1.00
Meta Hooks Performance

Benchmarking meta hooks separately:

prek run check-hooks-apply --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-hooks-apply --all-files 6.4 ± 0.1 6.2 6.6 1.00
prek-head run check-hooks-apply --all-files 6.5 ± 0.1 6.2 6.7 1.02 ± 0.03

prek run check-useless-excludes --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run check-useless-excludes --all-files 6.4 ± 0.1 6.2 6.5 1.00
prek-head run check-useless-excludes --all-files 6.4 ± 0.1 6.3 6.6 1.01 ± 0.02

prek run identity --all-files

Command Mean [ms] Min [ms] Max [ms] Relative
prek-base run identity --all-files 5.5 ± 0.1 5.4 5.6 1.00
prek-head run identity --all-files 5.5 ± 0.1 5.4 5.7 1.01 ± 0.02

@j178
j178 marked this pull request as draft August 12, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment