900d41835f
Build tinqs-git / build (push) Failing after 13m4s
New `tstudio` CLI binary (cmd/tstudio/) with subcommands:
- login: authenticate via username/password, create API token, open welcome page
- logout: revoke token and clear credentials
- whoami: show current user and auth status
- repos: list accessible repositories
- clone: authenticated HTTPS clone with credential storage
- doctor: check git, git-lfs, auth, and connectivity
Platform changes:
- Landing page: CLI download section with OS-detected install command,
direct download buttons for Windows/macOS/Linux
- /cli/welcome: post-login success page (like gcloud auth_success)
with next steps and resource links
- Makefile: tstudio, tstudio-all, tstudio-upload targets for
cross-platform builds and S3 upload
- .claude/settings.json: full auto-allow permissions for Claude Code
- go.mod: add golang.org/x/term for hidden password input
Builds: tstudio-windows-amd64.exe, tstudio-darwin-arm64,
tstudio-darwin-amd64, tstudio-linux-amd64, tstudio-linux-arm64
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
// Copyright 2026 Tinqs Ltd. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
func cmdClone(args []string) {
|
|
fs := flag.NewFlagSet("clone", flag.ExitOnError)
|
|
fs.Usage = func() {
|
|
fmt.Print("Usage: tstudio clone <owner/repo> [target-dir]\n\nClone a repository using stored credentials.\n")
|
|
}
|
|
fs.Parse(args)
|
|
|
|
if fs.NArg() < 1 {
|
|
fs.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
cfg := mustLoadConfig()
|
|
repoPath := fs.Arg(0)
|
|
targetDir := ""
|
|
if fs.NArg() > 1 {
|
|
targetDir = fs.Arg(1)
|
|
}
|
|
|
|
// Build authenticated HTTPS clone URL
|
|
// Format: https://username:token@instance/owner/repo.git
|
|
instance := strings.TrimRight(cfg.Instance, "/")
|
|
instance = strings.TrimPrefix(instance, "https://")
|
|
instance = strings.TrimPrefix(instance, "http://")
|
|
|
|
cloneURL := fmt.Sprintf("https://%s:%s@%s/%s.git", cfg.Username, cfg.Token, instance, repoPath)
|
|
|
|
gitArgs := []string{"clone", cloneURL}
|
|
if targetDir != "" {
|
|
gitArgs = append(gitArgs, targetDir)
|
|
}
|
|
|
|
fmt.Printf("Cloning %s from %s ...\n", repoPath, cfg.Instance)
|
|
|
|
cmd := exec.Command("git", gitArgs...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
fatal("git clone failed: %v", err)
|
|
}
|
|
|
|
// Set up credential helper so future git operations use the token
|
|
dir := targetDir
|
|
if dir == "" {
|
|
parts := strings.Split(repoPath, "/")
|
|
dir = parts[len(parts)-1]
|
|
}
|
|
|
|
// Configure the remote to not embed the token (use credential helper instead)
|
|
cleanURL := fmt.Sprintf("https://%s/%s.git", instance, repoPath)
|
|
setRemote := exec.Command("git", "-C", dir, "remote", "set-url", "origin", cleanURL)
|
|
setRemote.Run() // best-effort
|
|
|
|
// Store credentials for this host via git credential approve
|
|
credInput := fmt.Sprintf("protocol=https\nhost=%s\nusername=%s\npassword=%s\n\n", instance, cfg.Username, cfg.Token)
|
|
credCmd := exec.Command("git", "credential", "approve")
|
|
credCmd.Stdin = strings.NewReader(credInput)
|
|
credCmd.Run() // best-effort
|
|
|
|
fmt.Printf("Done. Repository cloned to %s/\n", dir)
|
|
}
|