Class: RepoTender::SCM::Client

Inherits:
Object
  • Object
show all
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

Git

Instance Method Summary collapse

Instance Method Details

#clone(url, path) ⇒ Object

‘git clone <url> <path>`.

Raises:

  • (NotImplementedError)


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.

Raises:

  • (NotImplementedError)


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`.

Raises:

  • (NotImplementedError)


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

Raises:

  • (NotImplementedError)


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`.

Raises:

  • (NotImplementedError)


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).

Raises:

  • (NotImplementedError)


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.

Raises:

  • (NotImplementedError)


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.

Raises:

  • (NotImplementedError)


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).

Raises:

  • (NotImplementedError)


82
83
84
# File 'lib/repo_tender/scm/client.rb', line 82

def sync_empty(path)
  raise NotImplementedError
end