Class: Cimas::WorkingCopy
- Inherits:
-
Object
- Object
- Cimas::WorkingCopy
- Defined in:
- lib/cimas/working_copy.rb
Overview
Deep module over one repository's working copy: every git-gem call, exception rescue, and porcelain/CLI parsing the orchestrator needs lives behind ~10 domain verbs. Subcommands then read as wave prose instead of git incantations.
Class Method Summary collapse
Instance Method Summary collapse
-
#clean? ⇒ Boolean
True when nothing is staged or modified — push skips the commit in this case.
- #commit(message) ⇒ Object
- #commit_all(message) ⇒ Object
- #diff_patch ⇒ Object
-
#drift? ⇒ Boolean
True when the working copy has any uncommitted change.
- #each_staged_change ⇒ Object
-
#fetch_reset_pull(branch) ⇒ Object
pull's dance: fetch origin, best-effort reset (a fresh clone may not hold the branch ref yet), checkout, pull.
- #head_sha ⇒ Object
-
#initialize(git) ⇒ WorkingCopy
constructor
A new instance of WorkingCopy.
-
#push(branch, force: false, remote: nil) ⇒ Object
Returns :pushed, :behind_remote (non-force push behind the remote tip), or [:rejected, error].
- #remote_name ⇒ Object
- #remove(*paths) ⇒ Object
-
#reset_clean(branch, include_untracked: false) ⇒ Object
checkout + reset_hard + clean: the "start from a pristine branch" preamble of sync and cleanup-orphan-files.
-
#reset_onto(base, discard_branch: nil) ⇒ Object
push's keep_changes=false preamble: stand on the base branch, soft-reset onto it, and discard an existing branch of the given name so it can be provisioned fresh.
- #stage(*paths) ⇒ Object
-
#switch_branch(name, fresh: false) ⇒ Object
Switch to a branch; :fresh discards an existing branch of the same name first (cleanup-orphan-files' shape).
Constructor Details
#initialize(git) ⇒ WorkingCopy
Returns a new instance of WorkingCopy.
18 19 20 |
# File 'lib/cimas/working_copy.rb', line 18 def initialize(git) @git = git end |
Class Method Details
.clone(remote, name, path:) ⇒ Object
14 15 16 |
# File 'lib/cimas/working_copy.rb', line 14 def self.clone(remote, name, path:) Git.clone(remote, name, path: path) end |
.open(dir) ⇒ Object
10 11 12 |
# File 'lib/cimas/working_copy.rb', line 10 def self.open(dir) new(Git.open(dir)) end |
Instance Method Details
#clean? ⇒ Boolean
True when nothing is staged or modified — push skips the commit in this case.
56 57 58 59 |
# File 'lib/cimas/working_copy.rb', line 56 def clean? status = @git.status status.changed.empty? && status.added.empty? && status.deleted.empty? end |
#commit(message) ⇒ Object
65 66 67 |
# File 'lib/cimas/working_copy.rb', line 65 def commit() @git.commit() end |
#commit_all(message) ⇒ Object
61 62 63 |
# File 'lib/cimas/working_copy.rb', line 61 def commit_all() @git.commit_all() end |
#diff_patch ⇒ Object
116 117 118 |
# File 'lib/cimas/working_copy.rb', line 116 def diff_patch @git.diff.patch end |
#drift? ⇒ Boolean
True when the working copy has any uncommitted change.
31 32 33 34 35 36 |
# File 'lib/cimas/working_copy.rb', line 31 def drift? out, = Open3.capture3("git", "-C", dir, "status", "--porcelain") !out.strip.empty? rescue StandardError false end |
#each_staged_change ⇒ Object
120 121 122 123 124 |
# File 'lib/cimas/working_copy.rb', line 120 def each_staged_change @git.status.changed.each do |file, status| yield(file, status.blob(:index).contents) end end |
#fetch_reset_pull(branch) ⇒ Object
pull's dance: fetch origin, best-effort reset (a fresh clone may not hold the branch ref yet), checkout, pull.
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/cimas/working_copy.rb', line 87 def fetch_reset_pull(branch) @git.remote("origin").fetch begin @git.reset_hard(branch) rescue Git::Error # reset can fail when the branch ref is absent on a fresh # clone; checkout/pull below still applies. nil end checkout(branch) @git.pull("origin", branch) end |
#head_sha ⇒ Object
22 23 24 |
# File 'lib/cimas/working_copy.rb', line 22 def head_sha @git.object("HEAD").sha end |
#push(branch, force: false, remote: nil) ⇒ Object
Returns :pushed, :behind_remote (non-force push behind the remote tip), or [:rejected, error]. The caller decides presentation. "Updates were rejected" covers both the classic git phrasing ("tip of your current branch is behind") and the modern one ("the remote contains work that you do not have locally").
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/cimas/working_copy.rb', line 105 def push(branch, force: false, remote: nil) @git.push(remote || remote_name, branch, force: force) :pushed rescue Git::GitExecuteError, Git::FailedError => e if e..match?(/Updates were rejected/) :behind_remote else [:rejected, e] end end |
#remote_name ⇒ Object
26 27 28 |
# File 'lib/cimas/working_copy.rb', line 26 def remote_name @git.remotes.first.to_s end |
#remove(*paths) ⇒ Object
50 51 52 |
# File 'lib/cimas/working_copy.rb', line 50 def remove(*paths) paths.each { |path| @git.remove(path) } end |
#reset_clean(branch, include_untracked: false) ⇒ Object
checkout + reset_hard + clean: the "start from a pristine branch" preamble of sync and cleanup-orphan-files.
40 41 42 43 44 |
# File 'lib/cimas/working_copy.rb', line 40 def reset_clean(branch, include_untracked: false) checkout(branch) @git.reset_hard(branch) @git.clean(force: true, d: include_untracked) end |
#reset_onto(base, discard_branch: nil) ⇒ Object
push's keep_changes=false preamble: stand on the base branch, soft-reset onto it, and discard an existing branch of the given name so it can be provisioned fresh.
72 73 74 75 76 |
# File 'lib/cimas/working_copy.rb', line 72 def reset_onto(base, discard_branch: nil) checkout(base) @git.reset(base) @git.branch(discard_branch).delete if discard_branch && @git.is_branch?(discard_branch) end |
#stage(*paths) ⇒ Object
46 47 48 |
# File 'lib/cimas/working_copy.rb', line 46 def stage(*paths) paths.each { |path| @git.add(path) } end |
#switch_branch(name, fresh: false) ⇒ Object
Switch to a branch; :fresh discards an existing branch of the same name first (cleanup-orphan-files' shape).
80 81 82 83 |
# File 'lib/cimas/working_copy.rb', line 80 def switch_branch(name, fresh: false) @git.branch(name).delete if fresh && @git.is_branch?(name) @git.branch(name).checkout end |