build(mmap): map packs on openbsd, netbsd and dragonfly; document limits (GO-007, GO-008)
syscall.Mmap exists on these systems. README gains a Limits section: the SIGBUS on in-place truncation and the in-memory fallback elsewhere are deferred, and the Resolve order is documented.
- commit
- 83c704caf029705bccef04865ea6a557a583505b
- author
- brice · · 2026-10-10 22:15 UTC
- parent
- 3c103d3
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +9 -3
M README.md +6 -0
| @@ -41,6 +41,12 @@ A `Repo` is safe for concurrent use. Call `Refresh` after the repository changed | |||
| 41 | 41 | ||
| 42 | 42 | Repositories the package does not read are rejected by `Open` with `ErrUnsupported`: SHA-256, reftable, other `extensions.*`, shallow, grafts, replace refs, alternates, partial clones, incremental or stale multi-pack-index. | |
| 43 | 43 | ||
| 44 | + | ## Limits | |
| 45 | + | ||
| 46 | + | - **A pack truncated in place can crash the process.** Packs and indexes are memory-mapped; if another process shrinks one of them while it is mapped, a read of the missing part ends with SIGBUS, which Go cannot recover from. Git always replaces a pack by renaming a new file over it (repack, gc, fetch), and a mapping keeps the old file alive, so this takes an external actor that edits packs in place, or a failing disk. Not handled. | |
| 47 | + | - **Without mmap, packs are read into memory.** Linux, macOS, FreeBSD, OpenBSD, NetBSD and DragonFly map packs. On Windows and other systems the whole `.pack` and `.idx` are read into memory when a pack is opened, so memory grows with the size of the repository. Not handled. | |
| 48 | + | - **Revision names.** `Resolve` follows `git rev-parse` for plain names: a tag wins over a branch of the same name, and a full 40 digit id is never read as a ref. Use `ResolveRef` for a full ref name and `ResolveCommitPrefix` for an abbreviation that must designate a commit. | |
| 49 | + | ||
| 44 | 50 | ## Test | |
| 45 | 51 | ||
| 46 | 52 | ```sh | |
| @@ -41,6 +41,12 @@ A `Repo` is safe for concurrent use. Call `Refresh` after the repository changed | |||||
| 41 | 41 | ||||
| 42 | Repositories the package does not read are rejected by `Open` with `ErrUnsupported`: SHA-256, reftable, other `extensions.*`, shallow, grafts, replace refs, alternates, partial clones, incremental or stale multi-pack-index. | 42 | Repositories the package does not read are rejected by `Open` with `ErrUnsupported`: SHA-256, reftable, other `extensions.*`, shallow, grafts, replace refs, alternates, partial clones, incremental or stale multi-pack-index. | ||
| 43 | 43 | ||||
| 44 | + | ## Limits | |||
| 45 | + | ||||
| 46 | + | - **A pack truncated in place can crash the process.** Packs and indexes are memory-mapped; if another process shrinks one of them while it is mapped, a read of the missing part ends with SIGBUS, which Go cannot recover from. Git always replaces a pack by renaming a new file over it (repack, gc, fetch), and a mapping keeps the old file alive, so this takes an external actor that edits packs in place, or a failing disk. Not handled. | |||
| 47 | + | - **Without mmap, packs are read into memory.** Linux, macOS, FreeBSD, OpenBSD, NetBSD and DragonFly map packs. On Windows and other systems the whole `.pack` and `.idx` are read into memory when a pack is opened, so memory grows with the size of the repository. Not handled. | |||
| 48 | + | - **Revision names.** `Resolve` follows `git rev-parse` for plain names: a tag wins over a branch of the same name, and a full 40 digit id is never read as a ref. Use `ResolveRef` for a full ref name and `ResolveCommitPrefix` for an abbreviation that must designate a commit. | |||
| 49 | + | ||||
| 44 | ## Test | 50 | ## Test | ||
| 45 | 51 | ||||
| 46 | ```sh | 52 | ```sh | ||
M mmap_notlinux.go +1 -1
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: MIT | |
| 2 | 2 | ||
| 3 | - | //go:build darwin || freebsd | |
| 3 | + | //go:build darwin || freebsd || openbsd || netbsd || dragonfly | |
| 4 | 4 | ||
| 5 | 5 | package git | |
| 6 | 6 | ||
| @@ -1,6 +1,6 @@ | |||||
| 1 | // SPDX-License-Identifier: MIT | 1 | // SPDX-License-Identifier: MIT | ||
| 2 | 2 | ||||
| 3 | - | //go:build darwin || freebsd | 3 | + | //go:build darwin || freebsd || openbsd || netbsd || dragonfly |
| 4 | 4 | ||||
| 5 | package git | 5 | package git | ||
| 6 | 6 | ||||
M mmap_other.go +1 -1
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: MIT | |
| 2 | 2 | ||
| 3 | - | //go:build !(linux || darwin || freebsd) | |
| 3 | + | //go:build !(linux || darwin || freebsd || openbsd || netbsd || dragonfly) | |
| 4 | 4 | ||
| 5 | 5 | package git | |
| 6 | 6 | ||
| @@ -1,6 +1,6 @@ | |||||
| 1 | // SPDX-License-Identifier: MIT | 1 | // SPDX-License-Identifier: MIT | ||
| 2 | 2 | ||||
| 3 | - | //go:build !(linux || darwin || freebsd) | 3 | + | //go:build !(linux || darwin || freebsd || openbsd || netbsd || dragonfly) |
| 4 | 4 | ||||
| 5 | package git | 5 | package git | ||
| 6 | 6 | ||||
M mmap_unix.go +1 -1
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | // SPDX-License-Identifier: MIT | |
| 2 | 2 | ||
| 3 | - | //go:build linux || darwin || freebsd | |
| 3 | + | //go:build linux || darwin || freebsd || openbsd || netbsd || dragonfly | |
| 4 | 4 | ||
| 5 | 5 | package git | |
| 6 | 6 | ||
| @@ -1,6 +1,6 @@ | |||||
| 1 | // SPDX-License-Identifier: MIT | 1 | // SPDX-License-Identifier: MIT | ||
| 2 | 2 | ||||
| 3 | - | //go:build linux || darwin || freebsd | 3 | + | //go:build linux || darwin || freebsd || openbsd || netbsd || dragonfly |
| 4 | 4 | ||||
| 5 | package git | 5 | package git | ||
| 6 | 6 | ||||