mirror of
https://github.com/feigeCode/navop.git
synced 2026-09-21 16:01:21 +00:00
The dynamic-texture API only exists on our zed dynamic-texture branch, so
the published gpui-pre-* snapshot predates it. Instead of a path patch
that ties the build to one host, point the [patch.crates-io] block at a
git fork we own:
feigeCode/gpui-pre, tag fork-0.3.99
The fork is cut from zed@cae01216cb with gpui-component's
script/bump-gpui.ts pipeline. Re-publish with
script/publish-gpui-pre-fork.py and move the patch with
script/migrate-to-git-fork.py; both live in script/.
With the API available again, revert the eda5371ae RenderImage fallback
in remote_desktop_view:
- surface.rs uses DynamicTexture directly; the backing framebuffer
becomes the upload source for paint_dynamic_texture.
- render.rs paints dirty rects via update_dynamic_texture /
paint_dynamic_texture instead of a whole-frame paint_image, and
releases retired handles with drop_dynamic_texture.
- view.rs drops the placeholder handles; the contract tests assert the
dynamic-texture path.
cargo check --workspace --locked: clean. cargo test -p
remote_desktop_view --lib: 241 passed.
230 lines
8.7 KiB
Python
Executable File
230 lines
8.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Rewrite the local `gpui-pre` patch block from path to git dependencies.
|
|
|
|
`script/patch-local-gpui-pre.py` adds a `[patch.crates-io]` block to Navop's
|
|
root `Cargo.toml` so the upstream `gpui-pre-*` crates resolve to a directory
|
|
on the build host. That works for the dev who runs both scripts, but it ties
|
|
every other build host (CI, teammates, deploy machines) to the same
|
|
directory layout. The fix is to keep the patch block but switch each
|
|
`path = "..."` entry to `git = "..." + tag = "..."`, pointing at the fork
|
|
that `script/publish-gpui-pre-fork.py` populates.
|
|
|
|
The patch block stays because `gpui-pre` reaches Navop only transitively
|
|
through `gpui-component`; adding `gpui-pre` to Navop's own `[dependencies]`
|
|
would be unused and rejected. Patching crates.io from path or from git is
|
|
the only mechanism that lets a transitive dep be re-pointed without
|
|
touching the upstream crate's manifest.
|
|
|
|
This script only edits the existing block produced by the path-patch
|
|
script. Both scripts share the same `>>> local gpui-pre patch >>>` /
|
|
`<<< local gpui-pre patch <<<` markers, so they can be interleaved freely:
|
|
|
|
script/patch-local-gpui-pre.py # path patch (dev workstation)
|
|
script/migrate-to-git-fork.py --tag X # switch to git (CI, ship)
|
|
script/migrate-to-git-fork.py --path # switch back to path (dev)
|
|
|
|
Usage:
|
|
script/migrate-to-git-fork.py [options]
|
|
|
|
Options:
|
|
--fork-url URL Git URL of the fork. Required for `--git` (default).
|
|
--tag TAG The tag the fork exposes for the snapshot. Required
|
|
for `--git` (default).
|
|
--path Rewrite the block back to a local path patch. This
|
|
is the inverse of `--git`; the path defaults to the
|
|
`<component>/../.gpui-pre/workspace` layout produced
|
|
by the path-patch script.
|
|
--no-update-lock Print the change but do not run `cargo update`. The
|
|
lock will keep the old path-based entries until you
|
|
run it.
|
|
--dry-run Print what would be written, do not touch files.
|
|
-h, --help Show this help
|
|
|
|
The script refuses to write a git-fork block without a non-empty
|
|
`--fork-url` and `--tag`, and refuses to write a path block when the path
|
|
mirror does not exist. Both refusals are deliberate: a half-written patch
|
|
is worse than a working path patch, and "the path is wrong" is a runtime
|
|
error that only shows up on `cargo check` two minutes later.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
BEGIN_MARKER = "# >>> local gpui-pre patch (generated by script/patch-local-gpui-pre.py) >>>"
|
|
END_MARKER = "# <<< local gpui-pre patch <<<"
|
|
PUBLISH_PREFIX = "gpui-pre"
|
|
|
|
|
|
class Error(Exception):
|
|
"""A user-facing failure, printed without a traceback."""
|
|
|
|
|
|
def run_capture(cmd: list[str], cwd: Path | None = None) -> str:
|
|
result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
raise Error(
|
|
f"command failed with exit code {result.returncode}: {' '.join(cmd)}\n"
|
|
f"{result.stderr}"
|
|
)
|
|
return result.stdout
|
|
|
|
|
|
def read_block(manifest: Path) -> tuple[str, int, int, str]:
|
|
"""Return (text, start_offset, end_offset, prefix_before_block)."""
|
|
text = manifest.read_text()
|
|
pattern = re.compile(
|
|
rf"^{re.escape(BEGIN_MARKER)}$.*?^{re.escape(END_MARKER)}\n?",
|
|
re.MULTILINE | re.DOTALL,
|
|
)
|
|
match = pattern.search(text)
|
|
if match is None:
|
|
raise Error(f"{manifest} has no local gpui-pre patch; run patch-local-gpui-pre.py first")
|
|
return match.group(0), match.start(), match.end(), text[: match.start()]
|
|
|
|
|
|
def parse_block_entries(block: str) -> list[str]:
|
|
"""Extract the patched crate names from an existing patch block.
|
|
|
|
Accepts both the path form (`{ path = "..." }`, written by the
|
|
path-patch script) and the git form (`{ git = "...", tag = "..." }`,
|
|
written by this script) so the two modes can be toggled repeatedly.
|
|
Only the crate names matter: for `--git` the path values are replaced
|
|
outright, and for `--path` the authoritative paths are recomputed by
|
|
`patch-local-gpui-pre.py`.
|
|
"""
|
|
names: list[str] = []
|
|
for line in block.splitlines():
|
|
entry = re.match(r"^\s*([\w-]+)\s*=\s*\{(.*)\}\s*$", line)
|
|
if entry is None:
|
|
continue
|
|
name, payload = entry.group(1), entry.group(2)
|
|
if not name.startswith(PUBLISH_PREFIX):
|
|
continue
|
|
if re.search(r'\b(path|git)\s*=\s*"', payload) is None:
|
|
continue
|
|
names.append(name)
|
|
if not names:
|
|
raise Error(
|
|
f"the patch block in this manifest has no {PUBLISH_PREFIX}-* entries"
|
|
)
|
|
return names
|
|
|
|
|
|
def build_git_block(names: list[str], fork_url: str, tag: str) -> str:
|
|
width = max(len(name) for name in names)
|
|
lines = [
|
|
BEGIN_MARKER,
|
|
"#",
|
|
"# SELF-MAINTAINED: gpui-pre-* is a git fork of the snapshot produced",
|
|
"# by script/patch-local-gpui-pre.py. The fork is owned by us, the tag",
|
|
"# below is bumped by script/publish-gpui-pre-fork.py. To return to a",
|
|
"# path patch (dev workstation only), re-run",
|
|
"# `script/migrate-to-git-fork.py --path`.",
|
|
"[patch.crates-io]",
|
|
]
|
|
for name in names:
|
|
lines.append(
|
|
f'{name.ljust(width)} = {{ git = "{fork_url}", tag = "{tag}" }}'
|
|
)
|
|
lines.append(END_MARKER)
|
|
return "\n".join(lines) + "\n"
|
|
|
|
|
|
def graph_crates(manifest: Path) -> list[str]:
|
|
"""Crates that Navop's graph resolves; only those can be `cargo update -p`."""
|
|
metadata = json.loads(
|
|
run_capture(["cargo", "metadata", "--format-version", "1"], cwd=manifest.parent)
|
|
)
|
|
return sorted(
|
|
{
|
|
package["name"]
|
|
for package in metadata["packages"]
|
|
if package["name"].startswith(PUBLISH_PREFIX)
|
|
}
|
|
)
|
|
|
|
|
|
def main(argv: list[str]) -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description=__doc__,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
)
|
|
parser.add_argument("--fork-url")
|
|
parser.add_argument("--tag")
|
|
parser.add_argument("--path", action="store_true")
|
|
parser.add_argument("--no-update-lock", action="store_true")
|
|
parser.add_argument("--dry-run", action="store_true")
|
|
args = parser.parse_args(argv)
|
|
|
|
root = Path(__file__).resolve().parent.parent
|
|
manifest = root / "Cargo.toml"
|
|
if not manifest.is_file():
|
|
raise Error(f"{manifest} not found")
|
|
|
|
block, start, end, prefix = read_block(manifest)
|
|
names = parse_block_entries(block)
|
|
|
|
if args.path:
|
|
# The path-patch script is the authoritative writer of the path
|
|
# block: it recomputes the relative paths from its own mirror, so
|
|
# delegate instead of trying to reconstruct them here (a git block
|
|
# does not carry the path values at all). It leaves Cargo.lock
|
|
# alone unless told to update, which matches --no-update-lock.
|
|
patcher = root / "script" / "patch-local-gpui-pre.py"
|
|
if not args.dry_run:
|
|
run(
|
|
[
|
|
sys.executable,
|
|
str(patcher),
|
|
"--no-stage",
|
|
],
|
|
cwd=root,
|
|
)
|
|
else:
|
|
print(f"# would run {patcher} --no-stage")
|
|
print(f"# ({len(names)} crates currently in the git block)")
|
|
return 0
|
|
|
|
if not args.fork_url:
|
|
raise Error("--fork-url is required (or pass --path to revert)")
|
|
if not args.tag:
|
|
raise Error("--tag is required (or pass --path to revert)")
|
|
new_block = build_git_block(names, args.fork_url, args.tag)
|
|
kind = "git"
|
|
|
|
if args.dry_run:
|
|
print(f"# would replace {end - start} bytes in {manifest}:")
|
|
print("--- new block ---")
|
|
print(new_block)
|
|
return 0
|
|
|
|
manifest.write_text(prefix + new_block + manifest.read_text()[end:])
|
|
print(f"wrote {kind}-patch block to {manifest} ({len(names)} entries: {', '.join(names)})")
|
|
|
|
if args.no_update_lock:
|
|
print("--no-update-lock: Cargo.lock still resolves to the old source; run")
|
|
print(" cargo update " + " ".join(f"-p {n}" for n in graph_crates(manifest)))
|
|
return 0
|
|
|
|
reachable = graph_crates(manifest)
|
|
if not reachable:
|
|
print("no gpui-pre-* packages reached by Navop's graph; nothing to update")
|
|
return 0
|
|
packages = [arg for n in reachable for arg in ("-p", n)]
|
|
subprocess.run(["cargo", "update", *packages], cwd=root)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
sys.exit(main(sys.argv[1:]))
|
|
except Error as error:
|
|
print(f"error: {error}", file=sys.stderr)
|
|
sys.exit(1)
|