From 217e49fb1f4b8942b739ffe8e153209fe31dc8ec Mon Sep 17 00:00:00 2001 From: Aly Raffauf Date: Wed, 8 Jul 2026 09:56:04 -0400 Subject: [PATCH] gitutil: extract tangled remote URL helper --- internal/cli/repo_clone.go | 6 +++++- internal/cli/repo_create.go | 6 +++++- internal/gitutil/checkout_pull.go | 2 +- internal/gitutil/clone_repo.go | 15 +++++++++++---- internal/gitutil/push_repo.go | 2 +- internal/gitutil/repo_context.go | 15 +++++++++++---- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/internal/cli/repo_clone.go b/internal/cli/repo_clone.go index d4143b6..0563c79 100644 --- a/internal/cli/repo_clone.go +++ b/internal/cli/repo_clone.go @@ -28,7 +28,11 @@ The default destination is the repository name.`, } fmt.Printf("Cloning %s/%s into %s...\n", handle, repo, dest) - if err := gitutil.CloneRepo(ctx, handle, repo, dest); err != nil { + if err := gitutil.CloneRepo(ctx, gitutil.CloneRepoParams{ + Handle: handle, + Repo: repo, + RepoDir: dest, + }); err != nil { return fmt.Errorf("clone %q: %w", args[0], err) } return nil diff --git a/internal/cli/repo_create.go b/internal/cli/repo_create.go index 76745b3..3faa5f2 100644 --- a/internal/cli/repo_create.go +++ b/internal/cli/repo_create.go @@ -69,7 +69,11 @@ Requires authentication (run "tg auth login" first).`, fmt.Printf("Created repository %s/%s\n", handle, args[0]) if repoCreateClone { - if err := gitutil.CloneRepo(ctx, handle, args[0], args[0]); err != nil { + if err := gitutil.CloneRepo(ctx, gitutil.CloneRepoParams{ + Handle: handle, + Repo: args[0], + RepoDir: args[0], + }); err != nil { return fmt.Errorf("clone new repository: %w", err) } } diff --git a/internal/gitutil/checkout_pull.go b/internal/gitutil/checkout_pull.go index 6d660df..392ffcd 100644 --- a/internal/gitutil/checkout_pull.go +++ b/internal/gitutil/checkout_pull.go @@ -23,7 +23,7 @@ type CheckoutPullParams struct { // CheckoutPull fetches the target branch as detached HEAD and applies // the PR's gzipped patch blob on top, all inside params.RepoDir. func CheckoutPull(ctx context.Context, params CheckoutPullParams) error { - fetchURL := fmt.Sprintf("git@tangled.org:%s/%s", params.TargetHandle, params.TargetRepo) + fetchURL := tangledRemoteURL(params.TargetHandle, params.TargetRepo) if err := runIn(params.RepoDir, ctx, "git", "fetch", fetchURL, params.TargetBranch); err != nil { return fmt.Errorf("fetch target branch: %w", err) } diff --git a/internal/gitutil/clone_repo.go b/internal/gitutil/clone_repo.go index 2bc3749..f336dbd 100644 --- a/internal/gitutil/clone_repo.go +++ b/internal/gitutil/clone_repo.go @@ -2,10 +2,17 @@ package gitutil import ( "context" - "fmt" ) -func CloneRepo(ctx context.Context, handle, repo, repoDir string) error { - url := fmt.Sprintf("git@tangled.org:%s/%s", handle, repo) - return run(ctx, "git", "clone", url, repoDir) +// CloneRepoParams groups the inputs to CloneRepo. +type CloneRepoParams struct { + Handle string // Tangled owner handle + Repo string // repository name + RepoDir string // local directory to clone into +} + +// CloneRepo clones handle/repo from Tangled into params.RepoDir. +func CloneRepo(ctx context.Context, params CloneRepoParams) error { + url := tangledRemoteURL(params.Handle, params.Repo) + return run(ctx, "git", "clone", url, params.RepoDir) } diff --git a/internal/gitutil/push_repo.go b/internal/gitutil/push_repo.go index 3a11d52..a039f47 100644 --- a/internal/gitutil/push_repo.go +++ b/internal/gitutil/push_repo.go @@ -15,7 +15,7 @@ type PushNewRepoParams struct { // PushNewRepo adds a remote at Dir and pushes the current branch. // Fails if RemoteName already exists. func PushNewRepo(ctx context.Context, params PushNewRepoParams) error { - remoteURL := fmt.Sprintf("git@tangled.org:%s/%s", params.Handle, params.Repo) + remoteURL := tangledRemoteURL(params.Handle, params.Repo) if err := runIn(params.Dir, ctx, "git", "remote", "add", params.RemoteName, remoteURL); err != nil { return fmt.Errorf("add remote %q (already exists? use --remote to pick another name): %w", params.RemoteName, err) } diff --git a/internal/gitutil/repo_context.go b/internal/gitutil/repo_context.go index 575907c..34018e9 100644 --- a/internal/gitutil/repo_context.go +++ b/internal/gitutil/repo_context.go @@ -7,6 +7,14 @@ import ( "strings" ) +// tangledSSHPrefix is the SSH remote prefix for Tangled repositories. +const tangledSSHPrefix = "git@tangled.org:" + +// tangledRemoteURL builds the SSH clone/push URL for a Tangled repo. +func tangledRemoteURL(handle, repo string) string { + return tangledSSHPrefix + handle + "/" + repo +} + // RepoContext holds the handle and repo name parsed from a git remote URL. type RepoContext struct { Handle string @@ -24,15 +32,14 @@ func DetectRepoFromCWD(ctx context.Context) (*RepoContext, error) { url := strings.TrimSpace(string(output)) - prefix := "git@tangled.org:" - if !strings.HasPrefix(url, prefix) { + if !strings.HasPrefix(url, tangledSSHPrefix) { return nil, fmt.Errorf( "remote URL %q does not look like a Tangled repo (expected %s/)", - url, prefix, + url, tangledSSHPrefix, ) } - path := strings.TrimPrefix(url, prefix) + path := strings.TrimPrefix(url, tangledSSHPrefix) parts := strings.SplitN(path, "/", 2) if len(parts) != 2 || parts[0] == "" || parts[1] == "" { return nil, fmt.Errorf("could not parse handle/repo from %q", url) -- 2.51.2