Contributing to zig-git #
This file covers what you need to know to make a change and get it accepted. README.md says what zig-git is and where it is going.
Where to send changes #
Report issues and send pull requests to the Tangled mirror: https://tangled.org/jcollie.dev/zig-git.
Setting up #
Everything is pinned in the Nix flake, Zig 0.17.0 and git included:
$ git clone https://git.jcollie.dev/jeff/zig-git.git
$ cd zig-git
$ nix develop
Without Nix you need Zig 0.17.0 and a git on PATH. The tests that read a
repository make it with git; without one they are skipped.
Before you send a change #
CI runs these, and a change has to pass all of them:
$ reuse lint # every file has a license
$ zig fmt --check --exclude zig-pkg . # Zig is formatted
$ zig build test --summary all # every test, under SHA-1 and SHA-256
$ zig build check # compiles what nothing else builds
$ nix build # the package; runs the tests in the sandbox
nix build sees only files git knows about. git add a new file before
running it, or the build fails as if the file were missing.
Where things are #
| Path | What |
|---|---|
src/root.zig |
The public API: what the git module exports |
src/object.zig |
Object formats, object IDs, kinds, headers, hashing |
src/Identity.zig |
Author, committer and tagger lines |
src/commit.zig, src/tag.zig, src/tree.zig |
Views of commits, tags and trees |
src/quote.zig |
Paths quoted as git quotes them |
src/ObjectDatabase.zig |
The object database interface |
src/loose.zig |
Loose objects |
src/zlib.zig |
zlib streams, inflated and checked as git checks them |
src/PackIndex.zig |
Pack indexes (.idx), versions 1 and 2 |
src/pack.zig |
Packs: entries, delta chains, reading objects |
src/delta.zig |
Applying a delta to its base |
src/MultiPackIndex.zig |
The multi-pack-index |
src/alternates.zig |
Reading objects/info/alternates and GIT_ALTERNATE_OBJECT_DIRECTORIES |
src/DiskDatabase.zig |
The object database on disk: every objects directory, pack and loose object |
src/Config.zig |
Configuration: its sources, includes, scopes and lookups |
src/config/syntax.zig |
The configuration file syntax, and keys spelled as git spells them |
src/config/value.zig |
Booleans, integers and paths as git reads them |
src/config/parameters.zig |
GIT_CONFIG_PARAMETERS and GIT_CONFIG_COUNT |
src/wildmatch.zig |
git's glob patterns |
src/Diagnostics.zig |
What a failed read was about |
src/testing/fixture.zig |
Repositories made with git for the tests |
src/testing/packs.zig |
Packs and pack indexes written byte by byte for the tests |
src/testing/fuzz.zig |
Fuzz test inputs from the corpus or the fuzzer |
src/fuzz/ |
The fuzz corpus: files git wrote, and patterns |
tools/zig_git.zig |
zig-git, git's commands answered by the library, for comparing with git |
tools/config_command.zig |
zig-git config |
tools/regex.zig |
POSIX extended regular expressions, for zig-git config --get-regexp |
tools/docs_server.zig |
zig build docs-serve |
GLOSSARY.md |
The words for the things in a repository |
docs/adr/ |
Decisions, and why |
Making changes #
Never from git's source #
zig-git is MIT licensed and git is GPL-2.0-only, so nothing here may be
translated from git's source, nor from libgit2, xdiff or any other
implementation whose license this project could not carry
(docs/adr/0004-written-from-documentation-never-gits-source.md). Don't
read them while working on zig-git. What git does comes from its
documentation — the manual pages, gitformat-*, the protocol documents —
and from running it. When the documentation is silent, ask git: make a
repository that exercises the case and see what it answers.
Words #
Use the words in GLOSSARY.md, in code and in comments: an object ID,
never a SHA or an OID; the index is the staging file, and a pack's .idx
is a pack index. A new concept gets an entry there when it gets a name.
git is the oracle #
Correct means what git does. A test that reads a repository makes it with
git through src/testing/fixture.zig and checks the library's answer
against what git says about the same repository, rather than against a
value written into the test. The fixture runs git with no system or
global configuration and a fixed clock, so object IDs are the same on every
machine. The git the tests compare with is the one the flake pins.
zig build test runs every test twice, the second time with
ZIG_GIT_TEST_OBJECT_FORMAT=sha256, so each repository test reads a SHA-1
repository and a SHA-256 one. Nothing may assume an object ID is 20 bytes.
Repositories git refuses to make — a corrupt object, a malformed tree — are
written byte by byte in the test that needs them.
zig-git (tools/zig_git.zig) is the same idea from the command line: some
of git's commands answered by the library and printing what git prints, so
diff <(zig-git ls-tree -r HEAD) <(git ls-tree -r HEAD) checks the library
against git on any repository. Its tests run each command both ways and
compare the output and exit status.
Layers and I/O #
Reading a format (an object header, a commit, a tree) is done on bytes the
caller already has, with no I/O, so it can be tested and fuzzed alone. Only
the storage layer touches files, through a std.Io it is given. Nothing
reads the environment, the clock or the current directory on its own.
Errors #
Anything a repository can get wrong is an error, never a panic, and a
function that can fail on the repository's account takes an optional
*Diagnostics and fills it in. Something this library does not support
returns an error saying so rather than an answer that is nearly right; see
docs/adr/0002-unsupported-revision-options-are-errors.md.
Documentation #
Every public declaration has a doc comment, since the published API documentation is made from them. Comments say why rather than what. The README describes the project as it is now, and its references cite the documents the code was written from.