| 📦 Turbo Core — files rewritten outside reload into their windows; the agent window wraps what you type and keeps a long paste aside as a token (#28); configrepo fetches a shared .turbo-<slug> from a forge URL (#25) fe23288 k33g 10h ago | 1 | # configrepo |
| 2 | |
| 3 | Copies a project's editor directory — `.turbo-go`, `.turbo-rust` — out of a repository somebody shares, from the URL a forge shows for the directory holding it. |
| 4 | |
| 5 | ``` |
| 6 | turbo-go -load-config https://rickub.com/turbo-editors/configs/tree/main/golang-init |
| 7 | ``` |
| 8 | |
| 9 | fetches `golang-init/.turbo-go` into the working directory. |
| 10 | |
| 11 | ## Why git, not an API |
| 12 | |
| 13 | The URL can be on rickub, GitHub, GitLab or Codeberg. Each has a JSON API for reading a directory, each API is different, and rickub's wants a personal access token even to read a public repository. Git is the one thing all of them speak the same way, with no token: the fetch is `git ls-remote` to find the repository and its branches, then `git clone --depth 1 --branch <ref>` into a temporary directory, then a copy. The price is that `git` must be installed, which on the machine of somebody running a terminal IDE it is. `ErrNoGit` is what you get otherwise. |
| 14 | |
| 15 | ## Reading the URL |
| 16 | |
| 17 | `Parse` understands what the browsers show: |
| 18 | |
| 19 | | Shape | Forge | |
| 20 | | --- | --- | |
| 21 | | `https://host/owner/repo/tree/main/dir` | rickub, GitHub | |
| 22 | | `https://host/group/sub/repo/-/tree/main/dir` | GitLab — the owner keeps its slashes | |
| 23 | | `https://host/owner/repo/src/branch/main/dir` | Codeberg, Forgejo, Gitea — also `src/tag/`, `src/commit/` | |
| 24 | | `https://host/owner/repo` | a repository: default branch, root | |
| 25 | |
| 26 | `blob/` is taken like `tree/`, so a URL to a file inside the directory works too. |
| 27 | |
| 28 | **A branch with a slash in it** — `feature/x` — cannot be told from the path by the URL alone. `Parse` takes the first segment as the ref and the rest as the path; `Load` then asks the repository for its branches and tags (`git ls-remote`) and `resolveRef` picks the **longest** one that begins `ref/path`, giving the rest back to the path. Nothing matching leaves both as they were and the clone reports the missing branch in git's own words. |
| 29 | |
| 30 | **Where to clone from.** GitHub, GitLab and Codeberg serve git at the address the browser shows. rickub does not — pages on `rickub.com`, repositories on `git.rickub.com` — so `CloneURLs` offers `https://host/owner/repo.git` and then `https://git.host/owner/repo.git`, and `firstAnswering` takes the first whose `ls-remote` answers. The listing does two jobs at once: telling the candidates apart, and being what a slashed ref is resolved against. |
| 31 | |
| 32 | ## What is copied, and where |
| 33 | |
| 34 | Inside the checkout, `locate` looks for `<path>/.turbo-go`, or takes `<path>` itself when its last segment already is `.turbo-go`. Every regular file under it is copied with `projectfile.Write` — same mode, same atomic rename, directories made on the way — so a loaded configuration is created exactly as the editor creates one itself. Symbolic links and anything else that is not a regular file stay behind: a configuration is files. |
| 35 | |
| 36 | The destination is `dest/.turbo-go`, `dest` being the working directory. **If it already exists, nothing is done and `ErrExists` says so.** A project's configuration is a decision the project made; the editor does not overwrite it because a URL was typed. Move it away first. |
| 37 | |
| 38 | `GIT_TERMINAL_PROMPT=0` is set on every git call: this runs from a command line that asked for a URL, and a private repository is reported, not waited on. |
| 39 | |
| 40 | ## Public API |
| 41 | |
| 42 | | Name | What it does | |
| 43 | | --- | --- | |
| 44 | | `Parse(url) (Source, error)` | Reads a forge's URL into host, owner, repo, ref, path | |
| 45 | | `Source.CloneURLs() []string` | The clone addresses to try, most likely first | |
| 46 | | `Load(ctx, profile, url, dest) (Result, error)` | Parse, find the repository, clone the ref, copy the editor's directory into dest | |
| 47 | | `Result` | The remote that answered, the ref, the directory created, the files in it | |
| 48 | | `ErrNoGit`, `ErrExists`, `ErrNotFound` | No git; the project already has the directory; the repository has none where the URL points | |
| 49 | |
| 50 | ## Tests |
| 51 | |
| 52 | ```sh |
| 53 | go test ./configrepo/ |
| 54 | TURBO_CORE_NETWORK=1 go test ./configrepo/ # also the real thing, against rickub |
| 55 | ``` |
| 56 | |
| 57 | `sampleRepo` builds a repository on disk with `git init` — two branches, one of them `feature/x` — and `loadFrom` is pointed at it as a remote, which git accepts as readily as a URL. The network test is skipped unless asked for: the suite must pass on a machine with no network. |