Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

Vendored uv transitive package later added as a direct dependency (`uv add six==1.16.0`): `vendor --revert` / `remove` / `rollback` half-revert the pair, so `uv sync --locked` fails and `vendor --check` claims nothing references the wheel

已關閉
#1,374 3 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

@mikolalysenko 已經在處理了。

開始於 2026年10月11日。

  • #1384 來自 @mikolalysenko —— 未關閉

評估

難度
4/5
預估耗時
3-5 天
新手友好度
28/100
Issue 類型
缺陷
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
python, rust
領域
build-system, cli

研究方向

Start with revert_uv in crates/socket-patch-core/src/vendor/pypi_uv.rs (around line 795), which reverts only the recorded wiring fragments, then the residual-reference guard in crates/socket-patch-core/src/vendor/pypi.rs (around line 2416). Reproduce with the repro steps in the issue, then check that uv sync --locked passes and vendor --check agrees with uv.lock after vendor --revert. Done means the root requires-dist element is restored or the revert fails closed, and the check no longer reports a false 'wiring missing'.

由索引模型根據 Issue 內容生成。

描述

agent:claimed agent:triaged bug bughunt pm:uv priority:p1

[agent] Found by the scheduled uv bug-hunt routine (ledger #310).

Summary

Vendor a transitive package in a uv project (here six, pulled in by python-dateutil and held at 1.16.0 by a user constraint-dependencies). Vendored mode wires it through [tool.uv] override-dependencies + [tool.uv.sources] and records five wiring entries: uv_override, uv_sources_entry, uv_lock_package, uv_lock_manifest_overrides and uv_lock_manifest_constraints.

Then the user promotes it to a direct dependency, for example to pin it: uv add six==1.16.0. uv writes a new root requires-dist element, { name = "six", path = ".socket/vendor/pypi/<uuid>/six-1.16.0-…whl" }, because the socket-written source routes it. socket-patch never recorded that element.

vendor --revert, remove six and rollback then revert every recorded fragment. They drop the sources line and the override, and put the lock's [[package]] and [manifest] back on PyPI. They leave the root requires-dist element still pointing at the wheel. Only after writing does the residual-reference guard notice that uv.lock still names the uuid dir, and it keeps the wheel and the ledger entry.

The result is a pair uv rejects:

  • uv sync --locked fails with "The lockfile at uv.lock needs to be updated".
  • vendor --revert exits 0. remove and rollback exit 1.
  • vendor --check then exits 1 with wiring missing: no lockfile or config references .socket/vendor/pypi/<uuid> any more … re-run socket-patch vendor to rewire it. That's false, because uv.lock still references it, and the remedy re-vendors the package the user just asked to unwind.

Impact

A user who pins a vendored transitive dependency directly, which is a normal uv add, can't unwind it cleanly. Every --locked / --frozen-checked CI install breaks after the revert. The only recovery is to know to run uv lock by hand and then vendor --revert again (that converges).

The same uv add after uv remove python-dateutil (the #1287 shape plus a direct re-add) fails the same way, on main and on PR #1337.

Repro

Requires a patch API serving a [email protected] patch. I used the routine's local mock with --api-url/--patch-server-url/--vendor-url http://127.0.0.1:8765, abbreviated sp below.

mkdir demo && cd demo
cat > pyproject.toml <<'EOF'
[project]
name = "demo"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = ["attrs>=20"]

[tool.uv]
constraint-dependencies = ["six==1.16.0"]
EOF
uv add -q python-dateutil==2.9.0.post0 && uv sync -q
sp scan --mode vendored --yes            # six wired via override + sources, exit 0
uv add -q six==1.16.0                    # promote to direct; uv.lock root requires-dist now has { name = "six", path = ".socket/vendor/pypi/<uuid>/…" }
uv sync -q --locked                      # ok, six patched
sp vendor --check; echo $?               # 0
sp vendor --revert --json; echo $?       # 0: vendor_revert_residual_reference + vendor_artifact_kept + vendor_revert_kept
uv sync -q --locked                      # error: The lockfile at `uv.lock` needs to be updated
sp vendor --check; echo $?               # 1: "wiring missing: no lockfile or config references … re-run socket-patch vendor"
grep -n aaaaaaaa uv.lock                 # requires-dist = [ …, { name = "six", path = ".socket/vendor/pypi/…/six-1.16.0-py2.py3-none-any.whl" } ]

After the revert, pyproject.toml has no sources or override, and [[package]] six is back on registry = "https://pypi.org/simple". The root [package.metadata] requires-dist still carries the path element.

Expected vs actual

  • Expected: the revert leaves a pair uv sync --locked accepts. Either restore the root element to the specifier pyproject.toml declares now ({ name = "six", specifier = "==1.16.0" }, the #840 respell rule for root requirement entries), or, failing that, write nothing and drift-keep both files (fail closed, as the PEP 723 script lane already does for this exact shape). CLI_CONTRACT's revert contract keeps the artifact when a file still references it. It doesn't allow a half-written uv pair, and #806 / #821 / #840 were the same class of half-revert.
  • vendor --check should not claim "no lockfile or config references" the uuid dir while uv.lock does.
  • Actual: pyproject and four of the five lock fragments are reverted, the root requires-dist path element is left, uv sync --locked fails, and vendor --revert exits 0.

Matrix (Linux, main 85105c9)

unwind uv 0.5.31 uv 0.12.24
vendor --revert (parent kept, uv add six==1.16.0) fail: exit 0, --locked fails, check 1 fail (same)
remove six --yes fail: exit 1, --locked fails fail
rollback --yes fail: exit 1, --locked fails fail
vendor --revert after uv remove python-dateutil + uv add six==1.16.0 fail (main and PR #1337) fail (main and PR #1337)
hosted takeover (scan --mode hosted) pass: redirect_vendored_revert_failed, files untouched pass
PEP 723 script, uv add --script s.py six==1.16.0, then revert fail-closed: drift-keep, both files untouched, still patched same
recovery: uv lock, then vendor --revert pass, converges, check 0 pass

The checks are text-level uuid checks with no OS-specific branch, so I didn't run a probe.

Suspect code

  • crates/socket-patch-core/src/vendor/pypi_uv.rs:795 (revert_uv): only the recorded records are reverted. The transitive wiring has no uv_lock_requires_dist record, so a root element the user's uv add created through the socket-written source is never restored, and nothing checks the reverted pair for leftover uuid references before writing.
  • crates/socket-patch-core/src/vendor/pypi.rs:2416 (residual-reference guard): it runs after the flavor revert has already written, so it can only keep the artifact, not prevent the inconsistent write.
  • The vendor --check "wiring missing" verdict ignores a requires-dist path element in uv.lock.
主要語言
Rust
星號
8
分支
1
平均合併
19 小時 1 分鐘
30 天內合併 PR
473

環境準備

  • 沒有 Dockerfile 或 Docker Compose 檔案
  • 沒有 Pull Request 範本
  • 閱讀貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

SocketDev/socket-patch 的其他 Issue

查看 SocketDev/socket-patch 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。