Class: Ocak::WorktreeManager

Inherits:
Object
  • Object
show all
Defined in:
lib/ocak/worktree_manager.rb

Defined Under Namespace

Classes: Worktree, WorktreeError

Instance Method Summary collapse

Constructor Details

#initialize(config:, logger: nil) ⇒ WorktreeManager

Returns a new instance of WorktreeManager.



10
11
12
13
14
15
# File 'lib/ocak/worktree_manager.rb', line 10

def initialize(config:, logger: nil)
  @config = config
  @logger = logger
  @worktree_base = File.join(config.project_dir, config.worktree_dir)
  @mutex = Mutex.new
end

Instance Method Details

#clean_staleObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ocak/worktree_manager.rb', line 54

def clean_stale
  removed = []
  list.each do |wt|
    next unless wt[:path]&.include?(@worktree_base)

    begin
      git('worktree', 'remove', '--force', wt[:path])
      removed << wt[:path]
    rescue StandardError => e
      @logger&.warn("Failed to remove worktree #{wt[:path]}: #{e.message}")
      next # skip failed removal so one bad worktree doesn't abort cleanup of others
    end
  end
  prune
  removed
end

#create(issue_number, setup_command: nil) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ocak/worktree_manager.rb', line 17

def create(issue_number, setup_command: nil)
  @mutex.synchronize do
    raise ArgumentError, "Invalid issue number: #{issue_number}" unless issue_number.to_s.match?(/\A\d+\z/)

    FileUtils.mkdir_p(@worktree_base)

    branch = "auto/issue-#{issue_number}-#{SecureRandom.hex(4)}"
    path = File.join(@worktree_base, "issue-#{issue_number}")

    _, stderr, status = git('worktree', 'add', '-b', branch, path, 'main')
    raise WorktreeError, "Failed to create worktree: #{stderr}" unless status.success?

    if setup_command
      _, stderr, status = Open3.capture3(*Shellwords.shellsplit(setup_command), chdir: path)
      raise WorktreeError, "Setup command failed: #{stderr}" unless status.success?
    end

    Worktree.new(path: path, branch: branch, issue_number: issue_number)
  end
end

#listObject



43
44
45
46
47
48
# File 'lib/ocak/worktree_manager.rb', line 43

def list
  stdout, _, status = git('worktree', 'list', '--porcelain')
  return [] unless status.success?

  parse_worktree_list(stdout)
end

#pruneObject



50
51
52
# File 'lib/ocak/worktree_manager.rb', line 50

def prune
  git('worktree', 'prune')
end

#remove(worktree) ⇒ Object



38
39
40
41
# File 'lib/ocak/worktree_manager.rb', line 38

def remove(worktree)
  git('worktree', 'remove', '--force', worktree.path)
  git('worktree', 'prune')
end