Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .anvil.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version = 1
tool = "anvil"
tool_version = "0.11.0"
catalog_checksum = "sha256:8902caf297ad65a158418bd2ab41801a95c600c99b6140d51c9e7a440000cffa"
tool_version = "0.11.1"
catalog_checksum = "sha256:b5e3da36fa7754d780c43c77e2cff46232de54a440b0798c91f085d2830eee3c"

[[file]]
path = ".anvil/container/Dockerfile.dockerignore"
Expand Down Expand Up @@ -125,7 +125,7 @@ checksum = "sha256:7aa0560dc9088b33e80cd55aee0a25090cbd3d3610652afd3734d0ca52ee7

[[file]]
path = "justfiles/anvil/checks/llvm-cov.just"
checksum = "sha256:662c85b748f87a0a294e34588ab294851562896739b5cc11f9ad895699e06a94"
checksum = "sha256:5c4d7454b67503ce68a4d68df1783989f5afabc763df5e343bf7abddf974c387"

[[file]]
path = "justfiles/anvil/checks/loom.just"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

7 changes: 7 additions & 0 deletions crates/cargo-anvil/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## [Unreleased]

## [0.11.1] - 2026-09-21

- 🐛 Bug Fixes

- normalize shell-quoted coverage arguments
- parse single-quoted llvm-cov paths

## [0.11.0] - 2026-09-17

- 🐛 Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion crates/cargo-anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

[package]
name = "cargo-anvil"
version = "0.11.0"
version = "0.11.1"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
8 changes: 4 additions & 4 deletions crates/cargo-anvil/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ More detailed design and operational guidance is available in the
This crate was developed as part of <a href="../..">The Oxidizer Project</a>. Browse this crate's <a href="https://github.com/microsoft/ox-tools/tree/main/crates/cargo-anvil">source code</a>.
</sub>

