Skip to content

Source Code Map

Won-Kyu Park edited this page Aug 28, 2026 · 3 revisions

์†Œ์Šค ์ฝ”๋“œ ์ง€๋„

ํŒจํ‚ค์ง€ ๊ตฌ์„ฑ

simple_rcs/
  simple_rcs.py          ํ•ต์‹ฌ ํด๋ž˜์Šค (2344์ค„) โ€” ์—ฌ๊ธฐ๊ฐ€ ์‚ฌ์‹ค์ƒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „์ฒด
  codec.py                ํฌ๋งท ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ (๋ฐ”์ด๋„ˆ๋ฆฌ ์ธ์ฝ”๋”ฉ, ํ•ด์‹œ, ์ด์Šค์ผ€์ดํ•‘)
  matchers.py             diff ๋ฐฑ์—”๋“œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ (import ์‹œ์ ์— ํ•ด์„, ํด๋ฐฑ ํฌํ•จ)
  gitpatch.py             git ํ˜ธํ™˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒจ์น˜ ์ถœ๋ ฅ (๋‚ด๋ณด๋‚ด๊ธฐ ์ „์šฉ)
  pydifflib.py             ํ”„๋กœ๋•์…˜ diff ์—”์ง„ (StreamSequenceMatcher)
  pybsdiff.py              ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ธํƒ€ (BSDIFF40 ํ˜ธํ™˜)
  myersdiff.py             ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ Myers ์•Œ๊ณ ๋ฆฌ์ฆ˜ (์ฐธ๊ณ /๋ฒค์น˜๋งˆํฌ์šฉ)
  myersdiff_ses.py          Myers SES ๋ณ€ํ˜•
  myersdiff_dmp.py          Myers, diff-match-patch ์Šคํƒ€์ผ offset ๋ฒ„์ „
  _myersdiff_ses.pyx       ์œ„ SES๋ฅผ Cython์œผ๋กœ ํฌํŒ…
  _myersdiff_dmp.pyx        ์œ„ DMP๋ฅผ Cython์œผ๋กœ ํฌํŒ…
  simple_rcs_gpg.py         GPG ์„œ๋ช…/๊ฒ€์ฆ ์ฝœ๋ฐฑ
  adapters.py               psycopg2 large object์šฉ ์ŠคํŠธ๋ฆผ ์–ด๋Œ‘ํ„ฐ

tools/
  srcs_commit.py     ํŒŒ์ผ์„ ์ปค๋ฐ‹ํ•˜๋Š” CLI
  srcs_log.py         ํžˆ์Šคํ† ๋ฆฌ/์„œ๋ช… ๋ชฉ๋ก ์ถœ๋ ฅ
  srcs_diff.py        ๋ฒ„์ „ ๊ฐ„, ํ˜น์€ ์—”์ง„ ๊ฐ„ unified diff
  srcs_blame.py       ๋ผ์ธ๋ณ„ ์ €์ž/๋ฒ„์ „ ๊ท€์†
  srcs_verify.py      ํ•ด์‹œ์ฒด์ธ + GPG ์„œ๋ช… ๊ฒ€์ฆ
  srcs_sign_head.py    ํ˜„์žฌ HEAD์— GPG ์„œ๋ช… ์ถ”๊ฐ€
  bench_diff.py        diff ์—”์ง„ ๋ฒค์น˜๋งˆํฌ (์‹œ๊ฐ„ + ๋ฉ”๋ชจ๋ฆฌ)
  compare_memory_usage.py  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋น„๊ต ์œ ํ‹ธ

tests/unit_tests/    pytest ์Šค์œ„ํŠธ (186๊ฐœ ํ…Œ์ŠคํŠธ)
docs/                 ์„ค๊ณ„/๋ฒค์น˜๋งˆํฌ ๋ฉ”๋ชจ
scripts/              ์ผํšŒ์„ฑ ์‹คํ—˜์šฉ ๋ฒค์น˜๋งˆํฌ ์Šคํฌ๋ฆฝํŠธ (์œ„ํ‚ค ๋ฐฑ์—”๋“œ ๋“ฑ)

