Class: Kettle::Dev::GitAdapter
- Inherits:
-
Object
- Object
- Kettle::Dev::GitAdapter
- Defined in:
- lib/kettle/dev/git_adapter.rb
Overview
Minimal Git adapter used by kettle-dev to avoid invoking live shell commands
directly from the higher-level library code. In tests, mock this adapter’s
methods to prevent any real network or repository mutations.
Behavior:
- Prefer the ‘git’ gem when available.
- If the ‘git’ gem is not present (LoadError), fall back to shelling out to
the systemgit
executable for the small set of operations we need.
Public API is intentionally small and only includes what we need right now.
Instance Method Summary collapse
-
#capture(args) ⇒ Array<(String, Boolean)>
Execute a git command and capture its stdout and success flag.
-
#checkout(branch) ⇒ Boolean
Checkout the given branch.
-
#current_branch ⇒ String?
Current branch name, or nil on error.
-
#fetch(remote, ref = nil) ⇒ Boolean
Fetch a ref from a remote (or everything if ref is nil).
-
#initialize ⇒ void
constructor
Create a new adapter rooted at the current working directory.
-
#pull(remote, branch) ⇒ Boolean
Pull from a remote/branch.
-
#push(remote, branch, force: false) ⇒ Boolean
Push a branch to a remote.
-
#remote_url(name) ⇒ String?
-
#remotes ⇒ Array<String>
List of remote names.
-
#remotes_with_urls ⇒ Hash{String=>String}
Remote name => fetch URL.
Constructor Details
#initialize ⇒ void
Create a new adapter rooted at the current working directory.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/kettle/dev/git_adapter.rb', line 33 def initialize begin # Allow users/CI to opt out of using the 'git' gem even when available. # Set KETTLE_DEV_DISABLE_GIT_GEM to a truthy value ("1", "true", "yes") to force CLI backend. env_val = ENV["KETTLE_DEV_DISABLE_GIT_GEM"] # Ruby 2.3 compatibility: String#match? was added in 2.4; use Regexp#=== / =~ instead disable_gem = env_val && !!(/\A(1|true|yes)\z/i =~ env_val) if disable_gem @backend = :cli else Kernel.require "git" @backend = :gem @git = ::Git.open(Dir.pwd) end rescue LoadError # Optional dependency: fall back to CLI @backend = :cli rescue StandardError => e raise Kettle::Dev::Error, "Failed to open git repository: #{e.}" end end |
Instance Method Details
#capture(args) ⇒ Array<(String, Boolean)>
Execute a git command and capture its stdout and success flag.
This is a generic escape hatch used by higher-level code for read-only
queries that aren’t covered by the explicit adapter API. Tests can stub
this method to avoid shelling out.
24 25 26 27 28 29 |
# File 'lib/kettle/dev/git_adapter.rb', line 24 def capture(args) out, status = Open3.capture2("git", *args) [out.strip, status.success?] rescue StandardError ["", false] end |
#checkout(branch) ⇒ Boolean
Checkout the given branch
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/kettle/dev/git_adapter.rb', line 150 def checkout(branch) if @backend == :gem @git.checkout(branch) true else system("git", "checkout", branch.to_s) end rescue StandardError false end |
#current_branch ⇒ String?
Returns current branch name, or nil on error.
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/kettle/dev/git_adapter.rb', line 84 def current_branch if @backend == :gem @git.current_branch else out, status = Open3.capture2("git", "rev-parse", "--abbrev-ref", "HEAD") status.success? ? out.strip : nil end rescue StandardError nil end |
#fetch(remote, ref = nil) ⇒ Boolean
Fetch a ref from a remote (or everything if ref is nil)
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/kettle/dev/git_adapter.rb', line 180 def fetch(remote, ref = nil) if @backend == :gem if ref @git.fetch(remote, ref) else @git.fetch(remote) end true elsif ref system("git", "fetch", remote.to_s, ref.to_s) else system("git", "fetch", remote.to_s) end rescue StandardError false end |
#pull(remote, branch) ⇒ Boolean
Pull from a remote/branch
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/kettle/dev/git_adapter.rb', line 165 def pull(remote, branch) if @backend == :gem @git.pull(remote, branch) true else system("git", "pull", remote.to_s, branch.to_s) end rescue StandardError false end |
#push(remote, branch, force: false) ⇒ Boolean
Push a branch to a remote.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/kettle/dev/git_adapter.rb', line 60 def push(remote, branch, force: false) if @backend == :gem begin if remote @git.push(remote, branch, force: force) else # Default remote according to repo config @git.push(nil, branch, force: force) end true rescue StandardError false end else args = ["git", "push"] args << "--force" if force if remote args << remote.to_s << branch.to_s end system(*args) end end |
#remote_url(name) ⇒ String?
135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/kettle/dev/git_adapter.rb', line 135 def remote_url(name) if @backend == :gem r = @git.remotes.find { |x| x.name == name } r&.url else out, status = Open3.capture2("git", "config", "--get", "remote.#{name}.url") status.success? ? out.strip : nil end rescue StandardError nil end |
#remotes ⇒ Array<String>
Returns list of remote names.
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/kettle/dev/git_adapter.rb', line 96 def remotes if @backend == :gem @git.remotes.map(&:name) else out, status = Open3.capture2("git", "remote") status.success? ? out.split(/\r?\n/).map(&:strip).reject(&:empty?) : [] end rescue StandardError [] end |
#remotes_with_urls ⇒ Hash{String=>String}
Returns remote name => fetch URL.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/kettle/dev/git_adapter.rb', line 108 def remotes_with_urls if @backend == :gem @git.remotes.each_with_object({}) do |r, h| begin h[r.name] = r.url rescue StandardError # ignore end end else out, status = Open3.capture2("git", "remote", "-v") return {} unless status.success? urls = {} out.each_line do |line| # Example: origin https://github.com/me/repo.git (fetch) if line =~ /^(\S+)\s+(\S+)\s+\(fetch\)/ urls[Regexp.last_match(1)] = Regexp.last_match(2) end end urls end rescue StandardError {} end |