-
Notifications
You must be signed in to change notification settings - Fork 3
Source Code Map en
simple_rcs/
simple_rcs.py the core class (1,848 lines) — basically the library
codec.py format primitives (binary encoding, hashing, escaping)
pydifflib.py the production diff engine (StreamSequenceMatcher)
pybsdiff.py binary deltas (BSDIFF40-compatible)
myersdiff.py pure-Python Myers algorithm (reference/benchmark)
myersdiff_ses.py Myers SES variant
myersdiff_dmp.py Myers, diff-match-patch-style offset variant
_myersdiff_ses.pyx Cython port of the SES variant above
_myersdiff_dmp.pyx Cython port of the DMP variant above
simple_rcs_gpg.py GPG signing/verification callbacks
adapters.py stream adapter for psycopg2 large objects
tools/
srcs_commit.py CLI to commit a file
srcs_log.py print history / signature listing
srcs_diff.py unified diff between versions, or between engines
srcs_blame.py per-line author/version attribution
srcs_verify.py verify the hash chain and GPG signatures
srcs_sign_head.py add a GPG signature to the current HEAD
bench_diff.py diff-engine benchmark (time + memory)
compare_memory_usage.py memory-usage comparison utility
tests/unit_tests/ pytest suite (61 tests)
docs/ design/benchmark notes
scripts/ one-off experimental benchmark scripts (e.g. wiki backend)
One class, SimpleRCS, does essentially all the work. Its public surface
looks like this:
| Method | What it does |
|---|---|
commit(content, author, log, ...) |
store a new version (text or binary, optional snapshot) |
checkout(ver_num=None) |
restore a specific version (defaults to HEAD) |
log(limit=None, reverse=False) |
list history metadata |
diff(ver_a, ver_b) |
unified diff between two versions |
blame(depth=None) |
which version/author each line of HEAD came from |
sign_head(signer_callbacks) |
add a GPG signature to HEAD |
verify(verifier_callbacks=None) |
verify the whole hash chain plus signatures |
verify_block_signature(...) |
verify a single block's signature |
get_content() |
return the raw stream content as bytes/text |
Internally, the part that matters most is the backward scan from the end
of the stream (_load_head, _get_prev_block). It never loads the whole
file into memory — it only reads the blocks it needs — so memory usage
doesn't grow with history length.
Pure functions that don't depend on a SimpleRCS instance, so they can be
tested in isolation. Binary payload encoding/decoding
(encode_binary/decode_binary, supports base64/base85/raw), escaping @
inside @...@ values, and computing the v2 block hash all live here.
SimpleRCS passes its own config (hash_algo, encoding) into these as
arguments.
-
StreamSequenceMatcherinpydifflib.py— the only engine actually used on the commit path. A hybrid: greedy hash-based matching, then standarddifflibrefinement on the replace blocks. Doesn't guarantee the shortest edit distance, but it's fast. -
myersdiff*.py— pure-Python implementations of the classic Myers O(ND) algorithm. Two variants: an SES (shortest edit script) version and a diff-match-patch-style offset-based version. Both guarantee minimal edit distance, but their performance diverges depending on the input characteristics. -
_myersdiff_{ses,dmp}.pyx— straight Cython ports of the two above. 15–26x faster than the pure-Python versions, but not wired into the commit path today — they're exercised throughtools/bench_diff.pyonly.
Why there are this many, and what you'd actually reach for, is covered in more depth in Diff Engines.
Used whenever you commit non-text content (bytes). Built to be
compatible with the BSDIFF40 format, so patches can also be created and
applied with the native bsdiff/bspatch tools if you have them
installed.
Shells out to the gpg binary to create and verify signatures. The
SRCS_GPGSIGN_PATH environment variable lets you point at a different
gpg executable. SimpleRCS.sign_head()/verify() take these functions
in as callbacks, so if you wanted a different signing scheme entirely, you
could plug in a replacement with the same callback signature.
SimpleRCS expects a BinaryIO, and something like psycopg2's large
object — which doesn't inherit from BinaryIO — can't be handed over
directly. PsycopgLargeObjectAdapter bridges that gap, so a PostgreSQL
large object can stand in for a .srcs file as the backing store. Why
this particular adapter is a good fit is discussed in
Wiki Backend Design (Korean only).
Each script is a thin CLI wrapper around the SimpleRCS library. Run them
from the repo root with uv run tools/<name>.py. Library code is supposed
to log through logging and never print, but the tools/ scripts are
the exception — printing to stdout is their whole job. See CLI Tools
for what each one does.
[build-system] in pyproject.toml uses setuptools + Cython, and
ext-modules registers the two Cython extensions
(_myersdiff_ses/_myersdiff_dmp). They get built as part of uv sync.
If you edit a .pyx file, you need to rebuild before it takes effect.