simple_rcs.py โ€” ํ•ต์‹ฌ

SimpleRCS ํด๋ž˜์Šค ํ•˜๋‚˜๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์‚ฌ์‹ค์ƒ ์ „๋ถ€๋‹ค. ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋Š” ์ด ์ •๋„๋‹ค:

๋ฉ”์„œ๋“œ ์—ญํ• 
commit(content, author, log, ...) ์ƒˆ ๋ฒ„์ „ ์ €์žฅ (ํ…์ŠคํŠธ/๋ฐ”์ด๋„ˆ๋ฆฌ, ์Šค๋ƒ…์ƒท ์˜ต์…˜)
checkout(ver_num=None) ํŠน์ • ๋ฒ„์ „ ๋ณต์› (๊ธฐ๋ณธ์€ HEAD)
log(limit=None, reverse=False) ํžˆ์Šคํ† ๋ฆฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ชฉ๋ก
diff(ver_a, ver_b) ๋‘ ๋ฒ„์ „ ๊ฐ„ unified diff
blame(depth=None) HEAD์˜ ๊ฐ ๋ผ์ธ์ด ์–ด๋А ๋ฒ„์ „/์ €์ž ๊ฒƒ์ธ์ง€
sign_head(signer_callbacks) HEAD์— GPG ์„œ๋ช… ์ถ”๊ฐ€
verify(verifier_callbacks=None) ํ•ด์‹œ์ฒด์ธ + ์„œ๋ช… ์ „์ฒด ๊ฒ€์ฆ
verify_block_signature(...) ๋ธ”๋ก ํ•˜๋‚˜์˜ ์„œ๋ช…๋งŒ ๊ฒ€์ฆ
get_content() ์ŠคํŠธ๋ฆผ ์ „์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜
get_bytes() ์ŠคํŠธ๋ฆผ ์ „์ฒด๋ฅผ ๋ฐ”์ดํŠธ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ (raw/base85 ๋ธ”๋ก์ด ์„ž์—ฌ ์žˆ์œผ๋ฉด ์ด์ชฝ)

์ƒ์„ฑ์ž๋Š” durable(๊ธฐ๋ณธ True)์„ ๋ฐ›๋Š”๋‹ค โ€” ํŒŒ์ผ ๊ฒฝ๋กœ ๋ฐฑ์—”๋“œ์—์„œ ์ปค๋ฐ‹์„ fsyncํ• ์ง€ ์—ฌ๋ถ€๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์ŠคํŠธ๋ฆผ์„ ๋์—์„œ๋ถ€ํ„ฐ ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ์Šค์บ”ํ•˜๋Š” ๋กœ์ง (_load_head, _get_prev_block)์ด ์ œ์ผ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด๋‹ค. ํŒŒ์ผ ์ „์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ ๋ธ”๋ก๋งŒ ์ฝ์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ๊ธธ์–ด์ ธ๋„ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋Š˜์ง€ ์•Š๋Š”๋‹ค. ๋ธ”๋ก ๊ฒฝ๊ณ„๋Š” ver @ ๋งˆ์ปค๋ฅผ ์ฐพ์€ ๋’ค @ ํŒจ๋ฆฌํ‹ฐ๋กœ ํ™•์ •ํ•œ๋‹ค (Storage Format).

