Module: Rakit::Git

Defined in:
lib/rakit/git.rb

Constant Summary collapse

NON_INTERACTIVE_CREDENTIAL_ENV =
{
  "GIT_TERMINAL_PROMPT" => "0",
  "GCM_INTERACTIVE" => "never",
  "GIT_ASKPASS" => "echo",
}.freeze

Class Method Summary collapse

Class Method Details

.clear_cached_credentials(dir = nil) ⇒ Object

Clears cached credentials for the active HTTPS remote scope. Returns a Hash with:

  • :status => “success” | “no-op” | “partial/failure”

  • :reason => nil or canonical reason



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rakit/git.rb', line 70

def self.clear_cached_credentials(dir = nil)
  target = git_repo!(dir)
  scope = active_remote_scope(target)
  return {status: "no-op", reason: "no_active_https_remote"} unless scope

  before = has_cached_credentials?(target)
  return {status: "no-op", reason: "no_cached_credentials"} unless before

  payload = credential_payload(scope)
  _out, err, status = Open3.capture3(NON_INTERACTIVE_CREDENTIAL_ENV, "git", "credential", "reject", stdin_data: payload, chdir: target)
  return {status: "partial/failure", reason: "helper_failed", details: err.to_s.strip} unless status.success?

  has_after = has_cached_credentials?(target)
  return {status: "success", reason: nil} unless has_after

  {status: "partial/failure", reason: "helper_partial"}
end

.has_cached_credentials?(dir = nil) ⇒ Boolean

Returns true when cached credentials are detectable for the active HTTPS remote scope. Returns false for missing/non-HTTPS remotes or when no cached credentials exist.

Returns:

  • (Boolean)


57
58
59
60
61
62
63
64
# File 'lib/rakit/git.rb', line 57

def self.has_cached_credentials?(dir = nil)
  target = git_repo!(dir)
  scope = active_remote_scope(target)
  return false unless scope

  credential = credential_fill(target, scope)
  credential_key?(credential)
end

.integrate(commit_message = nil, dir = nil) ⇒ Object

Stage all changes and commit. commit_message defaults to “Integrate” when nil. If there is nothing to commit after staging, skips commit (no error). Raises if not a git repo or if add fails.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rakit/git.rb', line 37

def self.integrate(commit_message = nil, dir = nil)
  require_relative "shell"
  target = dir ? ::File.expand_path(dir) : Dir.pwd
  raise "Not a git repository: #{target}" unless ::File.directory?(::File.join(target, ".git"))

  message = commit_message || "Integrate"
  Dir.chdir(target) do
    result = Rakit::Shell.run("git add -A")
    raise "git add failed" unless result.exit_status == 0
    # Only commit if there are staged changes (--cached --quiet exits 1 when there are)
    check = Rakit::Shell::CommandService.execute(Rakit::Shell::Command.new(name: "git", args: ["diff", "--cached", "--quiet"], working_directory: ""))
    unless check.exit_status == 0
      result = Rakit::Shell.run("git commit -m #{message.inspect}")
      raise "git commit failed" unless result.exit_status == 0
    end
  end
end

.sync(dir = nil) ⇒ Object

Sync the current directory with the remote (git pull, then git push). Runs from Dir.pwd. Raises if not a git repo or if pull/push fails. If the current branch has no remote tracking branch, pull and push are skipped (no error).



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rakit/git.rb', line 16

def self.sync(dir = nil)
  require_relative "shell"
  target = dir ? ::File.expand_path(dir) : Dir.pwd
  raise "Not a git repository: #{target}" unless ::File.directory?(::File.join(target, ".git"))

  Dir.chdir(target) do
    check = Rakit::Shell.run("git rev-parse --abbrev-ref @{u}")
    if check.exit_status != 0
      # No upstream configured for current branch; skip sync
      return
    end
    result = Rakit::Shell.run("git pull")
    raise "git pull failed" unless result.exit_status == 0
    result = Rakit::Shell.run("git push")
    raise "git push failed" unless result.exit_status == 0
  end
end