Support for but_ctx::ProjectHandle#12647
Conversation
|
@chatgpt-codex-connector[bot] is attempting to deploy a commit to the GitButler Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee2e76bf7d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR implements ProjectHandle in the but-ctx crate, which is the evolution of ProjectId as a self-describing, URL-safe way to identify a project by its on-disk path. It replaces the legacy UUID-based approach and is part of a broader data-consistency plan.
Changes:
- Adds a new
project_handlemodule withRepresentationenum and encoding/decoding functions (percent-encoding for Readable, base64url for Compact), with comprehensive unit tests. - Completes the
ProjectHandlestruct implementation inlib.rs: addsfrom_path,from_path_for_current_channel,as_str,Display,FromStr,TryFrom<&ProjectHandle>andTryFrom<ProjectHandle>forPathBuf, plusTryFrom<ProjectHandle>for bothContextandThreadSafeContext, andContext::new_from_project_handle. - Adds
base64 = "0.22.1"as a direct (per-crate) dependency.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
crates/but-ctx/src/project_handle.rs |
New module implementing the encoding/decoding logic for both Readable and Compact representations, plus comprehensive tests |
crates/but-ctx/src/lib.rs |
Completes the ProjectHandle struct with all required conversions and Context::new_from_project_handle constructor |
crates/but-ctx/Cargo.toml |
Adds base64 = "0.22.1" as a direct dependency for compact encoding |
Cargo.lock |
Lock file update reflecting the new base64 dependency in but-ctx |
Add first-class `ProjectHandle` support to `but-ctx`, including: - bidirectional `Path <-> ProjectHandle` conversion - `Context::new_from_project_handle(...)` - `TryFrom<ProjectHandle>` for `Context` and `ThreadSafeContext` - comprehensive round-trip and malformed-input tests Benefits vs `LegacyProjectId`: - self-describing: handle directly encodes project path; no `projects.json` lookup - lossless: preserves raw filesystem bytes (including non-UTF8 Unix paths) - URL-safe by design for transport/deeplink/API usage - channel-aware UX: compact IDs on release, readable IDs on dev/nightly - reduces coupling to legacy project metadata and global ID indirection Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
The `#[but_api]` proc macro has multiple expansion paths (`legacy`, `tauri`, `napi`) but had no dedicated compile-time coverage. Regressions were easy to introduce and only showed up downstream in `but-api` consumers. Add a separate `but-api-macros/tests` crate that mirrors `but-api` feature flags and uses `trybuild` to verify pass/fail behavior for each macro capability. This makes feature-specific expansion changes explicit and catches breakage at the macro boundary. Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
a422132 to
69cbe39
Compare
ProjectHandleis the evolution ofProjectIdas a URL-safe way to point to a project and create aContextfrom it.Let's have this ready and available in
but-api.This PR is part of the data-consistency plan.
Tasks
but-api-macrotestsbut-apisupport to allow creating contexts fromLegacyProjectIdandProjectHandle.ProjectHandleOrLegacyProjectIdeverywhere and letadd_projectreturn aProjectHandleequivalentCodex Plan
Implement
ProjectHandle+Context::new_from_project_handleSummary
Implement a fully lossless, URL-safe
ProjectHandleinbut-ctxthat supports two wire forms in one type:Readableform for non-release channels (debuggability)Compactform for release/stable channel (short IDs)Add conversion in both directions (
Path<->ProjectHandle) and a newContextconstructor fromProjectHandle, mirroring the existing legacyProjectId-based flow.No AGENTS skill applies directly here (
skill-creator/skill-installerare unrelated), so this will be implemented directly in-crate.Public API changes
crates/but-ctx/src/project_handle.rspub mod project_handle;incrates/but-ctx/src/lib.rsbut_ctx::project_handle::RepresentationReadableCompactRepresentation::for_app_channel(channel: but_path::AppChannel) -> SelfRepresentation::for_current_channel() -> SelfRelease=>CompactNightly/Dev=>ReadableProjectHandlebehavior inlib.rs(or module impl block):pub struct ProjectHandle(String);ProjectHandle::from_path(path: impl AsRef<Path>, representation: Representation) -> anyhow::Result<Self>ProjectHandle::from_path_for_current_channel(path: impl AsRef<Path>) -> anyhow::Result<Self>ProjectHandle::as_str(&self) -> &strimpl TryFrom<&ProjectHandle> for PathBufimpl TryFrom<ProjectHandle> for PathBufimpl std::fmt::Display for ProjectHandleimpl std::str::FromStr for ProjectHandle(validate format on parse)new_from_legacy_project_id:Context::new_from_project_handle(project_handle: ProjectHandle) -> anyhow::Result<Self>PathBuf(gitdir)Context::new(gitdir, but_path::app_config_dir()?, but_path::app_cache_dir().ok())impl TryFrom<ProjectHandle> for Contextimpl TryFrom<ProjectHandle> for ThreadSafeContextEncoding/decoding spec (decision-complete)
Use self-describing prefixes to distinguish formats during decode:
r.c.Path-to-bytes:
gix::path::os_str_into_bstr(path.as_os_str())for lossless path extraction.Readable encoding (
r.):A-Z a-z 0-9 - . _ ~%HHuppercase hexCompact encoding (
c.):URL_SAFE_NO_PAD).Decode rules:
r.: strict percent-decoder to raw bytes.c.: base64url decode to raw bytes.PathBufwithgix::path::try_from_bstring(...).Dependency changes
In
crates/but-ctx/Cargo.toml:base64 = "0.22.1"(for compact encoding/decoding)No additional dependency needed for readable form (manual percent codec).
Tests and scenarios
Add unit tests in
project_handle.rs(orlib.rstest module) covering:Path -> ProjectHandle(Readabe) -> Pathequalityr.andc.both decode correctly%escape errors in readablefor_app_channel(Release)=>CompactNightly/Dev=>Readable#[cfg(unix)])Context::new_from_project_handle(...)returns context with expectedgitdirValidation commands:
cargo test -p but-ctxcargo check -p but-ctx --all-featuresAssumptions and defaults
but_path::AppChannel::Release.r./c.) are the canonical format from first implementation.ProjectHandlewas not previously implemented).Context::new_from_project_handleaccepts a handle pointing atgitdir(same semantic as existingContext::new).