์“ฐ๊ธฐ ์ชฝ์€ _rewrite_head๊ฐ€ ๊ฐˆ๋ฆผ๊ธธ์ด๋‹ค. ํŒŒ์ผ ๊ฒฝ๋กœ ๋ฐฑ์—”๋“œ๋Š” _atomic_rewrite_head(prefix ๋ณต์‚ฌ โ†’ ์ž„์‹œ ํŒŒ์ผ โ†’ os.replace)๋กœ ๊ฐ€๊ณ , ๋ฉ”๋ชจ๋ฆฌยทํ˜ธ์ถœ์ž ์ŠคํŠธ๋ฆผ์€ _rewrite_head_in_place๋กœ ๊ฐ„๋‹ค. ํŒŒ๊ดด์  ์“ฐ๊ธฐ๊ฐ€ ์ฝ”๋“œ๋ฒ ์ด์Šค์— ํ•œ ๊ณณ๋งŒ ์žˆ๋„๋ก ๋‘ ์ปค๋ฐ‹ ๊ฒฝ๋กœ(commit/sign_head)๊ฐ€ ๋ชจ๋‘ ์—ฌ๊ธฐ๋ฅผ ์ง€๋‚œ๋‹ค.

gitpatch.py โ€” git ํ˜ธํ™˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒจ์น˜

์šฐ๋ฆฌ ์ €์žฅ ํฌ๋งท(BSDIFF + ๋ธ”๋ก)์€ ๋‹ค๋ฅธ ๋„๊ตฌ๊ฐ€ ์ฝ์ง€ ๋ชปํ•œ๋‹ค. ์ด ๋ชจ๋“ˆ์€ ๋‚ด๋ณด๋‚ด๊ธฐ ๊ฒฝ๋กœ๋‹ค โ€” ๋‘ ๋ฆฌ๋น„์ „์„ ๋ณต์›ํ•œ ๋’ค git diff --binary๊ฐ€ ์“ฐ๋Š” ํ˜•ํƒœ (GIT binary patch + literal ๋ธ”๋ก, zlib + git์‹ base85 ์ค„ ํ”„๋ ˆ์ด๋ฐ)๋กœ ๊ฐ์‹ธ์„œ git apply๊ฐ€ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. tools/srcs_diff.py --binary๊ฐ€ ์œ ์ผํ•œ ํ˜ธ์ถœ์ž๋‹ค.

codec.py โ€” ์ƒํƒœ ์—†๋Š” ํฌ๋งท ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ

SimpleRCS ์ธ์Šคํ„ด์Šค์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•œ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋“ค. ๋ฐ”์ด๋„ˆ๋ฆฌ ํŽ˜์ด๋กœ๋“œ ์ธ์ฝ”๋”ฉ/๋””์ฝ”๋”ฉ(encode_binary/decode_binary, base64/base85/raw ์ง€์›), @...@ ๊ฐ’ ์•ˆ์˜ @ ์ด์Šค์ผ€์ดํ•‘, v2 ๋ธ”๋ก ํ•ด์‹œ ๊ณ„์‚ฐ์ด ์—ฌ๊ธฐ ์žˆ๋‹ค. SimpleRCS๋Š” ์ž๊ธฐ ์„ค์ •(hash_algo, encoding)์„ ์ธ์ž๋กœ ๋„˜๊ฒจ์„œ ์ด ํ•จ์ˆ˜๋“ค์„ ํ˜ธ์ถœํ•œ๋‹ค.

