Class: RepoTender::SCM::Client
- Inherits:
-
Object
- Object
- RepoTender::SCM::Client
- Defined in:
- lib/repo_tender/scm/client.rb
Overview
Abstract SCM interface. The git CLI is the only implementation for now (per AGENTS.md / PRD §1), but the sync engine + tests must code to this interface so a future SCM is a drop-in.
Every method returns a Dry::Monads::Result. Programmer error (e.g. nil path) is a raise; expected failures (no .git, non-fast- forward, network down) are Failure.
Direct Known Subclasses
Instance Method Summary collapse
-
#clone(url, path) ⇒ Object
‘git clone <url> <path>`.
-
#current_branch(path) ⇒ Object
Returns the current branch name, or nil if HEAD is detached.
-
#default_branch(path) ⇒ Object
Returns the bare remote’s HEAD (e.g. “main” or “trunk”).
-
#fast_forward(path, default_branch) ⇒ Object
‘git merge –ff-only origin/<default>`.
-
#fetch(path) ⇒ Object
‘git fetch –prune –no-tags origin`.
-
#last_fetch_at(path) ⇒ Object
Returns the mtime of .git/FETCH_HEAD, or nil if absent.
-
#status(path) ⇒ Object
Parse the working-tree status of a repo on disk.
-
#switch(path, branch) ⇒ Object
‘git switch <branch>`.
-
#sync_empty(path) ⇒ Object
Sync an unborn (empty) local clone.
Instance Method Details
#clone(url, path) ⇒ Object
‘git clone <url> <path>`.
58 59 60 |
# File 'lib/repo_tender/scm/client.rb', line 58 def clone(url, path) raise NotImplementedError end |
#current_branch(path) ⇒ Object
Returns the current branch name, or nil if HEAD is detached.
25 26 27 |
# File 'lib/repo_tender/scm/client.rb', line 25 def current_branch(path) raise NotImplementedError end |
#default_branch(path) ⇒ Object
Returns the bare remote’s HEAD (e.g. “main” or “trunk”). Must work even when the default branch is not “main”. May do a one-shot network call (‘git remote set-head origin -a`) to refresh a stale `origin/HEAD`.
33 34 35 |
# File 'lib/repo_tender/scm/client.rb', line 33 def default_branch(path) raise NotImplementedError end |
#fast_forward(path, default_branch) ⇒ Object
‘git merge –ff-only origin/<default>`. Returns Failure if the local branch has diverged (left count > 0) — never resets. On Success: returns Integer commit count pulled.
0 → already up to date (no merge performed)
N → fast-forwarded N commits
53 54 55 |
# File 'lib/repo_tender/scm/client.rb', line 53 def fast_forward(path, default_branch) raise NotImplementedError end |
#fetch(path) ⇒ Object
‘git fetch –prune –no-tags origin`.
44 45 46 |
# File 'lib/repo_tender/scm/client.rb', line 44 def fetch(path) raise NotImplementedError end |
#last_fetch_at(path) ⇒ Object
Returns the mtime of .git/FETCH_HEAD, or nil if absent. Treated as a freshness hint (PRD §3.3 step 4 + gate G5).
39 40 41 |
# File 'lib/repo_tender/scm/client.rb', line 39 def last_fetch_at(path) raise NotImplementedError end |
#status(path) ⇒ Object
Parse the working-tree status of a repo on disk. Implementation must read porcelain v2 (per AGENTS.md gotcha) and report a ‘SCM::Status` value object.
20 21 22 |
# File 'lib/repo_tender/scm/client.rb', line 20 def status(path) raise NotImplementedError end |
#switch(path, branch) ⇒ Object
‘git switch <branch>`. Switches the local repo to the given branch. By default `git switch` refuses to clobber a dirty working tree (the operation is aborted on local-change loss per `man git-switch`); the engine treats that as a Failure. The engine is responsible for the upstream dirty-tree guard (per Slice 2 gate G5 / PHASE-0 ruling): the plan returns `:report_wrong_branch` / `:report_detached` for a dirty tree, so this method is only called on clean trees.
70 71 72 |
# File 'lib/repo_tender/scm/client.rb', line 70 def switch(path, branch) raise NotImplementedError end |
#sync_empty(path) ⇒ Object
Sync an unborn (empty) local clone. Called when the repo has no commits (‘status.unborn? == true`) and the working tree is clean. Returns Success(:empty) when the remote has no branches (valid empty clone; no mutation). Returns Success(:fast_forwarded) when the remote has gained commits and the local clone was advanced to them. Returns Failure on a real network/probe error (the empty-vs-error distinction is made via `git ls-remote –heads origin`: exit 0 = definitive answer; non-zero = real error).
82 83 84 |
# File 'lib/repo_tender/scm/client.rb', line 82 def sync_empty(path) raise NotImplementedError end |