144 lines
5.8 KiB
Markdown
144 lines
5.8 KiB
Markdown
# git for MontaukOS
|
|
|
|
Upstream [git/git](https://github.com/git/git), pinned at **v2.39.5**
|
|
(`upstream/`, submodule). Reports itself as `2.39.5-montauk`.
|
|
|
|
Installs as a system program, not an app bundle:
|
|
|
|
| Path | What |
|
|
|------|------|
|
|
| `0:/os/git.elf` | the binary (~3 MB stripped) |
|
|
| `0:/os/git/share/git-core/templates` | `git init` skeleton |
|
|
| `0:/os/git/etc/gitconfig` | system config (not created by the install) |
|
|
|
|
```bash
|
|
make -C dev-vcs/git # build
|
|
make -C dev-vcs/git install # -> MontaukOS/programs/bin/os/
|
|
```
|
|
|
|
`make ports` from the MontaukOS tree does both (git is in the top-level
|
|
Makefile's `SELF_INSTALL_PORTS`).
|
|
|
|
## Status
|
|
|
|
First run on hardware: `git` started, died at exit 128, printed nothing. Two
|
|
bugs, both outside git and both now fixed -- **needs a retest**:
|
|
|
|
1. **`sanitize_stdfds()` opened `/dev/null`**, which MontaukOS does not have,
|
|
so `xopen()` died before any command dispatched. That function guards
|
|
against inheriting closed descriptors, which cannot happen on a system that
|
|
spawns rather than forks; `patches/0002` makes it a no-op.
|
|
2. **Nothing git wrote with `write(2, ...)` ever appeared** -- which is why
|
|
the fatal error was invisible. The libc's `read()`/`write()` passed fd 0/1/2
|
|
straight to `SYS_READ`/`SYS_FWRITE` as file handles, and the kernel hands
|
|
out file handles starting at 0, so those numbers named real files. A
|
|
program's third `open()` owned "stderr". Fixed in the OS: the kernel no
|
|
longer allocates handles 0/1/2, and the libc routes them to the terminal.
|
|
|
|
Second run got as far as `git init` (works, repository created) and then hit
|
|
`fatal: detected dubious ownership`. That is git's safe.directory check
|
|
comparing `lstat()`'s `st_uid` against `geteuid()`; MontaukOS stores no
|
|
per-file owner, so it is false for every directory on the system. The port now
|
|
answers that check directly -- see `compat/montauk-ownership.h`, which also
|
|
records what has to change when the OS grows real ownership.
|
|
|
|
Confirmed working on hardware so far: startup, error output, `git init`, and
|
|
quoted arguments. The rest is still only what the build configuration
|
|
implies.
|
|
|
|
## What should work
|
|
|
|
Everything git does inside one process and one filesystem:
|
|
|
|
- `init`, `add`, `rm`, `mv`, `status`, `diff`, `commit`, `log`, `show`
|
|
- `branch`, `checkout`, `switch`, `restore`, `merge`, `reset`, `revert`
|
|
- `tag`, `stash`, `cherry-pick`, `rebase` (the builtin, non-interactive path)
|
|
- `cat-file`, `rev-parse`, `ls-files`, `ls-tree`, `hash-object`, `fsck`
|
|
- `config`, `blame`, `grep`, `describe`, `bisect`
|
|
- `clone`/`fetch`/`push` **against a local path**, e.g.
|
|
`git clone 0:/users/dan/repo`
|
|
|
|
## What does not work, and why
|
|
|
|
**Anything that starts another process.** MontaukOS spawns (`SYS_SPAWN`); it
|
|
has no `fork()`, no `exec()` and no `pipe()`, and a spawned process cannot
|
|
inherit a pipe for its stdio. Every git feature built on sub-processes fails
|
|
with `ENOSYS` rather than misbehaving:
|
|
|
|
- hooks (`pre-commit`, `commit-msg`, ...) -- the samples are installed but
|
|
never run
|
|
- `$EDITOR`, so `git commit` needs `-m` or `-F`, and interactive rebase and
|
|
`git add -p` are out
|
|
- the pager (harmless -- output goes straight to the terminal, and
|
|
`DEFAULT_PAGER=cat` is compiled in anyway)
|
|
- aliases that shell out (`!command`), `git submodule`, `difftool`,
|
|
`mergetool`, `git gc` (it re-runs itself as `git repack`)
|
|
|
|
**Network transports.** No `http://`, `https://`, `git://` or `ssh://`. The
|
|
port is built `NO_CURL NO_OPENSSL`, and the socket shims fail: MontaukOS TCP
|
|
lives behind IPC handles rather than file descriptors, and DNS resolution is
|
|
inside the kernel with no userspace interface. Local paths are the transport.
|
|
|
|
**Symlinks.** The VFS cannot create them, so git behaves as if
|
|
`core.symlinks=false` -- a symlink in a tree checks out as a regular file
|
|
containing the link target.
|
|
|
|
**File modes.** Built `NO_TRUSTABLE_FILEMODE`, so the executable bit is not
|
|
read back from the filesystem; `core.fileMode` defaults to false.
|
|
|
|
**Threads.** `NO_PTHREADS`, so packing, delta search and `git grep` are
|
|
single-threaded. Correct, just slower.
|
|
|
|
**`mmap`.** `NO_MMAP`, so pack and index access reads into memory instead of
|
|
mapping. Large repositories will be heavier on RAM than on Linux.
|
|
|
|
## Before the first commit
|
|
|
|
The environment MontaukOS hands a process is empty, so the port sets `HOME`
|
|
itself from the session user (`0:/users/<name>`) before git reads any config
|
|
-- that is what makes `--global` work. Set an identity:
|
|
|
|
```
|
|
git config --global user.name "Your Name"
|
|
git config --global user.email [email protected]
|
|
```
|
|
|
|
This is not optional. Left unset, git builds a fallback address from the
|
|
session user and the hostname -- and since `gethostname()` answers `montauk`,
|
|
with no domain in it, git marks the address bogus, appends `.(none)` and
|
|
refuses:
|
|
|
|
```
|
|
fatal: unable to auto-detect email address (got 'admin@montauk.(none)')
|
|
```
|
|
|
|
That is stock git behaviour on any host without a domain name, not something
|
|
the port introduces.
|
|
|
|
## Quoting
|
|
|
|
Arguments are split by the C runtime, not by a shell. `crt1.c` understands
|
|
`'...'` and `"..."` (added for this port), so
|
|
|
|
```
|
|
git commit -m "a message with spaces"
|
|
```
|
|
|
|
reaches git as three arguments. There is no escaping and no substitution --
|
|
a literal quote character cannot be passed.
|
|
|
|
## How the port is put together
|
|
|
|
`Makefile` drives upstream's own build with the toolchain and a long list of
|
|
`NO_*` knobs; the header comment there explains the ones that are not
|
|
self-evident. Two mechanisms fill the gaps:
|
|
|
|
- `compat/` -- headers MontaukOS has no equivalent of, plus
|
|
`libgitcompat.a` with the POSIX functions the libc does not carry. See
|
|
`compat/README`.
|
|
- `patches/` -- two patches: calling `montauk_startup()` from `main()`, and
|
|
emptying `sanitize_stdfds()`, which cannot run without a `/dev/null`.
|
|
|
|
Everything else upstream needed was already reachable through git's own
|
|
portability knobs, which is the reason this port is small.
|