diff ๊ด€๋ จ ๋ชจ๋“ˆ๋“ค โ€” ์™œ ์ด๋ ‡๊ฒŒ ๋งŽ์€๊ฐ€

  • pydifflib.py์˜ StreamSequenceMatcher โ€” ์‹ค์ œ๋กœ ์ปค๋ฐ‹ ๊ฒฝ๋กœ์—์„œ ์“ฐ์ด๋Š” ์œ ์ผํ•œ ์—”์ง„. ํ•ด์‹œ ๊ธฐ๋ฐ˜ ๊ทธ๋ฆฌ๋”” ๋งค์นญ + ๊ต์ฒด ๊ตฌ๊ฐ„๋งŒ ํ‘œ์ค€ difflib์œผ๋กœ ๋‹ค๋“ฌ๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ. ์ตœ๋‹จ ํŽธ์ง‘ ๊ฑฐ๋ฆฌ๋ฅผ ๋ณด์žฅํ•˜์ง„ ์•Š์ง€๋งŒ ๋น ๋ฅด๋‹ค.
  • myersdiff*.py โ€” ์ •ํ†ต Myers O(ND) ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๊ตฌํ˜„. SES(์ตœ๋‹จ ํŽธ์ง‘ ์Šคํฌ๋ฆฝํŠธ) ๋ณ€ํ˜•๊ณผ diff-match-patch ์Šคํƒ€์ผ offset ๊ธฐ๋ฐ˜ ๋ณ€ํ˜• ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ๋‘˜ ๋‹ค ์ตœ๋‹จ ํŽธ์ง‘ ๊ฑฐ๋ฆฌ๋ฅผ ๋ณด์žฅํ•˜์ง€๋งŒ, ์„œ๋กœ ๋‹ค๋ฅธ ์ž…๋ ฅ ํŠน์„ฑ์—์„œ ์„ฑ๋Šฅ์ด ๊ฐˆ๋ฆฐ๋‹ค.
  • _myersdiff_{ses,dmp}.pyx โ€” ์œ„ ๋‘ ๊ฐœ๋ฅผ Cython์œผ๋กœ ํฌํŒ…ํ•œ ๊ฒƒ. ๋นŒ๋“œ๋ผ ์žˆ์œผ๋ฉด ์ด๊ฒŒ ๊ธฐ๋ณธ ๋ฐฑ์—”๋“œ๋‹ค (matchers.py๊ฐ€ import ์‹œ์ ์— dmp_cython โ†’ ses_cython โ†’ stream ์ˆœ์œผ๋กœ ํ•ด์„). ์‹ค์ธก์œผ๋กœ ํด๋ฐฑ์ธ StreamSequenceMatcher๋ณด๋‹ค ~14๋ฐฐ, ๊ฐ™์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ๊ตฌํ˜„๋ณด๋‹ค ~300๋ฐฐ ๋น ๋ฅด๋‹ค. ์ˆœ์ˆ˜ ํŒŒ์ด์ฌ ์Œ๋‘ฅ์ด๋Š” ํด๋ฐฑ ๋Œ€์ƒ์ด ์•„๋‹ˆ๋ผ ์ด๋ฆ„์œผ๋กœ๋งŒ ์„ ํƒ๋œ๋‹ค.

์™œ ์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ๋ฒŒ์ด ์กด์žฌํ•˜๋Š”์ง€, ์‹ค์ œ๋กœ ๋ญ˜ ์จ์•ผ ํ•˜๋Š”์ง€๋Š” Diff Engines์—์„œ ๋” ๊นŠ๊ฒŒ ๋‹ค๋ฃฌ๋‹ค.

pybsdiff.py โ€” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ธํƒ€

ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ์ฝ˜ํ…์ธ (bytes)๋ฅผ ์ปค๋ฐ‹ํ•  ๋•Œ ์“ฐ์ธ๋‹ค. BSDIFF40 ํฌ๋งท๊ณผ ํ˜ธํ™˜๋˜๋„๋ก ๋งŒ๋“ค์–ด์ ธ ์žˆ์–ด์„œ, ์‹œ์Šคํ…œ์— ์„ค์น˜๋œ ๋„ค์ดํ‹ฐ๋ธŒ bsdiff/bspatch ๋„๊ตฌ๋กœ๋„ ํŒจ์น˜๋ฅผ ๋งŒ๋“ค๊ณ  ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

simple_rcs_gpg.py โ€” ์„œ๋ช…/๊ฒ€์ฆ

