Class: FluidCLI::Git
- Inherits:
-
Object
- Object
- FluidCLI::Git
- Defined in:
- lib/fluid_cli/git.rb
Overview
FluidCLI::Git wraps git functionality to make it easier to integrate with git.
Class Method Summary collapse
-
.available?(ctx) ⇒ Boolean
Check if the current working directory is a Git repository.
-
.branches(ctx) ⇒ Object
will fetch the repos list of branches.
-
.clone(repo_with_branch, dest, ctx: Context.new) ⇒ Object
calls git to clone a new repo into a supplied destination, it will also output progress of the cloning process into a new progress bar.
-
.clone_progress(stderr, bar: nil) ⇒ Object
handles showing the progress of the git clone command.
-
.exists?(ctx) ⇒ Boolean
Check if Git exists in the environment.
-
.git_clone_command(repo, dest, branch) ⇒ Object
returns array with components of git clone command.
-
.init(ctx) ⇒ Object
will initialize a new repo in the current directory.
-
.merge_file(current_file, base_file, other_file, opts = [], ctx: Context.new) ⇒ Object
Run git three-way file merge (it doesn't require an initialized git repository).
-
.raw_clone(repo_with_branch, dest, ctx: Context.new) ⇒ Object
calls git to clone a new repo into a supplied destination, it will also call a supplied block with the percentage of clone completion.
-
.sha(dir: Dir.pwd, ctx: Context.new) ⇒ Object
will return the current sha of the cli repo.
- .sparse_checkout(repo, set, branch, ctx) ⇒ Object
Class Method Details
.available?(ctx) ⇒ Boolean
Check if the current working directory is a Git repository
15 16 17 18 19 20 |
# File 'lib/fluid_cli/git.rb', line 15 def available?(ctx) _output, status = ctx.capture2e("git", "status") status.success? rescue Errno::ENOENT # git is not installed false end |
.branches(ctx) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/fluid_cli/git.rb', line 174 def branches(ctx) output, status = ctx.capture2e("git", "branch", "--list", "--format=%(refname:short)") ctx.abort(ctx.("core.git.error.no_branches_found")) unless status.success? branches = if output == "" ["master"] else output.split("\n") end branches end |
.clone(repo_with_branch, dest, ctx: Context.new) ⇒ Object
calls git to clone a new repo into a supplied destination, it will also output progress of the cloning process into a new progress bar
Parameters
repo_with_branch- a git url for git to clone the repo fromdest- a filepath to where the repo should be cloned toctx- the current running context of your command, defaults to a new context.
Returns
sha_string- string of the sha of the most recent commit to the repo
Example
FluidCLI::Git.clone('[email protected]:fluid-commerce/test.git', 'test-app')
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/fluid_cli/git.rb', line 130 def clone(repo_with_branch, dest, ctx: Context.new) if Dir.exist?(dest) && !Dir.empty?(dest) ctx.abort("Directory #{dest} already exists and is not empty.") else msg = [] # require at usage point to not slow down CLI startup # https://github.com/Shopify/shopify-cli/pull/698#discussion_r444342445 require "open3" repo, branch = repo_with_branch.split("#") git_cmd = git_clone_command(repo, dest, branch) = "{{success:Cloned repository into #{dest}}}" CLI::UI::Frame.open("Cloning #{repo} into #{dest}", success_text: ) do CLI::UI::Progress.progress do || success = Open3.popen3("git", *git_cmd, "--progress") do |_stdin, _stdout, stderr, thread| msg = clone_progress(stderr, bar: ) thread.value end.success? ctx.abort((msg.join("\n"))) unless success .tick(set_percent: 1.0) end end end end |
.clone_progress(stderr, bar: nil) ⇒ Object
handles showing the progress of the git clone command. if block given, assumes passing percent to block, otherwise increments bar for progress bar
Parameters
stderr- Open3.popen3 output streambar- progress bar object to set percent
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/fluid_cli/git.rb', line 287 def clone_progress(stderr, bar: nil) msg = [] while (line = stderr.gets) msg << line.chomp next unless line.strip.start_with?("Receiving objects:") percent = (line.match(/Receiving objects:\s+(\d+)/)[1].to_f / 100).round(2) if block_given? yield percent elsif !.nil? .tick(set_percent: percent) end end msg end |
.exists?(ctx) ⇒ Boolean
Check if Git exists in the environment
7 8 9 10 11 12 |
# File 'lib/fluid_cli/git.rb', line 7 def exists?(ctx) _output, status = ctx.capture2e("git", "version") status.success? rescue Errno::ENOENT # git is not installed false end |
.git_clone_command(repo, dest, branch) ⇒ Object
returns array with components of git clone command
Parameters
repo- repo url without branch namedest- a filepath to where the repo should be cloned tobranch- branch name when cloning
Returns
- array of strings
Example
["clone", "--single-branch", "--branch", "test-branch", "test-app"]
64 65 66 67 68 69 70 |
# File 'lib/fluid_cli/git.rb', line 64 def git_clone_command(repo, dest, branch) if branch ["clone", "--single-branch", "--branch", branch, repo, dest] else ["clone", "--single-branch", repo, dest] end end |
.init(ctx) ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/fluid_cli/git.rb', line 235 def init(ctx) output, status = ctx.capture2e("git", "status") unless status.success? ctx.abort(ctx.("core.git.error.repo_not_initiated")) end if output.include?("No commits yet") ctx.abort(ctx.("core.git.error.no_commits_made")) end end |
.merge_file(current_file, base_file, other_file, opts = [], ctx: Context.new) ⇒ Object
Run git three-way file merge (it doesn't require an initialized git repository)
Parameters
- `current_file - string path of the current file
base_file- string path of the base fileother_file- string path of the other fileopts- list of "git merge-file" options. Valid values: - "-q" - do not warn about conflicts - "--diff3" - show conflicts - "--ours" - resolve conflicts favoring lines fromcurrent_file- "--theirs" - resolve conflicts favoring lines fromother_file- "--union" - resolve conflicts favoring lines from both files - "-p" - send results to standard output instead of overwriting thecurrent_filectx- the current running context of your command, defaults to a new context
Returns
- standard output from git
Example
output = FluidCLI::Git.merge_file(current_file, base_file, other_file, opts, ctx: ctx)
213 214 215 216 217 218 219 220 221 |
# File 'lib/fluid_cli/git.rb', line 213 def merge_file(current_file, base_file, other_file, opts = [], ctx: Context.new) output, status = ctx.capture2e("git", "merge-file", current_file, base_file, other_file, *opts) unless status.success? ctx.abort(ctx.("core.git.error.merge_failed")) end output end |
.raw_clone(repo_with_branch, dest, ctx: Context.new) ⇒ Object
calls git to clone a new repo into a supplied destination, it will also call a supplied block with the percentage of clone completion
Parameters
repo_with_branch- a git url for git to clone the repo fromdest- a filepath to where the repo should be cloned toctx- the current running context of your command, defaults to a new context.
Returns
sha_string- string of the sha of the most recent commit to the repo
Example
FluidCLI::Git.raw_clone('[email protected]:fluid-commerce/test.git', 'test-app')
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/fluid_cli/git.rb', line 90 def raw_clone(repo_with_branch, dest, ctx: Context.new) if Dir.exist?(dest) && !Dir.empty?(dest) ctx.abort(ctx.("core.git.error.directory_exists")) else msg = [] # require at usage point to not slow down CLI startup # https://github.com/Shopify/shopify-cli/pull/698#discussion_r444342445 require "open3" repo, branch = repo_with_branch.split("#") git_cmd = git_clone_command(repo, dest, branch) success = Open3.popen3("git", *git_cmd, "--progress") do |_stdin, _stdout, stderr, thread| msg = clone_progress(stderr, bar: nil) thread.value end.success? ctx.abort((msg.join("\n"))) unless success end end |
.sha(dir: Dir.pwd, ctx: Context.new) ⇒ Object
will return the current sha of the cli repo
Parameters
dir- the directory of the git repo. This defaults to the cli repoctx- the current running context of your command
Returns
sha_string- string of the sha of the most recent commit to the repo
Example
FluidCLI::Git.sha
Some environments don't have git in PATH and this prevents the execution from raising an error https://app.bugsnag.com/shopify/shopify-cli/errors/615dd36365ce57000889d4c5
41 42 43 44 45 |
# File 'lib/fluid_cli/git.rb', line 41 def sha(dir: Dir.pwd, ctx: Context.new) if available?(ctx) rev_parse("HEAD", dir: dir, ctx: ctx) end end |
.sparse_checkout(repo, set, branch, ctx) ⇒ Object
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/fluid_cli/git.rb', line 247 def sparse_checkout(repo, set, branch, ctx) _, status = ctx.capture2e("git init") unless status.success? ctx.abort(ctx.("core.git.error.repo_not_initiated")) end _, status = ctx.capture2e("git remote add -f origin #{repo}") unless status.success? ctx.abort(ctx.("core.git.error.remote_not_added")) end _, status = ctx.capture2e("git config core.sparsecheckout true") unless status.success? ctx.abort(ctx.("core.git.error.sparse_checkout_not_enabled")) end _, status = ctx.capture2e("git sparse-checkout set #{set}") unless status.success? ctx.abort(ctx.("core.git.error.sparse_checkout_not_set")) end resp, status = ctx.capture2e("git pull origin #{branch}") unless status.success? if resp.include?("fatal: couldn't find remote ref") ctx.abort(ctx.("core.git.error.pull_failed_bad_branch", branch)) end ctx.abort(ctx.("core.git.error.pull_failed")) end end |