Author SHA1 Message Date
vhaudiquet e6504398ec cli: mark the tree 0.2.0-rc2
CI / snap (push) Successful in 14m10s
CI / build (push) Successful in 8m49s
CI / test (push) Skipped
CI / release (push) Skipped
CI / publish (push) Skipped
2026-10-06 01:14:21 +02:00
vhaudiquet 58cd6f6c41 context: give spawned children a clean fd table
CI / build (push) Successful in 8m44s
CI / test (push) Skipped
CI / publish (push) Skipped
CI / snap (push) Successful in 13m56s
CI / release (push) Skipped
pkh's process carries inheritable descriptors (async runtime, gpgme
sockets, the log tee) that std passes to every child. Tools with
fd-number assumptions then break on the shifted table: mmdebstrap's
apt hook is `cat >&N`, and /bin/sh (dash) rejects any two-digit N
with "Bad fd number" — a fresh-chroot bootstrap died with
"mmdebstrap failed to run" whenever the hook pipe landed above
fd 9, and succeeded from a clean shell where it lands lower.

Sweep fds >= 3 pre-exec in the local driver's spawns: it is the one
funnel every context spawn goes through (schroot and unshare chain
through their parent, ssh execs remotely over libssh2). Verified
end to end: the sid bootstrap test fails on the unfixed code under
a polluted fd table and passes with the sweep under the same table.
2026-10-05 13:27:36 +02:00
vhaudiquet 90a9559c00 deb: collapse the incremental fork logs into one line
The fork announcement, the base selection and the resume note all
described the same thing — building on the previous attempt's tree —
in three consecutive lines. One line now carries the record ids, the
carried/fresh state, and the selection why only when it deviates
from the default pick (a base that did not succeed).
2026-10-05 10:22:58 +02:00
vhaudiquet ee7380f572 deb: shorten the staged-tree copy progress label
The live view's bar template renders the byte counters after the
bar, so baking them into the message too duplicated them and pushed
the line past the terminal width. Announce the copy as
"Restoring <id>" and leave the counters to the view.
2026-10-05 09:50:34 +02:00
vhaudiquet 692e77f1a1 ci: gate release publishing to final tags, upstream-shape the tarball
CI / build (push) Successful in 8m46s
CI / test (push) Skipped
CI / publish (push) Skipped
CI / snap (push) Successful in 13m53s
CI / release (push) Skipped
RC tags (a v* tag with a prerelease suffix) now publish nothing at
all — the release job joins the crates.io job behind the same gate;
only final release tags attach artifacts.

The tarball loses the 'orig' qualifier: 'orig' is the Debian side's
name for the imported upstream tarball (gbp/uscan rename it on
import), not something upstream ships. The asset is
pkh-<version>.tar.gz over a versioned pkh-<version>/ prefix, the
conventional upstream shape.
2026-10-04 17:54:18 +02:00
vhaudiquet ca5e623184 ci: attach the orig tarball and snap to the tag release
CI / build (push) Successful in 8m50s
CI / test (push) Skipped
CI / publish (push) Skipped
CI / snap (push) Successful in 13m54s
CI / release (push) Skipped
A pushed tag only gets Gitea's automatic tree archive: a snapshot
named after the raw tag, unusable as a Debian orig (the upstream
version may not carry a hyphen — 0.2.0-rc1 parses as upstream 0.2.0,
revision rc1, where the Debian encoding of the prerelease is
0.2.0~rc1) and with no release object to hold attachments. A v* tag
now publishes a release with the dpkg-shaped orig tarball (git
archive, prefixed pkh-<version>/), the packed snap and their
checksums; prerelease tags mark the release as such, and an existing
release is reused on a tag re-push. Still nothing published beyond
this repo's release page.
2026-10-04 17:41:59 +02:00
vhaudiquet d0b5ce65a4 deps: build against the crates packaged in Debian
The audit of the lock against Debian's archive (qa.debian.org
madison, sid/trixie/bookworm) showed 255 of 291 crates packaged, the
36 missing ones all Windows/wasm/apple/redox-only. Making the tree
build against the Debian-packaged crates — the difference between a
vendored source package and a thin debcargo one — needed:

- sha1/sha2/md-5 bumped to the digest 0.11 line (sid moved, 0.10 is
  trixie-only): finalize() now returns hybrid-array Output without
  LowerHex (hex::encode it) and no io::Write impl (sha256_file reads
  chunks into update()). The digest outputs are unchanged; the full
  suite including the checksums tests passes.
- crossterm 0.28 -> 0.29: Debian skipped 0.28 entirely.
- reqwest 0.12 -> 0.13: the blocking/json/stream usages carried over
  unchanged.
- suppaftp behind an opt-out 'ftp' feature: the one dependency absent
  from the archive, used only by the plain-FTP upload fallback of
  'pkh put' — the Debian build drops it and the SFTP failure path
  reports the transport as unavailable instead.
- every patch-level requirement pin relaxed to the minor level
  (4.5.51 -> 4.5, 1.0.228 -> 1.0, ...) — semver-compatible, and what
  lets trixie's slightly older crates satisfy the manifest.

Result: 30 of 32 direct dependencies resolve from sid as-is; the
remaining two are indicatif 0.18 (sitting in experimental, migrating)
and the feature-gated suppaftp. No vendoring on sid.
2026-10-04 15:59:56 +02:00
9 changed files with 664 additions and 258 deletions
+66
View File
@@ -123,6 +123,72 @@ jobs:
path: ./*.snap
if-no-files-found: error
release:
# Publishes the release artifacts on a release tag (a v* tag without
# a prerelease suffix — RC tags publish nothing, like the crates.io
# job): the upstream tarball, the packed snap, and their checksums.
# Gitea's automatic per-tag archive is a git-tree snapshot named
# after the raw tag; this produces the conventional upstream shape
# (pkh-<version>.tar.gz, versioned pkh-<version>/ prefix) attached
# to a release page. Nothing is published beyond this repo: no
# crates.io (see the publish job), no snap store. The Debian
# packaging renames the tarball to .orig.tar.gz on import, as
# gbp/uscan always do for upstream releases.
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-')
needs: [build, snap]
runs-on: ubuntu-latest
container:
image: ubuntu:26.04
options: --privileged --cap-add SYS_ADMIN --security-opt apparmor:unconfined
steps:
- name: Set up container image
run: |
apt-get update
apt-get install -y nodejs curl ca-certificates git
- uses: actions/checkout@v6
- uses: actions/download-artifact@v3
with:
name: snap
- name: Build the upstream tarball
run: |
tag="${GITHUB_REF_NAME#v}"
git archive --format=tar.gz --prefix="pkh-${tag}/" \
-o "pkh-${tag}.tar.gz" HEAD
sha256sum "pkh-${tag}.tar.gz" pkh_*_amd64.snap > sha256sums.txt
- name: Create or get the release
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
tag="${GITHUB_REF_NAME#v}"
body="{\"tag_name\":\"$GITHUB_REF_NAME\",\"name\":\"pkh $tag\",\"body\":\"Release artifacts for $tag: the source tarball, the packed snap and their checksums.\",\"draft\":false,\"prerelease\":false}"
release_id=$(curl -sf -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-d "$body" "$api/releases" \
| grep -o '"id":[0-9]*' | head -1 | cut -d: -f2 || true)
if [ -z "$release_id" ]; then
# Already released (e.g. a re-push of the tag): reuse it.
release_id=$(curl -sf "$api/releases/tags/$tag" \
| grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
fi
[ -n "$release_id" ] || { echo "cannot resolve the release id" >&2; exit 1; }
echo "release_id=$release_id" >> "$GITHUB_OUTPUT"
- name: Upload the release assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_ID: ${{ steps.release.outputs.release_id }}
run: |
api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
for f in pkh-*.tar.gz pkh_*_amd64.snap sha256sums.txt; do
echo "attaching $f"
curl -sf -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-F "attachment=@$f" \
"$api/releases/$RELEASE_ID/assets?name=$(basename "$f")"
done
publish:
# Publishes the crate to crates.io on a release tag (a v* tag without
# a prerelease suffix: v0.2.0 publishes, v0.2.0-rc1 does not — release
Generated
+417 -169
View File
@@ -89,10 +89,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "base64"
version = "0.22.1"
name = "aws-lc-rs"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
dependencies = [
"aws-lc-sys",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
dependencies = [
"cc",
"cmake",
"dunce",
"fs_extra",
"pkg-config",
]
[[package]]
name = "base64"
@@ -114,11 +131,11 @@ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
[[package]]
name = "block-buffer"
version = "0.10.4"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
dependencies = [
"generic-array",
"hybrid-array",
]
[[package]]
@@ -193,6 +210,23 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
[[package]]
name = "cfg_aliases"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "chacha20"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
dependencies = [
"cfg-if",
"cpufeatures",
"rand_core",
]
[[package]]
name = "chrono"
version = "0.4.45"
@@ -233,12 +267,31 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486"
[[package]]
name = "cmake"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
"cc",
]
[[package]]
name = "colorchoice"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "combine"
version = "4.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
dependencies = [
"bytes 1.12.1",
"memchr",
]
[[package]]
name = "console"
version = "0.16.6"
@@ -251,6 +304,12 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "const-oid"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
[[package]]
name = "conv"
version = "0.3.3"
@@ -260,6 +319,15 @@ dependencies = [
"custom_derive",
]
[[package]]
name = "convert_case"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -294,9 +362,9 @@ checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48"
[[package]]
name = "cpufeatures"
version = "0.2.17"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
dependencies = [
"libc",
]
@@ -312,15 +380,17 @@ dependencies = [
[[package]]
name = "crossterm"
version = "0.28.1"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
dependencies = [
"bitflags 2.13.2",
"crossterm_winapi",
"derive_more",
"document-features",
"mio",
"parking_lot",
"rustix 0.38.44",
"rustix",
"signal-hook",
"signal-hook-mio",
"winapi",
@@ -337,12 +407,11 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.7"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"generic-array",
"typenum",
"hybrid-array",
]
[[package]]
@@ -414,12 +483,35 @@ dependencies = [
]
[[package]]
name = "digest"
version = "0.10.7"
name = "derive_more"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.119",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer",
"const-oid",
"crypto-common",
]
@@ -455,6 +547,21 @@ dependencies = [
"syn 3.0.6",
]
[[package]]
name = "document-features"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
dependencies = [
"litrs",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "encode_unicode"
version = "1.0.0"
@@ -553,21 +660,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
@@ -577,6 +669,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futures"
version = "0.1.31"
@@ -656,16 +754,6 @@ dependencies = [
"tokio-io",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.17"
@@ -673,8 +761,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
@@ -684,8 +774,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi",
"rand_core",
"wasm-bindgen",
]
[[package]]
@@ -820,6 +913,15 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "hybrid-array"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17"
dependencies = [
"typenum",
]
[[package]]
name = "hyper"
version = "1.11.1"
@@ -856,29 +958,13 @@ dependencies = [
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes 1.12.1",
"http-body-util",
"hyper",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff"
dependencies = [
"base64 0.23.1",
"base64",
"bytes 1.12.1",
"futures-channel",
"futures-util",
@@ -1123,6 +1209,55 @@ dependencies = [
"syn 2.0.119",
]
[[package]]
name = "jni"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
dependencies = [
"cfg-if",
"combine",
"jni-macros",
"jni-sys",
"log",
"simd_cesu8",
"thiserror",
"walkdir",
"windows-link",
]
[[package]]
name = "jni-macros"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"simd_cesu8",
"syn 2.0.119",
]
[[package]]
name = "jni-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
"syn 2.0.119",
]
[[package]]
name = "jobserver"
version = "0.1.35"
@@ -1239,12 +1374,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
@@ -1257,6 +1386,12 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
[[package]]
name = "litrs"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "lock_api"
version = "0.4.14"
@@ -1272,6 +1407,12 @@ version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "lru-slab"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f"
[[package]]
name = "lzma-sys"
version = "0.1.20"
@@ -1294,9 +1435,9 @@ dependencies = [
[[package]]
name = "md-5"
version = "0.10.6"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
dependencies = [
"cfg-if",
"digest",
@@ -1351,23 +1492,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d"
[[package]]
name = "native-tls"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe 0.2.1",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
@@ -1398,31 +1522,6 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "openssl"
version = "0.10.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
dependencies = [
"bitflags 2.13.2",
"cfg-if",
"foreign-types",
"libc",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "openssl-probe"
version = "0.1.6"
@@ -1496,7 +1595,7 @@ checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]]
name = "pkh"
version = "0.2.0-rc1"
version = "0.2.0-rc2"
dependencies = [
"bzip2-rs",
"chrono",
@@ -1568,6 +1667,63 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quinn"
version = "0.11.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11"
dependencies = [
"bytes 1.12.1",
"cfg_aliases",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls",
"socket2",
"thiserror",
"tokio",
"tracing",
"web-time",
]
[[package]]
name = "quinn-proto"
version = "0.11.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe"
dependencies = [
"aws-lc-rs",
"bytes 1.12.1",
"getrandom 0.4.3",
"lru-slab",
"rand",
"rand_pcg",
"ring",
"rustc-hash",
"rustls",
"rustls-pki-types",
"slab",
"thiserror",
"tinyvec",
"tracing",
"web-time",
]
[[package]]
name = "quinn-udp"
version = "0.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016"
dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2",
"tracing",
"windows-sys 0.61.2",
]
[[package]]
name = "quote"
version = "1.0.47"
@@ -1583,6 +1739,32 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
dependencies = [
"chacha20",
"getrandom 0.4.3",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rand_pcg"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
@@ -1633,11 +1815,11 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "reqwest"
version = "0.12.28"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
dependencies = [
"base64 0.22.1",
"base64",
"bytes 1.12.1",
"encoding_rs",
"futures-channel",
@@ -1649,21 +1831,21 @@ dependencies = [
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-tls",
"hyper-util",
"js-sys",
"log",
"mime",
"native-tls",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tokio-util",
"tower",
"tower-http",
@@ -1690,16 +1872,18 @@ dependencies = [
]
[[package]]
name = "rustix"
version = "0.38.44"
name = "rustc-hash"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"bitflags 2.13.2",
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
"semver",
]
[[package]]
@@ -1711,7 +1895,7 @@ dependencies = [
"bitflags 2.13.2",
"errno",
"libc",
"linux-raw-sys 0.12.1",
"linux-raw-sys",
"windows-sys 0.61.2",
]
@@ -1721,6 +1905,7 @@ version = "0.23.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634"
dependencies = [
"aws-lc-rs",
"once_cell",
"rustls-pki-types",
"rustls-webpki",
@@ -1728,21 +1913,62 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustls-native-certs"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
dependencies = [
"openssl-probe 0.2.1",
"rustls-pki-types",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pki-types"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
dependencies = [
"web-time",
"zeroize",
]
[[package]]
name = "rustls-platform-verifier"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
"jni",
"log",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls-platform-verifier-android"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"aws-lc-rs",
"ring",
"rustls-pki-types",
"untrusted",
@@ -1760,6 +1986,15 @@ version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.29"
@@ -1798,6 +2033,12 @@ dependencies = [
"libc",
]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.229"
@@ -1850,18 +2091,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.34+deprecated"
@@ -1902,9 +2131,9 @@ dependencies = [
[[package]]
name = "sha1"
version = "0.10.7"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1913,9 +2142,9 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.10.9"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1974,6 +2203,16 @@ version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "simd_cesu8"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
dependencies = [
"rustc_version",
"simdutf8",
]
[[package]]
name = "simdutf8"
version = "0.1.5"
@@ -2152,7 +2391,7 @@ dependencies = [
"fastrand",
"getrandom 0.4.3",
"once_cell",
"rustix 1.1.5",
"rustix",
"windows-sys 0.61.2",
]
@@ -2270,16 +2509,6 @@ dependencies = [
"syn 3.0.6",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.26.5"
@@ -2449,6 +2678,12 @@ version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
[[package]]
name = "unicode-segmentation"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "unicode-width"
version = "0.2.2"
@@ -2516,10 +2751,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
[[package]]
name = "version_check"
version = "0.9.5"
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "want"
@@ -2594,9 +2833,9 @@ dependencies = [
[[package]]
name = "wasm-streams"
version = "0.4.2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
dependencies = [
"futures-util",
"js-sys",
@@ -2625,6 +2864,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "winapi"
version = "0.3.9"
@@ -2641,6 +2889,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -2735,15 +2992,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
@@ -2915,7 +3163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
dependencies = [
"libc",
"rustix 1.1.5",
"rustix",
]
[[package]]
+31 -23
View File
@@ -1,6 +1,6 @@
[package]
name = "pkh"
version = "0.2.0-rc1"
version = "0.2.0-rc2"
edition = "2024"
authors = ["vhaudiquet"]
description = "pkh is a packaging helper for Debian/Ubuntu packages"
@@ -9,38 +9,46 @@ repository = "https://git.vhaudiquet.fr/vhaudiquet/pkh"
readme = "README.md"
[dependencies]
clap = { version = "4.5.51", features = ["cargo"] }
crossterm = "0.28"
flate2 = "1.1.5"
serde = { version = "1.0.228", features = ["derive"] }
clap = { version = "4.5", features = ["cargo"] }
crossterm = "0.29"
flate2 = "1.1"
serde = { version = "1.0", features = ["derive"] }
libc = "0.2"
csv = "1.3.0"
reqwest = { version = "0.12.9", features = ["blocking", "json", "stream"] }
git2 = "0.20.2"
csv = "1.3"
reqwest = { version = "0.13", features = ["blocking", "json", "stream"] }
git2 = "0.20"
regex = "1"
chrono = "0.4"
tokio = { version = "1.41.1", features = ["rt-multi-thread", "macros", "time", "sync"] }
sha2 = "0.10.8"
sha1 = "0.10"
md-5 = "0.10"
hex = "0.4.3"
log = "0.4.28"
indicatif = "0.18.3"
indicatif-log-bridge = "0.2.3"
env_logger = "0.11.8"
futures-util = { version = "0.3.31", features = ["tokio-io"] }
tokio = { version = "1.41", features = ["rt-multi-thread", "macros", "time", "sync"] }
sha2 = "0.11"
sha1 = "0.11"
md-5 = "0.11"
hex = "0.4"
log = "0.4"
indicatif = "0.18"
indicatif-log-bridge = "0.2"
env_logger = "0.11"
futures-util = { version = "0.3", features = ["tokio-io"] }
tar = "0.4"
xz2 = "0.1"
serde_json = "1.0.145"
directories = "6.0.0"
ssh2 = "0.9.5"
serde_json = "1.0"
directories = "6.0"
ssh2 = "0.9"
gpgme = "0.11"
serde_yaml = "0.9"
unicode-width = "0.2"
parking_lot = "0.12"
suppaftp = "12"
bzip2-rs = "0.1.2"
bzip2-rs = "0.1"
thiserror = "2"
suppaftp = { version = "12", optional = true }
# The plain-FTP upload fallback (the archive masters' queue, dput's
# method) behind a feature: it is the one dependency absent from the
# Debian archive, so the Debian build drops it and the SFTP failure
# path reports the transport as unavailable.
[features]
default = ["ftp"]
ftp = ["dep:suppaftp"]
[dev-dependencies]
test-log = "0.2.19"
+58
View File
@@ -4,6 +4,7 @@ use super::api::{ContextDriver, LineSink, Stream};
use super::capture::pump;
use std::io;
use std::os::unix::fs::symlink;
use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::Arc;
@@ -11,6 +12,30 @@ use std::time::SystemTime;
pub struct LocalDriver;
/// Close every file descriptor above stdio in the spawned child
///
/// pkh's process legitimately carries descriptors that stay open for its
/// lifetime (the async runtime, gpgme sockets, the log tee), and std passes
/// any inheritable one to children. Tools with fd-number assumptions then
/// see their low-numbered allocations land on two-digit fds: mmdebstrap's
/// apt hook is `cat >&N`, which /bin/sh (dash) rejects for N >= 10 with
/// "Bad fd number" — the fresh-chroot bootstrap died exactly there. A
/// clean child table keeps those numbers single-digit.
fn sanitize_fds(cmd: &mut Command) {
unsafe {
cmd.pre_exec(|| {
// One syscall when the kernel has close_range; the loop
// covers the rest (and is what the syscall does anyway).
if libc::syscall(libc::SYS_close_range, 3, libc::c_uint::MAX, 0u32) != 0 {
for fd in 3..1024 {
libc::close(fd);
}
}
Ok(())
});
}
}
impl ContextDriver for LocalDriver {
fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result<PathBuf> {
let dest_root_path = Path::new(dest_root);
@@ -77,6 +102,7 @@ impl ContextDriver for LocalDriver {
if let Some(dir) = cwd {
cmd.current_dir(dir);
}
sanitize_fds(&mut cmd);
cmd.status()
}
@@ -99,6 +125,7 @@ impl ContextDriver for LocalDriver {
cmd.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null());
sanitize_fds(&mut cmd);
let mut child = cmd.spawn()?;
let stdout = child.stdout.take();
@@ -137,6 +164,7 @@ impl ContextDriver for LocalDriver {
if let Some(dir) = cwd {
cmd.current_dir(dir);
}
sanitize_fds(&mut cmd);
cmd.output()
}
@@ -227,4 +255,34 @@ mod tests {
std::fs::remove_dir(name).unwrap();
}
}
/// Inherited descriptors must not leak into spawned children: the
/// tools' low-numbered fd assumptions break on a shifted table
/// (mmdebstrap's dash-executed `cat >&N` apt hook).
#[test]
fn spawned_children_get_a_clean_fd_table() {
// Raw open(): std marks its own descriptors close-on-exec, which
// would make the test pass vacuously.
let mut strays = Vec::new();
for _ in 0..8 {
let path = std::ffi::CString::new("/dev/null").unwrap();
let fd = unsafe { libc::open(path.as_ptr(), libc::O_RDWR) };
assert!(fd >= 0);
strays.push(fd);
}
let mut cmd = Command::new("sh");
cmd.arg("-c").arg("ls /proc/self/fd");
sanitize_fds(&mut cmd);
let out = cmd.output().unwrap();
for fd in strays {
unsafe { libc::close(fd) };
}
// stdio (3) + the directory ls itself opened (1)
let table = String::from_utf8_lossy(&out.stdout);
assert!(
table.lines().count() <= 5,
"child fd table should be clean, got:\n{table}"
);
}
}
+1 -1
View File
@@ -284,7 +284,7 @@ pub(crate) fn chroot_tarball_filename(
Some(m) => {
let mut hasher = Sha256::new();
hasher.update(m.as_bytes());
let hash = format!("{:x}", hasher.finalize());
let hash = hex::encode(hasher.finalize());
format!("{target}-{}-buildd.tar.xz", &hash[..12])
}
}
+45 -35
View File
@@ -641,9 +641,6 @@ async fn build_binary_package_impl(
)
})?;
if build_resume {
log::info!(
"Reusing the build artifacts of the previous attempt (incremental build)"
);
// Before the overlay mounts (see the function's doc): a
// setpriv-era tree handed over here lets the mapped
// build identity run the rules; a failed handover makes
@@ -821,19 +818,26 @@ fn copy_report<'a>(
base_id: &str,
) -> Option<Box<dyn Fn(u64, u64) + Sync + 'a>> {
view.map(|view| {
let label = format!("Copying the staged tree of record {base_id}");
// The views render the byte counters after the bar: the label
// must stay short or the bar line overflows a narrow terminal.
let label = format!("Restoring {base_id}");
view.message(&label);
Box::new(move |pos: u64, total: u64| {
let size = crate::utils::size::format_bytes;
view.byte_progress(
&format!("{label} ({}/{})", size(pos), size(total)),
pos,
total,
)
}) as Box<dyn Fn(u64, u64) + Sync + 'a>
Box::new(move |pos: u64, total: u64| view.byte_progress(&label, pos, total))
as Box<dyn Fn(u64, u64) + Sync + 'a>
})
}
/// The staged-tree clause of the incremental-base log line: right
/// after a successful fork the record's staged tree exists exactly
/// when the base's was carried through the gate.
fn fork_tree_clause(record: &session::Session) -> &'static str {
if record.has_upper() {
"staged tree carried"
} else {
"fresh staged tree"
}
}
/// Resolve the record a build runs in, per the `--incremental` request,
/// against the real sessions root and the chroot tarball the bootstrap
/// would use today. See [`resolve_record_in`].
@@ -893,11 +897,12 @@ fn resolve_record_in(
.filter(|s| !session::lock_is_held(&s.lock_path()).unwrap_or(true))
.collect();
for base in session::rank_base_candidates(candidates) {
let why = if base.manifest().last_outcome == session::OUTCOME_SUCCESS {
"the newest successful record of the target"
} else {
"no successful record among the last usable ones; the newest record"
};
// Only a deviant selection explains itself: forking from
// a record that did not succeed is worth a clause, the
// default pick is not.
let why = (base.manifest().last_outcome != session::OUTCOME_SUCCESS).then_some(
"no successful record among the last usable ones; the newest record",
);
let report = copy_report(view, &base.manifest().id);
match session::fork_record_in(
records_root,
@@ -909,9 +914,14 @@ fn resolve_record_in(
report.as_deref(),
) {
Ok(record) => {
let mut notes = Vec::with_capacity(2);
notes.extend(why);
notes.push(fork_tree_clause(&record));
log::info!(
"Base of the incremental build: record {} ({why})",
base.manifest().id
"Incremental base {} -> record {} ({})",
base.manifest().id,
record.manifest().id,
notes.join(", ")
);
return Ok((record, true));
}
@@ -943,23 +953,23 @@ fn resolve_record_in(
.into()),
1 => {
let base = matches.remove(0);
log::info!(
"Base of the incremental build: record {} (pinned by id)",
base.manifest().id
);
let report = copy_report(view, &base.manifest().id);
Ok((
session::fork_record_in(
records_root,
&base,
host_tree,
identity,
version,
cache_tarball_sha256,
report.as_deref(),
)?,
true,
))
let record = session::fork_record_in(
records_root,
&base,
host_tree,
identity,
version,
cache_tarball_sha256,
report.as_deref(),
)?;
log::info!(
"Incremental base {} -> record {} ({})",
base.manifest().id,
record.manifest().id,
fork_tree_clause(&record)
);
Ok((record, true))
}
_ => {
let found = matches
+10 -12
View File
@@ -44,7 +44,7 @@
use std::collections::BTreeMap;
use std::fs;
use std::io::{self, Seek, Write};
use std::io::{self, Read, Seek, Write};
use std::os::unix::fs::{FileTypeExt, MetadataExt};
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
@@ -806,7 +806,15 @@ fn hex(digest: &[u8]) -> String {
pub(crate) fn sha256_file(path: &Path) -> io::Result<String> {
let mut file = fs::File::open(path)?;
let mut hasher = Sha256::new();
io::copy(&mut file, &mut hasher)?;
// digest 0.11 no longer implements io::Write for hashers
let mut buf = [0u8; 64 * 1024];
loop {
let read = file.read(&mut buf)?;
if read == 0 {
break;
}
hasher.update(&buf[..read]);
}
Ok(hex(&hasher.finalize()))
}
@@ -1316,16 +1324,6 @@ pub(crate) fn fork_record_in(
)));
}
}
log::info!(
"Forked build record {} from record {}: {}",
record.manifest().id,
base_manifest.id,
if carry_upper {
"the staged tree (objects included) is carried"
} else {
"a fresh staged tree; the environment comes from the apt cache"
}
);
Ok(record)
}
+3
View File
@@ -43,8 +43,10 @@ struct LaunchpadData {
ssh_port: u16,
/// Host of the PPA upload queue over anonymous FTP (the transport
/// `pkh put` degrades to when the SSH connection never comes up)
#[cfg(feature = "ftp")]
ftp_host: String,
/// Port of the anonymous FTP upload queue
#[cfg(feature = "ftp")]
ftp_port: u16,
/// Upload queue incoming directory template (`{owner}`/`{ppa}`)
incoming_template: String,
@@ -61,6 +63,7 @@ embed_data! {
/// The PPA upload queue over anonymous FTP (host, port): the transport
/// dput-ng's plain `ppa:` profile pushes over, and the one `pkh put`
/// degrades to when the SSH connection itself never comes up.
#[cfg(feature = "ftp")]
pub(crate) fn ppa_ftp_queue() -> (String, u16) {
(LAUNCHPAD_DATA.ftp_host.clone(), LAUNCHPAD_DATA.ftp_port)
}
+33 -18
View File
@@ -6,6 +6,11 @@
//! transport dput's plain `ppa:` profiles use — through [`ftp`].
pub mod changes;
// The plain-FTP fallback transport: feature-gated (the `ftp` feature) so
// the Debian build can drop its one unpackaged dependency; with the
// feature off, the SFTP failure path reports the transport as
// unavailable instead of degrading to the anonymous FTP queue.
#[cfg(feature = "ftp")]
pub mod ftp;
pub mod ssh;
pub mod target;
@@ -164,24 +169,34 @@ async fn put_impl(opts: &PutOptions<'_>) -> Result<(), Box<dyn std::error::Error
Ok(session) => sftp_transfer(&session, &uploads, incoming, &host, opts.view),
Err(ssh::ConnectFailure::Transport(e)) => {
log::warn!("SSH transport to {host}:{port} failed: {e}");
let (ftp_host, ftp_port) = launchpad::ppa_ftp_queue();
opts.view.message(&format!(
"Falling back to the anonymous FTP queue on {ftp_host}:{ftp_port} \
(dput's upload method)..."
));
ftp::upload_queue(
&ftp_host,
ftp_port,
incoming,
&uploads,
&|name, uploaded, total| {
opts.view.progress(
&format!("Uploading {name}"),
uploaded as usize,
total as usize,
);
},
)
#[cfg(feature = "ftp")]
{
let (ftp_host, ftp_port) = launchpad::ppa_ftp_queue();
opts.view.message(&format!(
"Falling back to the anonymous FTP queue on \
{ftp_host}:{ftp_port} (dput's upload method)..."
));
ftp::upload_queue(
&ftp_host,
ftp_port,
incoming,
&uploads,
&|name, uploaded, total| {
opts.view.progress(
&format!("Uploading {name}"),
uploaded as usize,
total as usize,
);
},
)
}
#[cfg(not(feature = "ftp"))]
{
let _ = (&host, &port, incoming, &uploads);
Err("the SFTP transport failed, and this build has no FTP \
fallback (built without the 'ftp' feature)"
.into())
}
}
Err(ssh::ConnectFailure::Refused(e)) => return Err(e),
};