์ฌ๋ฌ git ยท svn ์ ์ฅ์์ ์ํ(๋ฏธ์ปค๋ฐยท์คํ ์ด์งยท๋ธ๋์นยทํธ์ ์ฌ๋ถยท์ํนํธ๋ฆฌ)๋ฅผ ํ ์ฐฝ์์ ํ๋์ ๋ณด๋ macOS/Windows ๋ฐ์คํฌํฑ ๋์๋ณด๋. SourceTree์ "์ํ ๋ณด๊ธฐ"๋ง ๋ผ์ด๋ธ ๊ฒฝ๋ํ.
์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ์ค๊ฐ๋ฉฐ git status๋ฅผ ์ผ์ผ์ด ์น์ง ์์๋, ๋ฑ๋กํ ํด๋ ์๋์ ๋ชจ๋ ์ ์ฅ์๊ฐ ์นด๋ ๊ทธ๋ฆฌ๋๋ก ๋จ๊ณ ๋ณ๊ฒฝ์ด ์๋ repo๋ง ๋ถ๊ฒ ๊ฐ์กฐ๋๋ค. ๋ก์ปฌ ์ ์ฉ โ ๋คํธ์ํฌ๋ฅผ ์ ํ ํ์ง ์๋๋ค.
์นดํ
๊ณ ๋ฆฌ(2_App / 3_Library / 4_Server โฆ)๋ณ๋ก ๋ฌถ์ธ ์นด๋ ๊ทธ๋ฆฌ๋. ๊ฐ ์นด๋์ ๋ธ๋์นยท๋ฏธ์ปค๋ฐ ์ ํธ(โ/?/+)ยทworktreeยทfetched ์๊ฐ์ด ํ์๋๊ณ , ๊นจ๋ํ repo๋ ํ๋ฆฌ๊ฒ, ๋ณ๊ฒฝ์ด ์๋ repo๋ ๋ถ๊ฒ ๊ฐ์กฐ๋๋ค.
- ๋ฑ๋กํ ๋ฃจํธ ํด๋๋ฅผ ์ค์บํด ๊ทธ ์๋ ๋ชจ๋ git/svn ์ ์ฅ์๋ฅผ ์๋ ๋ฐ๊ฒฌ (+ ๊ฐ๋ณ ๊ฒฝ๋ก ์๋ ๋ฑ๋ก, ์ ์ธ ๊ธ๋กญ)
- ์นดํ ๊ณ ๋ฆฌ๋ณ ๊ทธ๋ฃน (๋ฃจํธ ๊ธฐ์ค ์ฒซ ๊ฒฝ๋ก ์ธ๊ทธ๋จผํธ) + ์นด๋ ๊ทธ๋ฆฌ๋
- ๋ฌธ์ ์ฐ์ ์ ๋ ฌ +
๋ฌธ์ ๋ง ๋ณด๊ธฐํํฐ + ์ด๋ฆ ๊ฒ์ - ํค๋ ์์ฝ:
N repos ยท M dirty ยท K behind ยท L ahead
- git: ๋ธ๋์น/detached, ๋ก์ปฌ ๊ธฐ์ค
โahead โbehind,+staged โmodified ?untracked โ conflict โstash, merge/rebase ๋ฑ ์งํ ์ํ, ์ฐ๊ฒฐ worktree ์, ๋ง์ง๋ง fetch ์๊ฐ - svn:
SVN๋ฐฐ์ง + ๋ธ๋์น(URL์ trunk/branches/โฆ) + modified/untracked/conflict (svn์ stagingยทstashยทahead ๊ฐ๋ ์ด ์์ด ๋ฏธํ์)
git status/svn status๋ฑ read-only ๋ก์ปฌ ๋ช ๋ น๋ง ์ฌ์ฉ โ fetch/pull/push ์์- git์
behind๋ ๋ง์ง๋ง fetch ์์ ๊ธฐ์ค์ด๋ผ ์นด๋์fetched Nd ago๋ฅผ ํจ๊ป ํ๊ธฐ(์ค๋๋๋ฉด ํ๋ฆฌ๊ฒ). svn์ out-of-date ํ์ธ์ด ๋คํธ์ํฌ๋ฅผ ํ๋ฏ๋ก ์๋ต
- ๋คํฌ/๋ผ์ดํธ โ ์์คํ ์ธ๊ด ์๋ ์ถ์ข + ํค๋ ํ ๊ธ(system โ light โ dark)
- ๋นํด๋ฆฐ ๊ฐ์กฐ โ ๋ณ๊ฒฝ์ด ์๋ ์นด๋๋ ๋ถ์ ๋ฐฐ๊ฒฝ + ์ข์ธก ์คํธ๋ผ์ดํ, ๊นจ๋ํ ์นด๋๋ ํ๋ฆฌ๊ฒ
- ์ฐํด๋ฆญ ๋ฉ๋ด โ Finder/Explorer ยท ํฐ๋ฏธ๋ ยท SourceTree ์์ ์ด๊ธฐ ยท ๊ฒฝ๋ก ๋ณต์ฌ ยท ์ด ํ๋ก์ ํธ ์ ์ธ
- ํฌ์ปค์ค ๊ฒ์ดํ ํด๋ง โ ์ฐฝ์ด ํ์ฑ์ผ ๋๋ง ์ฃผ๊ธฐ(๊ธฐ๋ณธ 30์ด) ๊ฐฑ์ + ์๋ ์๋ก๊ณ ์นจ
๋ค์ด๋ก๋: Releases์์ macOS(.dmg)ยทWindows(.msi) ์ค์นํ์ผ. macOS ๋น๋๋ Apple Developer ID๋ก ์๋ช ยท๊ณต์ฆ๋์ด ๋ฐ๋ก ์คํ๋๋ค.
์์ค์์ ๋น๋ (Prerequisite: Rust, Node 18+, pnpm, SVN ์ถ์ ์ svn CLI):
pnpm install # ์์กด์ฑ ์ค์น (pnpm-workspace.yaml์ allowBuilds๋ก esbuild ๋น๋ ํ์ฉ)
pnpm tauri dev # ๊ฐ๋ฐ ์คํ (hot reload)
pnpm tauri build # ๋ฆด๋ฆฌ์ฆ ์ฑ ๋ฒ๋ค ๋น๋(.app/.dmg ๋๋ .msi/.exe)์์ธํ ๊ฐ๋ฐยทํ ์คํธยท๋น๋ ์ ์ฐจ: docs/DEVELOPMENT.md
-
์ฑ ์คํ โ ์ฒซ ์คํ์ด๋ฉด "์ค์บํ ํด๋๋ฅผ ์ถ๊ฐํ์ธ์" ํ๋ฉด.
-
โ ์ค์ โ ์ค์บ ๋ฃจํธ ์ถ๊ฐ(์:~/Desktop/@Projects) โ ์ ์ฅํ๋ฉด ๊ทธ ์๋ ๋ชจ๋ git/svn ์ ์ฅ์๊ฐ ์ค์บ๋์ด ์นด๋ ๊ทธ๋ฆฌ๋๋ก ํ์. -
์นด๋ ์ฝ๋ ๋ฒ:
์ ํธ ์๋ฏธ main/detached @a1b2c3ํ์ฌ ๋ธ๋์น / detached HEAD โ no upstreamupstream ์๋ ๋ธ๋์น โ2โ5๋ก์ปฌ ๊ธฐ์ค ahead / behind (์์ผ๋ฉด ์จ๊น) +nโn?nstaged / modified / untracked ํ์ผ ์ โ nโnconflict / stash ์ โ clean๊นจ๋ (ํ๋ฆฌ๊ฒ ๋ ๋) mergingrebasingโฆ์งํ ์ค ์ํ +N worktree์ฐ๊ฒฐ๋ ์ถ๊ฐ worktree ์ SVNSVN ์ ์ฅ์ fetched Nd ago๋ง์ง๋ง fetch ์๊ฐ (git, behind ์ ์ ๋) -
์ฐํด๋ฆญ โ Finder/Explorer, ํฐ๋ฏธ๋, SourceTree ์ด๊ธฐ ยท ๊ฒฝ๋ก ๋ณต์ฌ ยท ์ด ํ๋ก์ ํธ ์ ์ธํ๊ธฐ. ํธ๋ฒ ๋ฒํผ(
F/T/S/โง)์ผ๋ก๋ ๊ฐ๋ฅ. -
โ ์ค์ ์์ ๋ฃจํธ/์ ์ธ ๊ธ๋กญ/ํด๋ง ์ฃผ๊ธฐ/์ค์บ ๊น์ด/stale ๊ธฐ์ค/ํฐ๋ฏธ๋ ์ฑ ์กฐ์ .
| VCS | ์ ๊ทผ ๋ฐฉ์ | ๋ฐ์ดํฐ |
|---|---|---|
| git | git status --porcelain=v2 --branch (+ stash list, rev-parse --git-path, worktree list) |
๋ธ๋์นยทahead/behindยท๋ฏธ์ปค๋ฐยทstashยทstateยทworktree |
| git | .git/FETCH_HEAD mtime |
๋ง์ง๋ง fetch ์๊ฐ |
| svn | svn status ยท svn info --show-item relative-url |
๋ฏธ์ปค๋ฐ ๋ณ๊ฒฝยท๋ธ๋์น(URL) |
๋ชจ๋ ์ ๊ทผ์ read-only ๋ก์ปฌ ๋ช ๋ น์ด๋ฉฐ ์ธ๋ถ ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ์ง ์๋๋ค. ์ ํธ โ ํ๋ ๋งคํ ์์ธ: docs/STATUS-MAPPING.md
Tech Stack: Tauri 2 ยท Rust (tokio, globset, walkdir, dirs-next) ยท Svelte 5 ยท TypeScript ยท Vite
ํ๋์ Tauri 2 ํ๋ก์ธ์ค ์์์ Rust ๋ฐฑ์๋(๋ฐ๊ฒฌยท์ํ ์ฝ๊ธฐยท์ง๊ณ) ์ Svelte 5 ํ๋ก ํธ(๋ ๋) ๊ฐ IPC๋ก ์ฐ๊ฒฐ๋๋ค. ๋จ์ผ main ์๋์ฐ. ๋ฐ์ดํฐ๋ ๋ฐฑ์๋ โ ํ๋ก ํธ ๋จ๋ฐฉํฅ push(repos_updated ์ด๋ฒคํธ), ํ๋ก ํธ โ ๋ฐฑ์๋๋ command invoke ๋ฟ.
graph TD
subgraph Sources["์ ์ฅ์ (read-only ยท ๋คํธ์ํฌ 0)"]
G[(".git ์์
ํธ๋ฆฌ")]
S[(".svn ์์
๋ณต์ฌ๋ณธ")]
end
subgraph Proc["Tauri 2 ํ๋ก์ธ์ค"]
subgraph BE["Rust ๋ฐฑ์๋ (src-tauri/src)"]
Disc["discovery.rs<br/>๋ฃจํธ ์ค์บ ยท ์ ์ธ๊ธ๋กญ ยท ์นดํ
๊ณ ๋ฆฌ ยท VcsKind ํ์ "]
GR["git_reader.rs<br/>porcelain v2 ํ์"]
SR["svn_reader.rs<br/>svn status / info (๋ก์ปฌ)"]
Batch["batch.rs<br/>tokio semaphore(8) + 5s timeout<br/>vcs๋ก reader ๋์คํจ์น"]
Sched["scheduler.rs<br/>WindowEvent::Focused ๊ฒ์ดํ
ํด๋ง"]
State["app_state.rs<br/>AppState(.manage) ยท ์ง์ ์ค๋
์ท ์บ์"]
Emit["emit_gate.rs<br/>ํด์ ๋ณ๊ฒฝ์๋ง emit ยท seq"]
end
subgraph FE["Svelte 5 ํ๋ก ํธ (src)"]
Store["lib/store.svelte.ts<br/>repos_updated ๊ตฌ๋
(seq ํ๊ธฐ)"]
Logic["lib/logic.ts<br/>clean์ ์ด ยท ์ ๋ ฌrank ยท ํํฐ ยท ๊ทธ๋ฃน"]
UI["Grid ยท RepoCard ยท Header ยท Settings ยท EmptyState"]
end
end
G -->|"git CLI"| GR
S -->|"svn CLI"| SR
Disc --> Batch
GR --> Batch
SR --> Batch
Sched -->|"์ฃผ๊ธฐ + ํฌ์ปค์ค"| Batch
Batch -->|"์คํจ repo ๋จธ์ง + ์บ์"| Emit
Emit -->|"emit repos_updated(seq, repos)"| Store
Store --> Logic --> UI
UI -->|"command invoke"| State
flowchart LR
Scan["discovery<br/>RepoRef[] (pathยทnameยทcategoryยทvcs)"]
Read["batch.run_batch<br/>RepoRef๋ณ git/svn reader<br/>(๋ณ๋ ฌยทํ์์์)"]
Merge["snapshot.merge<br/>์คํจ repo๋ ์ง์ ๊ฐ ์ ์ง"]
Gate["emit_gate.should_emit<br/>last_checked ์ ์ธ ๋น๊ต"]
Store["store.repos<br/>(Svelte 5 ๋ฃฌ, seq ํ๊ธฐ)"]
UI["Grid โ groupByCategory<br/>+ compareRepos + filter"]
Scan --> Read --> Merge --> Gate
Gate -->|"๋ณ๊ฒฝ์๋ง emit"| Store
Store --> UI
- ๋ฐ๊ฒฌ โ
discovery๊ฐ ๋ฑ๋ก ๋ฃจํธ๋ฅผ walk(๊น์ด ์ ํยทnode_modules/.git/.svn๋ฑ prune)ํ๋ฉฐ.git(๋๋ ํ ๋ฆฌ) โ git,.svnโ svn ์ผ๋กRepoRef{path, name, category, vcs}๋ฅผ ๋ง๋ ๋ค. ์ ์ธ ๊ธ๋กญ์ ์ ๋๊ฒฝ๋ก์ ๋งค์นญ. - ์ํ ์ฝ๊ธฐ โ
batch.run_batch๊ฐ repo๋ณ๋กvcs์ ๋ฐ๋ผgit_reader/svn_reader๋ฅผ tokio ๋ธ๋กํน ํ์คํฌ๋ก ๋ณ๋ ฌ ์คํ(๋์ ์ํ 8, repo๋น 5์ด ํ์์์). git์status --porcelain=v2 --branch๋ฅผ ๋จ์ผ ํ์ฑ. - ๋จธ์ง/๊ฒ์ดํธ โ ์ง์ ์ค๋
์ท์
AppState์ ์บ์ํด ์ผ์ ์คํจ repo๋ ์ด์ ์์น๋ฅผ ์ ์ง(+error).emit_gate๊ฐlast_checked๋ง ๋ค๋ฅธ ๋ฌด์๋ฏธ ๋ณํ๋ ๊ฑธ๋ฌ ๋ด์ฉ์ด ๋ฐ๋ ๊ฒฝ์ฐ์๋งrepos_updated{seq, repos}๋ฅผ emit. - ๋ ๋ โ ํ๋ก ํธ
store๊ฐlisten("repos_updated")๋ก ๊ตฌ๋ (์ค๋๋seqํ๊ธฐ)ํ๊ณ ,logic.ts์clean์ ์ดยท์ ๋ ฌ rankยทํํฐยท์นดํ ๊ณ ๋ฆฌ ๊ทธ๋ฃน์ผ๋ก ๊ทธ๋ฆฌ๋๋ฅผ ๊ทธ๋ฆฐ๋ค.
ํ๋ก ํธ๋ lib/tauri.ts ํ ๊ณณ์ผ๋ก๋ง ๋ฐฑ์๋์ ์์กดํ๋ค.
| ๋ฐฉํฅ | ์ข ๋ฅ | ์๊ทธ๋์ฒ |
|---|---|---|
| ๋ฐฑโํ | event | repos_updated ({ seq, repos }, ๋ณ๊ฒฝ ์๋ง) |
| ํโ๋ฐฑ | command | get_config ยท set_config |
| ํโ๋ฐฑ | command | scan_repos ยท refresh_status ยท open_action |
์ ์ฒด ๋ชจ๋ ๊ตฌ์กฐยท์ค๊ณ ๊ฒฐ์ : docs/ARCHITECTURE.md
pnpm install
pnpm tauri dev
pnpm check # svelte-check (ํ์
)
pnpm test # vitest (ํ๋ก ํธ ๋ก์ง)
cd src-tauri && cargo test # Rust ๋จ์/ํตํฉ ํ
์คํธ๋ฌธ์: ์ํคํ ์ฒ ยท ์ํ ๋งคํ ยท ๊ฐ๋ฐ ๊ฐ์ด๋
- ์ฑ์ด ์คํ ์ค์ผ ๋๋ง ๊ฐฑ์ ๋๋ค(๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฐ๋ชฌ ์์).
- git
behind๋ ๋ง์ง๋ง fetch ์์ ๊ธฐ์ค โ ๋ก์ปฌ ์ ์ฉ์ด๋ผ ์๊ฒฉ์ ์ค์๊ฐ์ผ๋ก ๋ณด์ง ์๋๋ค. svn์ out-of-date(behind)๋ฅผ ํ์ํ์ง ์๋๋ค. cleanํ์ ์ stashยทworktree>1๋ ํฌํจ๋์ด, ์ปค๋ฐยทํธ์๊ฐ ๋๋ฌ์ด๋ stash๊ฐ ๋จ์์์ผ๋ฉด ์นด๋๊ฐ ๋นํด๋ฆฐ(๋ถ๊ฒ)์ผ๋ก ํ์๋๋ค.- ์ฑ ์์ด์ฝ์ ํ์ฌ ์์(ํ์ ํ๋ก์ ํธ ๋ณต์ ). ๋ฉ๋ด๋ฐ ํธ๋ ์ด/์๋ฆผ/์๋ fetch๋ ๋ฏธ๊ตฌํ(ํฅํ).