[__cargo_doc2readme_dependencies_info]: ggGmYW0CYXZlMC43LjNhdIQblRYhli3L8qob_NSi_WYo69wbWnMVqZw3jJwb3u56HnT6RDphYvRhcoQbBALu36V1VAYbFUDdfp-8dCobobFjKbRep8AbYNMPgi_aMhFhZIGDa2NhcmdvLWFudmlsZjAuMTEuMGtjYXJnb19hbnZpbA
[__cargo_doc2readme_dependencies_info]: ggGmYW0CYXZlMC43LjNhdIQblRYhli3L8qob_NSi_WYo69wbWnMVqZw3jJwb3u56HnT6RDphYvRhcoQbBALu36V1VAYbFUDdfp-8dCobobFjKbRep8AbYNMPgi_aMhFhZIGDa2NhcmdvLWFudmlsZjAuMTEuMWtjYXJnb19hbnZpbA
[__link0]: https://github.com/casey/just
[__link1]: https://rust-lang.github.io/rustfmt/
[__link10]: https://embarkstudios.github.io/cargo-deny/
Expand All @@ -419,9 +419,9 @@ This crate was developed as part of <a href="../..">The Oxidizer Project</a>. Br
[__link22]: https://mutants.rs/
[__link23]: https://crates.io/crates/cargo-hack
[__link24]: https://crates.io/crates/cargo-coverage-gate
[__link25]: https://docs.rs/cargo-anvil/0.11.0/cargo_anvil/?search=Catalog::anvil
[__link26]: https://docs.rs/cargo-anvil/0.11.0/cargo_anvil/?search=Artifact
[__link27]: https://docs.rs/cargo-anvil/0.11.0/cargo_anvil/fn.run_app.html
[__link25]: https://docs.rs/cargo-anvil/0.11.1/cargo_anvil/?search=Catalog::anvil
[__link26]: https://docs.rs/cargo-anvil/0.11.1/cargo_anvil/?search=Artifact
[__link27]: https://docs.rs/cargo-anvil/0.11.1/cargo_anvil/fn.run_app.html
[__link3]: https://crates.io/crates/cargo-sort
[__link4]: https://crates.io/crates/cargo-heather
[__link5]: https://crates.io/crates/cargo-ensure-no-cyclic-deps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,16 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
}
$command = [regex]::Match(
$failedProcess.Groups['command'].Value,
'(?s)^(?:"(?<quoted>[^"]+)"|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
'(?s)^(?:"(?<quoted>[^"]+)"|''(?<singleQuoted>[^'']+)''|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
)
if (-not $command.Success) {
Write-Warning 'anvil-llvm-cov: the failed process was not an llvm-cov export command'
return $reportExitCode
}
$llvmCov = if ($command.Groups['quoted'].Success) {
$command.Groups['quoted'].Value
} elseif ($command.Groups['singleQuoted'].Success) {
$command.Groups['singleQuoted'].Value
} else {
$command.Groups['bare'].Value
}
Expand All @@ -147,10 +149,15 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
return $reportExitCode
}
$responsePath = [System.IO.Path]::GetFullPath("$OutputPath.llvm-cov.rsp")
$responseArguments = [regex]::Replace(
$command.Groups['arguments'].Value,
"'(?<value>[^']*)'",
{ param($match) '"' + $match.Groups['value'].Value.Replace('"', '\"') + '"' }
)
try {
[System.IO.File]::WriteAllText(
$responsePath,
$command.Groups['arguments'].Value,
$responseArguments,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host 'anvil-llvm-cov: retrying Windows error 206 with an LLVM response file'
Expand Down
33 changes: 29 additions & 4 deletions crates/cargo-anvil/tests/recipe_contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,16 @@ if ($args -contains 'bolero' -and $args -contains 'list') {
exit [int]$env:FAKE_BOLERO_LIST_EXIT
}
if ($args -contains 'llvm-cov' -and $args -contains 'report' -and $env:FAKE_LLVM_COV_REPORT_206) {
$command = "$([char]34)$($env:FAKE_LLVM_COV_PATH)$([char]34) export -format=lcov -instr-profile=fake.profdata -object fake-object.exe"
$quote = if ($env:FAKE_LLVM_COV_SINGLE_QUOTES) { [char]39 } else { [char]34 }
$arguments = if ($env:FAKE_LLVM_COV_SINGLE_QUOTES) {
"'-format=lcov' '-instr-profile=fake.profdata' '-object' 'fake-object.exe'"
} else {
'-format=lcov -instr-profile=fake.profdata -object fake-object.exe'
}
$command = "$quote$($env:FAKE_LLVM_COV_PATH)$quote export $arguments"
if ($env:FAKE_LLVM_COV_MULTILINE) {
$command = $command.Replace(' -object', "`n-object")
$objectArgument = if ($env:FAKE_LLVM_COV_SINGLE_QUOTES) { " '-object'" } else { ' -object' }
$command = $command.Replace($objectArgument, "`n$($objectArgument.TrimStart())")
}
Write-Output (
"error: failed to generate report: could not execute process $([char]96)$command$([char]96) " +
Expand Down Expand Up @@ -2372,6 +2379,10 @@ fn coverage_reports_use_requested_package_scope() {

#[cfg(all(windows, not(target_arch = "aarch64")))]
#[test]
#[expect(
clippy::too_many_lines,
reason = "one end-to-end fixture covers successful and failed response-file retries"
)]
fn windows_coverage_report_retries_error_206_with_response_file() {
if !tools_available() {
return;
Expand Down Expand Up @@ -2399,7 +2410,10 @@ fn windows_coverage_report_retries_error_206_with_response_file() {
Add-Content -LiteralPath $env:FAKE_LLVM_COV_LOG -Value ($Remaining -join ' ')\n\
$response = $Remaining | Where-Object { $_.StartsWith('@') } | Select-Object -First 1\n\
if (-not $response) { exit 2 }\n\
Add-Content -LiteralPath $env:FAKE_LLVM_COV_RESPONSE_LOG -Value (Get-Content -LiteralPath $response.Substring(1) -Raw)\n\
$responseContent = Get-Content -LiteralPath $response.Substring(1) -Raw\n\
if ($responseContent -match \"'\") { exit 3 }\n\
if ($responseContent -notmatch '-instr-profile=fake.profdata') { exit 4 }\n\
Add-Content -LiteralPath $env:FAKE_LLVM_COV_RESPONSE_LOG -Value $responseContent\n\
Write-Output 'TN:'\n\
if ($env:FAKE_LLVM_COV_EXIT) { exit [int]$env:FAKE_LLVM_COV_EXIT }\n\
exit 0\n",
Expand All @@ -2412,6 +2426,7 @@ fn windows_coverage_report_retries_error_206_with_response_file() {
("FAKE_SECOND_PACKAGE_NAME", OsStr::new("measured")),
("FAKE_LLVM_COV_REPORT_206", OsStr::new("1")),
("FAKE_LLVM_COV_MULTILINE", OsStr::new("1")),
("FAKE_LLVM_COV_SINGLE_QUOTES", OsStr::new("1")),
("FAKE_LLVM_COV_PATH", llvm_cov.as_os_str()),
("FAKE_LLVM_COV_LOG", llvm_cov_log.as_os_str()),
("FAKE_LLVM_COV_RESPONSE_LOG", response_log.as_os_str()),
Expand All @@ -2428,7 +2443,11 @@ fn windows_coverage_report_retries_error_206_with_response_file() {
assert_eq!(invocations.lines().count(), 2, "invocations:\n{invocations}");
assert_eq!(invocations.matches("export @").count(), 2, "invocations:\n{invocations}");
let responses = fs::read_to_string(&response_log).unwrap();
assert_eq!(responses.matches("-object fake-object.exe").count(), 2, "responses:\n{responses}");
assert_eq!(
responses.matches("\n\"-object\" \"fake-object.exe\"").count(),
2,
"both reports must preserve the multiline command shape:\n{responses}"
);
for config in ["all-features", "no-default"] {
let report = tmp.path().join(format!("target/coverage/lcov-{config}.info"));
assert_eq!(fs::read_to_string(report).unwrap().trim(), "TN:");
Expand All @@ -2455,6 +2474,12 @@ fn windows_coverage_report_retries_error_206_with_response_file() {
],
);
assert_failed(&failed, "failed response-file fallback");
let invocations = fs::read_to_string(&llvm_cov_log).unwrap();
assert_eq!(
invocations.lines().count(),
3,
"both quote styles must reach llvm-cov:\n{invocations}"
);
let failed_report = tmp.path().join("target/coverage/lcov-all-features.info");
assert!(!failed_report.exists(), "failed response-file fallback must remove partial report");
assert!(
Expand Down
11 changes: 9 additions & 2 deletions crates/cargo-anvil/tests/snapshots/snapshots__ado_backend.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2858,14 +2858,16 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
}
$command = [regex]::Match(
$failedProcess.Groups['command'].Value,
'(?s)^(?:"(?<quoted>[^"]+)"|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
'(?s)^(?:"(?<quoted>[^"]+)"|''(?<singleQuoted>[^'']+)''|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
)
if (-not $command.Success) {
Write-Warning 'anvil-llvm-cov: the failed process was not an llvm-cov export command'
return $reportExitCode
}
$llvmCov = if ($command.Groups['quoted'].Success) {
$command.Groups['quoted'].Value
} elseif ($command.Groups['singleQuoted'].Success) {
$command.Groups['singleQuoted'].Value
} else {
$command.Groups['bare'].Value
}
Expand All @@ -2874,10 +2876,15 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
return $reportExitCode
}
$responsePath = [System.IO.Path]::GetFullPath("$OutputPath.llvm-cov.rsp")
$responseArguments = [regex]::Replace(
$command.Groups['arguments'].Value,
"'(?<value>[^']*)'",
{ param($match) '"' + $match.Groups['value'].Value.Replace('"', '\"') + '"' }
)
try {
[System.IO.File]::WriteAllText(
$responsePath,
$command.Groups['arguments'].Value,
$responseArguments,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host 'anvil-llvm-cov: retrying Windows error 206 with an LLVM response file'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2971,14 +2971,16 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
}
$command = [regex]::Match(
$failedProcess.Groups['command'].Value,
'(?s)^(?:"(?<quoted>[^"]+)"|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
'(?s)^(?:"(?<quoted>[^"]+)"|''(?<singleQuoted>[^'']+)''|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
)
if (-not $command.Success) {
Write-Warning 'anvil-llvm-cov: the failed process was not an llvm-cov export command'
return $reportExitCode
}
$llvmCov = if ($command.Groups['quoted'].Success) {
$command.Groups['quoted'].Value
} elseif ($command.Groups['singleQuoted'].Success) {
$command.Groups['singleQuoted'].Value
} else {
$command.Groups['bare'].Value
}
Expand All @@ -2987,10 +2989,15 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
return $reportExitCode
}
$responsePath = [System.IO.Path]::GetFullPath("$OutputPath.llvm-cov.rsp")
$responseArguments = [regex]::Replace(
$command.Groups['arguments'].Value,
"'(?<value>[^']*)'",
{ param($match) '"' + $match.Groups['value'].Value.Replace('"', '\"') + '"' }
)
try {
[System.IO.File]::WriteAllText(
$responsePath,
$command.Groups['arguments'].Value,
$responseArguments,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host 'anvil-llvm-cov: retrying Windows error 206 with an LLVM response file'
Expand Down
11 changes: 9 additions & 2 deletions crates/cargo-anvil/tests/snapshots/snapshots__local_only.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1655,14 +1655,16 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
}
$command = [regex]::Match(
$failedProcess.Groups['command'].Value,
'(?s)^(?:"(?<quoted>[^"]+)"|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
'(?s)^(?:"(?<quoted>[^"]+)"|''(?<singleQuoted>[^'']+)''|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
)
if (-not $command.Success) {
Write-Warning 'anvil-llvm-cov: the failed process was not an llvm-cov export command'
return $reportExitCode
}
$llvmCov = if ($command.Groups['quoted'].Success) {
$command.Groups['quoted'].Value
} elseif ($command.Groups['singleQuoted'].Success) {
$command.Groups['singleQuoted'].Value
} else {
$command.Groups['bare'].Value
}
Expand All @@ -1671,10 +1673,15 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
return $reportExitCode
}
$responsePath = [System.IO.Path]::GetFullPath("$OutputPath.llvm-cov.rsp")
$responseArguments = [regex]::Replace(
$command.Groups['arguments'].Value,
"'(?<value>[^']*)'",
{ param($match) '"' + $match.Groups['value'].Value.Replace('"', '\"') + '"' }
)
try {
[System.IO.File]::WriteAllText(
$responsePath,
$command.Groups['arguments'].Value,
$responseArguments,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host 'anvil-llvm-cov: retrying Windows error 206 with an LLVM response file'
Expand Down
11 changes: 9 additions & 2 deletions justfiles/anvil/checks/llvm-cov.just
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,16 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
}
$command = [regex]::Match(
$failedProcess.Groups['command'].Value,
'(?s)^(?:"(?<quoted>[^"]+)"|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
'(?s)^(?:"(?<quoted>[^"]+)"|''(?<singleQuoted>[^'']+)''|(?<bare>\S+))\s+export\s+(?<arguments>.*)$'
)
if (-not $command.Success) {
Write-Warning 'anvil-llvm-cov: the failed process was not an llvm-cov export command'
return $reportExitCode
}
$llvmCov = if ($command.Groups['quoted'].Success) {
$command.Groups['quoted'].Value
} elseif ($command.Groups['singleQuoted'].Success) {
$command.Groups['singleQuoted'].Value
} else {
$command.Groups['bare'].Value
}
Expand All @@ -147,10 +149,15 @@ anvil-llvm-cov: anvil-llvm-cov-validate-prereqs anvil-impact
return $reportExitCode
}
$responsePath = [System.IO.Path]::GetFullPath("$OutputPath.llvm-cov.rsp")
$responseArguments = [regex]::Replace(
$command.Groups['arguments'].Value,
"'(?<value>[^']*)'",
{ param($match) '"' + $match.Groups['value'].Value.Replace('"', '\"') + '"' }
)
try {
[System.IO.File]::WriteAllText(
$responsePath,
$command.Groups['arguments'].Value,
$responseArguments,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host 'anvil-llvm-cov: retrying Windows error 206 with an LLVM response file'
Expand Down
Loading