Skip to content

fix(file): handle GNU sparse files and tar crate extraction issues#6380

Merged
jdx merged 3 commits intomainfrom
fix/gnu-sparse-file-extraction
Sep 22, 2025
Merged

fix(file): handle GNU sparse files and tar crate extraction issues#6380
jdx merged 3 commits intomainfrom
fix/gnu-sparse-file-extraction

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Sep 22, 2025

Summary

  • Fixes tar extraction issues that create GNUSparseFile.0 directories
  • Adds fallback to system tar when the rust tar crate can't properly handle certain archives
  • Resolves installation failures for tools like tokei

Problem

The rust tar crate has issues extracting certain tar archives:

  1. Some archives cause files to be extracted into a GNUSparseFile.0 directory instead of the intended location
  2. GNU sparse files aren't properly handled, resulting in corrupted extractions with sparse metadata prepended to file contents

This was causing cargo run test-tool tokei to fail because the tokei binary was being incorrectly extracted.

Solution

  • During extraction, check if entries have the GNU sparse file type using is_gnu_sparse()
  • After extraction, check for the presence of GNUSparseFile.0 directory (catches cases where sparse type isn't set but tar crate still mishandles the archive)
  • When either condition is detected, fall back to using the system tar command which properly handles these archives
  • Clean up any partial/corrupted extractions before retrying with system tar

Testing

✅ Verified with cargo run test-tool tokei - now passes successfully
✅ Tested clean installation after mise uninstall --all tokei
✅ Confirmed both detection methods are necessary (some archives need the GNUSparseFile.0 fallback)

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings September 22, 2025 18:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Fixes extraction issues with GNU sparse files by implementing a fallback mechanism to system tar when the tar crate fails to handle sparse file formats properly.

  • Adds detection for GNUSparseFile.0 directory after tar crate extraction
  • Implements fallback to system tar command when GNU sparse files are detected
  • Maintains existing functionality for regular tar archives while fixing sparse file support

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

src/file.rs Outdated
Comment on lines +770 to +774
let tar_cmd = if cfg!(target_os = "macos") || cfg!(target_os = "freebsd") {
"tar" // BSD tar handles sparse files better
} else {
"tar" // GNU tar
};
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The conditional logic assigns the same value 'tar' for both branches, making the condition redundant. Either remove the condition or implement platform-specific logic if different tar commands are needed.

Suggested change
let tar_cmd = if cfg!(target_os = "macos") || cfg!(target_os = "freebsd") {
"tar" // BSD tar handles sparse files better
} else {
"tar" // GNU tar
};
let tar_cmd = "tar";

Copilot uses AI. Check for mistakes.
Comment on lines 793 to 795
}
// if let Some(pr) = &opts.pr {
// pr.set_position(total);
// }

strip_archive_path_components(dest, opts.strip_components).wrap_err_with(err)?;
Copy link

Copilot AI Sep 22, 2025

Choose a reason for hiding this comment

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

The strip_archive_path_components function is called after both fallback and regular extraction, but it should only be called for regular extraction since the system tar command already handles --strip-components.

Suggested change
}
// if let Some(pr) = &opts.pr {
// pr.set_position(total);
// }
strip_archive_path_components(dest, opts.strip_components).wrap_err_with(err)?;
strip_archive_path_components(dest, opts.strip_components).wrap_err_with(err)?;
}

Copilot uses AI. Check for mistakes.
cursor[bot]

This comment was marked as outdated.

@jdx jdx force-pushed the fix/gnu-sparse-file-extraction branch from e46054a to f7e76ac Compare September 22, 2025 18:48
The tar crate doesn't properly handle GNU sparse files, which can result in:
1. Files being extracted to GNUSparseFile.0 directory
2. Corrupted files with sparse metadata prepended

This fix:
- Checks for GNU sparse files using is_gnu_sparse() during extraction
- Falls back to system tar when sparse files are detected
- Also checks for GNUSparseFile.0 directory as a secondary detection
  (needed because some archives don't have the sparse entry type set
  but still cause the tar crate to extract incorrectly)
- Cleans up any partial/corrupted extractions before retrying

Fixes extraction issues with tools like tokei that use problematic tar archives.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@jdx jdx force-pushed the fix/gnu-sparse-file-extraction branch from f7e76ac to 66cbf56 Compare September 22, 2025 18:52
@jdx jdx changed the title fix(file): add fallback to system tar for GNU sparse file extraction fix(file): handle GNU sparse files and tar crate extraction issues Sep 22, 2025
@github-actions
Copy link

github-actions bot commented Sep 22, 2025

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.15 x -- echo 19.8 ± 0.5 19.2 23.3 1.00
mise x -- echo 20.2 ± 0.5 19.4 24.0 1.02 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.15 env 19.3 ± 0.5 18.7 24.4 1.00
mise env 19.3 ± 0.3 18.7 20.8 1.00 ± 0.03

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.15 hook-env 18.9 ± 0.3 18.3 20.4 1.00
mise hook-env 19.1 ± 0.7 18.3 28.2 1.01 ± 0.04

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.9.15 ls 16.9 ± 0.4 16.2 19.3 1.00
mise ls 17.0 ± 0.4 16.4 18.8 1.01 ± 0.04

xtasks/test/perf

Command mise-2025.9.15 mise Variance
install (cached) 170ms ✅ 105ms +61%
ls (cached) 65ms 65ms +0%
bin-paths (cached) 72ms 70ms +2%
task-ls (cached) 496ms 472ms +5%

✅ Performance improvement: install cached is 61%

@jdx jdx requested a review from Copilot September 22, 2025 23:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@jdx jdx force-pushed the fix/gnu-sparse-file-extraction branch from 40fb335 to 61970e6 Compare September 22, 2025 23:43
@jdx jdx merged commit fb208d5 into main Sep 22, 2025
18 checks passed
@jdx jdx deleted the fix/gnu-sparse-file-extraction branch September 22, 2025 23:53
@jdx jdx mentioned this pull request Sep 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants