Files
ozan 900d41835f
Build tinqs-git / build (push) Failing after 13m4s
feat: tstudio CLI v0.1.0 — login, repos, clone, doctor + welcome page
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>
2026-05-22 08:31:06 +01:00

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)
}