Class: Ace::Git::Molecules::BranchReader

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/git/molecules/branch_reader.rb

Overview

Reads git branch information Consolidated from ace-review GitBranchReader (adapted to use CommandExecutor)

Class Method Summary collapse

Class Method Details

.current_branch(executor: Atoms::CommandExecutor) ⇒ String|nil

Get current git branch name or commit SHA if detached

Parameters:

  • executor (Module) (defaults to: Atoms::CommandExecutor)

    Command executor

Returns:

  • (String|nil)

    branch name, commit SHA (if detached), or nil if not in git repo



13
14
15
# File 'lib/ace/git/molecules/branch_reader.rb', line 13

def current_branch(executor: Atoms::CommandExecutor)
  executor.current_branch
end

.detached?(executor: Atoms::CommandExecutor) ⇒ Boolean

Check if HEAD is detached

Parameters:

  • executor (Module) (defaults to: Atoms::CommandExecutor)

    Command executor

Returns:

  • (Boolean)

    true if HEAD is detached



20
21
22
23
24
25
# File 'lib/ace/git/molecules/branch_reader.rb', line 20

def detached?(executor: Atoms::CommandExecutor)
  result = executor.execute("git", "rev-parse", "--abbrev-ref", "HEAD")
  return false unless result[:success]

  result[:output].strip == "HEAD"
end

.format_status(ahead, behind) ⇒ String

Format tracking status as human-readable string

Parameters:

  • ahead (Integer)

    Commits ahead of remote

  • behind (Integer)

    Commits behind remote

Returns:

  • (String)

    Status description



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ace/git/molecules/branch_reader.rb', line 77

def format_status(ahead, behind)
  if ahead == 0 && behind == 0
    "up to date"
  elsif ahead > 0 && behind > 0
    "#{ahead} ahead, #{behind} behind"
  elsif ahead > 0
    "#{ahead} ahead"
  else
    "#{behind} behind"
  end
end

.full_info(executor: Atoms::CommandExecutor) ⇒ Hash

Get full branch information

Parameters:

  • executor (Module) (defaults to: Atoms::CommandExecutor)

    Command executor

Returns:

  • (Hash)

    Branch information



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/ace/git/molecules/branch_reader.rb', line 54

def full_info(executor: Atoms::CommandExecutor)
  branch = current_branch(executor: executor)

  return {error: "Not in git repository or no branch"} if branch.nil?

  tracking = tracking_branch(executor: executor)
  status = tracking_status(executor: executor)

  {
    name: branch,
    detached: detached?(executor: executor),
    tracking: tracking,
    ahead: status[:ahead],
    behind: status[:behind],
    up_to_date: status[:ahead] == 0 && status[:behind] == 0,
    status_description: format_status(status[:ahead], status[:behind])
  }
end

.tracking_branch(executor: Atoms::CommandExecutor) ⇒ String|nil

Get remote tracking branch

Parameters:

  • executor (Module) (defaults to: Atoms::CommandExecutor)

    Command executor

Returns:

  • (String|nil)

    tracking branch name or nil



30
31
32
# File 'lib/ace/git/molecules/branch_reader.rb', line 30

def tracking_branch(executor: Atoms::CommandExecutor)
  executor.tracking_branch
end

.tracking_status(executor: Atoms::CommandExecutor) ⇒ Hash

Get remote tracking status (ahead/behind counts)

Parameters:

  • executor (Module) (defaults to: Atoms::CommandExecutor)

    Command executor

Returns:

  • (Hash)

    { ahead: Integer, behind: Integer }



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ace/git/molecules/branch_reader.rb', line 37

def tracking_status(executor: Atoms::CommandExecutor)
  result = executor.execute("git", "rev-list", "--left-right", "--count", "@{upstream}...HEAD")

  unless result[:success]
    return {ahead: 0, behind: 0, error: "No tracking branch or not in git repo"}
  end

  parts = result[:output].strip.split(/\s+/)
  {
    ahead: parts[1].to_i,
    behind: parts[0].to_i
  }
end