)]}'
{
  "commit": "21e26e1d2b7426e809a6f934feb46b813327d087",
  "tree": "2aa6ac77ca49ea4cd1e31ce3c930b474c6afb552",
  "parents": [
    "7fd5496f177699940dd57decc4ed7695d966d151"
  ],
  "author": {
    "name": "Richard Levasseur",
    "email": "richardlev@gmail.com",
    "time": "Sat Nov 07 05:34:37 2026 +0000"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Sat Nov 07 05:34:37 2026 +0000"
  },
  "message": "refactor(zipapp): port zipper to Rust and add it to the shrubbery toolchain (#4407)\n\nReplaces the Python zipper used by py_zipapp\u0027s PyZipAppCreateZip action\nwith a Rust implementation, so creating zipapps no longer requires a\nPython interpreter in the exec configuration.\n\nThe crates/zipper library mirrors tools/zipapp/zipper.py: same manifest\nformat, symlink-precedence sorting, sandboxed source symlink detection,\nfixed 1980-01-01 timestamps, and permission preservation. It is exposed\nas the `zipper` shrubbery subcommand and selected via\nget_shrubbery_tool,\nfalling back to the Python tool when shrubbery is unavailable.\n\nThe `zip` crate is pinned to 8.x: 9.x adds target-conditional OS deps\nthat fail on powerpc64le until rules_rust supports that platform (see\nthe NOTE in MODULE.bazel).\n\nError handling uses `anyhow` so failures name the manifest line or the\npath they concern. Rust code is linted in CI by a new `rust_lint`\nBazelCI task (`bazel build --config\u003drust-lint //...`), which runs\nclippy with warnings as errors and `unwrap()` forbidden, checks\nrustfmt, and denies `expect()` in the non-test crates.\n\n## Performance\n\nZip creation time only (x86_64 Linux, `-c opt`; median of 5 runs for\nthe small cases, single run for the large ones):\n\n```\nWorkload                            Comp  Python   Rust  Ratio\n3k .py + 5x8 MB blobs (46 MB)         0    0.43s  0.26s   1.6x\nsame                                  6    1.48s  1.59s   0.9x\n10k small .py files                   0    1.19s  0.70s   1.7x\nsame                                  6    1.42s  1.07s   1.3x\nCPython runtime + 10k .py (405 MB)    0    4.08s  1.19s   3.4x\n+ torch/CUDA wheels (7.3 GB, ZIP64)   0    9.7s   7.9s    1.2x\n+ torch/CUDA wheels                   6    335s   370s    0.9x\n```\n\nRust is faster on per-entry overhead, which dominates the default\nuncompressed case. Deflate throughput is ~10% slower because `flate2`\nuses the pure-Rust miniz_oxide backend (chosen so the tool\ncross-compiles for all `dev/platforms`); CPython\u0027s `zipfile` uses C\nzlib.",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "a5b9664ce6c5c8c9f48d39c8e403df68a79e217b",
      "old_mode": 33188,
      "old_path": ".bazelrc",
      "new_id": "ed25451c074dc127f28c78f6944b0622a200a730",
      "new_mode": 33188,
      "new_path": ".bazelrc"
    },
    {
      "type": "modify",
      "old_id": "4b8b5bfb47f198259412162903b93324dd3c25d7",
      "old_mode": 33188,
      "old_path": ".bazelrc.deleted_packages",
      "new_id": "e17e1f250fad1708efa395eaaf3a663a5862117f",
      "new_mode": 33188,
      "new_path": ".bazelrc.deleted_packages"
    },
    {
      "type": "modify",
      "old_id": "6ebc202226bb8101e323bb5b5285bbd2cf593e5f",
      "old_mode": 33188,
      "old_path": "MODULE.bazel",
      "new_id": "ab53d6065cd9685826c9de3df503340fd2e68c60",
      "new_mode": 33188,
      "new_path": "MODULE.bazel"
    },
    {
      "type": "modify",
      "old_id": "c7dbb08e4ac18a93c0b5fda3067ac74de0840eee",
      "old_mode": 33188,
      "old_path": "crates/Cargo.Bazel.lock",
      "new_id": "1f3a91799f9fc3403596e9f846e11ace563847b7",
      "new_mode": 33188,
      "new_path": "crates/Cargo.Bazel.lock"
    },
    {
      "type": "modify",
      "old_id": "05055d4314ff34ff8cb0e7d15495a5bc0bd44c5d",
      "old_mode": 33188,
      "old_path": "crates/Cargo.lock",
      "new_id": "4454b5238d22e5f473e90c4df63032188ad67b54",
      "new_mode": 33188,
      "new_path": "crates/Cargo.lock"
    },
    {
      "type": "modify",
      "old_id": "936cc96e3df53d6add075301477220febfa48c98",
      "old_mode": 33188,
      "old_path": "crates/exe_zip_maker/src/lib.rs",
      "new_id": "17fe2c4d109d98c503fc3070a087f06581f126ad",
      "new_mode": 33188,
      "new_path": "crates/exe_zip_maker/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "338dff3fac8f1bd16b2a3a2dd682a979095c7d14",
      "old_mode": 33188,
      "old_path": "crates/shrubbery/BUILD.bazel",
      "new_id": "9d3dd1e845b9af6222c37502e63e355a6f849e03",
      "new_mode": 33188,
      "new_path": "crates/shrubbery/BUILD.bazel"
    },
    {
      "type": "modify",
      "old_id": "7b06fdad3901f4cb94d6f603b153198ba1194734",
      "old_mode": 33188,
      "old_path": "crates/shrubbery/src/lib.rs",
      "new_id": "ef97e4593c79b7a2b1d63aefb41a382ec52b64d0",
      "new_mode": 33188,
      "new_path": "crates/shrubbery/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "425eb4c6c670e586ce9b130ee3d8fd6af091ca21",
      "old_mode": 33188,
      "old_path": "crates/shrubbery/src/main.rs",
      "new_id": "5399c67ddc81960ee0dbb87e9e7ed4c206729d35",
      "new_mode": 33188,
      "new_path": "crates/shrubbery/src/main.rs"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1c925c8e86b7adf38e28e3d7b5acd6bd26c27310",
      "new_mode": 33188,
      "new_path": "crates/zipper/BUILD.bazel"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "05e0dd373458ef8e06e9dc0f582f193db82891da",
      "new_mode": 33188,
      "new_path": "crates/zipper/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "06ed25a31b0932bcacf87fc6c88b753a9d8a20f6",
      "old_mode": 33188,
      "old_path": "python/private/zipapp/py_zipapp_rule.bzl",
      "new_id": "be00b0426457a5ea8d850356c350d9bc3b5a64e8",
      "new_mode": 33188,
      "new_path": "python/private/zipapp/py_zipapp_rule.bzl"
    },
    {
      "type": "modify",
      "old_id": "76ce96dc6f384d51f35f477dd56d4448c986bacf",
      "old_mode": 33188,
      "old_path": "tests/exe_zip_maker/exe_zip_maker_test.rs",
      "new_id": "1ba26dc2b25658e93379079ed8e91a725138d13e",
      "new_mode": 33188,
      "new_path": "tests/exe_zip_maker/exe_zip_maker_test.rs"
    },
    {
      "type": "modify",
      "old_id": "453ae5b0bcc67c6ab6950d1f7ffc76a05d93d2c6",
      "old_mode": 33188,
      "old_path": "tests/integration/prebuilt_toolchain_test.py",
      "new_id": "1c61188f2ba50aacc76636f7abbb8ac9093cf6da",
      "new_mode": 33188,
      "new_path": "tests/integration/prebuilt_toolchain_test.py"
    },
    {
      "type": "modify",
      "old_id": "b9ca0f33eea3e1b17bd3fcb8317f7dc1f4ce073f",
      "old_mode": 33188,
      "old_path": "tests/modules/rules_rust_stub/rust/defs.bzl",
      "new_id": "d2d9008ee7f7f302aa35b8e359be2aceb1a60fd2",
      "new_mode": 33188,
      "new_path": "tests/modules/rules_rust_stub/rust/defs.bzl"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "91ce64c4f39a951ed9a87b4428967980ca841b3b",
      "new_mode": 33188,
      "new_path": "tests/modules/rules_rust_stub/rust/settings/BUILD.bazel"
    },
    {
      "type": "modify",
      "old_id": "e10de69edfa1c42de7184de042e8f14930749be7",
      "old_mode": 33188,
      "old_path": "tests/shrubbery/shrubbery_test.rs",
      "new_id": "7a03035134d3ef7c50125842cd6e25de49f8fa14",
      "new_mode": 33188,
      "new_path": "tests/shrubbery/shrubbery_test.rs"
    },
    {
      "type": "modify",
      "old_id": "6b336cefc4bc9191752fec90c0c9977cb7a876a3",
      "old_mode": 33188,
      "old_path": "tests/shrubbery_toolchain/shrubbery_toolchain_tests.bzl",
      "new_id": "7a6f6393353b2cddcfd712ba47c28dc115ca280e",
      "new_mode": 33188,
      "new_path": "tests/shrubbery_toolchain/shrubbery_toolchain_tests.bzl"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "8c409e0b7571236c38dcfee2acf38493e4ea0700",
      "new_mode": 33188,
      "new_path": "tests/zipper/BUILD.bazel"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "37fdbce325fd5d996cd779eb8887000260c180f7",
      "new_mode": 33188,
      "new_path": "tests/zipper/zipper_test.rs"
    }
  ]
}
