| @@ -25,6 +25,7 @@ The web interface is then on `127.0.0.1:3200` and wants a reverse proxy with TLS |
| 25 | 25 | - Pull mirrors that fetch a source on a schedule and stay read only and push mirrors that copy every branch and tag to another host after each change |
| 26 | 26 | - Pull requests opened by pushing to `refs/for/<branch>` with no fork needed |
| 27 | 27 | - Static sites served from `<user>.<host>` or a domain of your own, built from a `pages` repository or the `pages` branch of any repository, private ones included |
| 28 | +- Gists of one or more flat files with public or secret visibility, revisions shown as diffs, stars, forks, comments, iframe embeds and a JSON API for uploads from the command line |
| 28 | 29 | - Reports to admins and per account blocking, with hourly limits on new issues, pull requests and repositories |
| 29 | 30 | - SSH and PGP commit verification, TOTP, access tokens and Atom feeds for commits, issues and pull requests |
| 30 | 31 | - Site search over repositories and people with language facets |
| @@ -64,6 +65,21 @@ A site can also answer on a domain of your own once you claim it under settings, |
| 64 | 65 | |
| 65 | 66 | The pages origin never sets or reads cookies and the main site only uses `__Host-` cookies, so a script running on a user site can neither read a session from the main host nor plant a cookie that the main host would later accept. |
| 66 | 67 | |
| 68 | +### Gists |
| 69 | + |
| 70 | +A gist is a bare repository at `~you/.gists/<id>.git` holding a single `main` branch of flat files, so it counts towards your quota, moves with a renamed account and clones or pushes like any repository through `https://git.example.org/gist/<id>.git` or `[email protected]:gist/<id>.git`. The pre-receive hook refuses pushes from anyone but the owner, other branches, deletions of `main`, directories, symlinks, more than 300 files and files over 10 MB, while every save in the web editor becomes a commit whose diff appears on the revisions page. |
| 71 | + |
| 72 | +Secret gists are unlisted rather than private, which means anyone holding the link can read, clone or fork them while neither the gist index nor a profile ever lists one. Creating a gist needs an account at least a day old and shares the hourly upload limit, and anyone signed in may report a gist to the admins, who can delete it from its page. |
| 73 | + |
| 74 | +Raw files and embeds are served from `gist.git.example.org`, a separate origin that never sees a cookie, answers only `GET` and sends every file as `text/plain` or an image under a sandboxed content security policy, so a hostile file cannot run script against the main site. A pinned revision such as `/raw/<id>/<commit>/<name>` is cached as immutable, while the embed page at `/embed/<id>` may be framed by any site. |
| 75 | + |
| 76 | +``` |
| 77 | +curl -u you:TOKEN --data-binary @notes.txt 'https://git.example.org/api/gists?file=notes.txt&public=1' |
| 78 | +curl -u you:TOKEN -H 'Content-Type: application/json' -d '{"description":"demo","public":false,"files":{"a.ml":{"content":"let x = 1"}}}' https://git.example.org/api/gists |
| 79 | +``` |
| 80 | + |
| 81 | +The first form prints the address of the new gist and the second answers with the same JSON that `GET /api/gists/<id>` returns, in the shape of the GitHub gist API, while uploads without `public` default to secret. |
| 82 | + |
| 67 | 83 | ### Mirrors |
| 68 | 84 | |
| 69 | 85 | Ticking *keep it as a read only mirror* on the import page turns the import into a pull mirror that fetches the source again every 1, 4, 8 or 24 hours and refuses pushes, web edits and merges in the meantime. Push mirrors are added under the repository settings with a URL, a username and a token, and they push with `--force --prune` whenever the refs change before retrying after ten minutes if a push fails. Every fetch and push checks the URL again and resolves it once to a public address that stays pinned for the whole transfer, with redirects refused and https as the only protocol allowed. Tokens are sealed with AES-GCM under `mirror.key` in the data directory so that a copy of the database on its own does not reveal any of them. |