gpg ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์„œ๋ธŒํ”„๋กœ์„ธ์Šค๋กœ ํ˜ธ์ถœํ•ด์„œ ์„œ๋ช…์„ ๋งŒ๋“ค๊ณ  ๊ฒ€์ฆํ•œ๋‹ค. SRCS_GPGSIGN_PATH ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ gpg ์‹คํ–‰ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. SimpleRCS.sign_head()/verify()๊ฐ€ ์ฝœ๋ฐฑ ํ˜•ํƒœ๋กœ ์ด ๋ชจ๋“ˆ์˜ ํ•จ์ˆ˜๋“ค์„ ๋ฐ›์•„์„œ ์“ฐ๋Š” ๊ตฌ์กฐ๋ผ, GPG๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์„œ๋ช… ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ์œผ๋ฉด ๊ฐ™์€ ์ฝœ๋ฐฑ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋กœ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด ๋ผ์šฐ๋ฉด ๋œ๋‹ค.

adapters.py โ€” DB์— ์ง์ ‘ ๋ถ™์ด๊ธฐ

SimpleRCS๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฑด BinaryIO๋ฟ์ด๋ผ, psycopg2์˜ large object์ฒ˜๋Ÿผ BinaryIO๋ฅผ ์ƒ์†ํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ ๋น„์Šทํ•œ ๊ฐ์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋ชป ๋„˜๊ธด๋‹ค. PsycopgLargeObjectAdapter๊ฐ€ ๊ทธ ํ‹ˆ์„ ๋ฉ”์›Œ์„œ, PostgreSQL large object๋ฅผ .srcs ํŒŒ์ผ ๋Œ€์‹  ๊ทธ๋Œ€๋กœ ๋ฐฑ์—”๋“œ๋กœ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ์ด ์–ด๋Œ‘ํ„ฐ๊ฐ€ ์™œ ํŠน๋ณ„ํžˆ ์ž˜ ๋งž๋Š”์ง€๋Š” Wiki Backend Design์—์„œ ๋‹ค๋ฃฌ๋‹ค.

tools/ โ€” ๋ช…๋ น์ค„ ๋„๊ตฌ

๊ฐ ์Šคํฌ๋ฆฝํŠธ๋Š” SimpleRCS๋ฅผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š” ์–‡์€ CLI ๋ž˜ํผ๋‹ค. uv run tools/<์ด๋ฆ„>.py๋กœ ์ €์žฅ์†Œ ๋ฃจํŠธ์—์„œ ๋ฐ”๋กœ ์‹คํ–‰ํ•œ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฝ”๋“œ๋Š” logging๋งŒ ์“ฐ๊ณ  ์ ˆ๋Œ€ printํ•˜์ง€ ์•Š๋Š” ๊ฒŒ ์›์น™์ด์ง€๋งŒ, tools/ ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ๋“ค์€ CLI ์ถœ๋ ฅ์ด ๋ณธ์—…์ด๋ผ ์ด ๊ทœ์น™์—์„œ ์˜ˆ์™ธ๋‹ค. ๊ฐ ๋„๊ตฌ๊ฐ€ ์ •ํ™•ํžˆ ๋ญ˜ ํ•˜๋Š”์ง€๋Š” CLI Tools ์ฐธ๊ณ .

๋นŒ๋“œ

pyproject.toml์˜ [build-system]์ด setuptools + Cython์„ ์“ฐ๋„๋ก ์„ค์ •๋ผ ์žˆ๊ณ , ext-modules์— _myersdiff_ses/_myersdiff_dmp ๋‘ Cython ํ™•์žฅ์ด ๋“ฑ๋ก๋ผ ์žˆ๋‹ค. uv syncํ•  ๋•Œ ๊ฐ™์ด ๋นŒ๋“œ๋œ๋‹ค. .pyx ํŒŒ์ผ์„ ๊ณ ์น˜๋ฉด ๋‹ค์‹œ ๋นŒ๋“œํ•ด์•ผ ๋ฐ˜์˜๋œ๋‹ค.

Clone this wiki locally