Skip to content

Commit eee23c3

Browse files
Add worktree listing, add and remove
Signed-off-by: Ofir Petrushka <hatkyinc@gmail.com>
1 parent 4bef5ab commit eee23c3

File tree

16 files changed

+185
-4
lines changed

16 files changed

+185
-4
lines changed

lib/git.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
require 'git/stashes'
2222
require 'git/version'
2323
require 'git/working_directory'
24+
require 'git/worktree'
25+
require 'git/worktrees'
2426

2527
lib = Git::Lib.new(nil, nil)
2628
unless lib.meets_required_version?

lib/git/base/factory.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Git
33
class Base
44

55
module Factory
6-
6+
77
# returns a Git::Branch object for branch_name
88
def branch(branch_name = 'master')
99
Git::Branch.new(self, branch_name)
@@ -14,7 +14,18 @@ def branch(branch_name = 'master')
1414
def branches
1515
Git::Branches.new(self)
1616
end
17-
17+
18+
# returns a Git::Worktree object for dir, commitish
19+
def worktree(dir, commitish = nil)
20+
Git::Worktree.new(self, dir, commitish)
21+
end
22+
23+
# returns a Git::worktrees object of all the Git::Worktrees
24+
# objects for this repo
25+
def worktrees
26+
Git::Worktrees.new(self)
27+
end
28+
1829
def commit_tree(tree = nil, opts = {})
1930
Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
2031
end

lib/git/lib.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,35 @@ def branches_all
308308
arr
309309
end
310310

311+
def worktrees_all
312+
arr = []
313+
directory = ''
314+
# Output example for `worktree list --porcelain`:
315+
# worktree /code/public/ruby-git
316+
# HEAD 4bef5abbba073c77b4d0ccc1ffcd0ed7d48be5d4
317+
# branch refs/heads/master
318+
#
319+
# worktree /tmp/worktree-1
320+
# HEAD b8c63206f8d10f57892060375a86ae911fad356e
321+
# detached
322+
#
323+
command_lines('worktree',['list', '--porcelain']).each do |w|
324+
s = w.split("\s")
325+
directory = s[1] if s[0] == 'worktree'
326+
arr << [directory, s[1]] if s[0] == 'HEAD'
327+
end
328+
arr
329+
end
330+
331+
def worktree_add(dir, commitish = nil)
332+
return command('worktree', ['add', dir, commitish]) if !commitish.nil?
333+
command('worktree', ['add', dir])
334+
end
335+
336+
def worktree_remove(dir)
337+
command('worktree', ['remove', dir])
338+
end
339+
311340
def list_files(ref_dir)
312341
dir = File.join(@git_dir, 'refs', ref_dir)
313342
files = []

lib/git/worktree.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
require 'git/path'
2+
3+
module Git
4+
5+
class Worktree < Path
6+
7+
attr_accessor :full, :dir, :gcommit
8+
9+
def initialize(base, dir, gcommit = nil)
10+
@full = dir
11+
@full += ' ' + gcommit if !gcommit.nil?
12+
@base = base
13+
@dir = dir
14+
@gcommit = gcommit
15+
end
16+
17+
def gcommit
18+
@gcommit ||= @base.gcommit(@full)
19+
@gcommit
20+
end
21+
22+
def add
23+
@base.lib.worktree_add(@dir, @gcommit)
24+
end
25+
26+
def remove
27+
@base.lib.worktree_remove(@dir)
28+
end
29+
30+
def to_a
31+
[@full]
32+
end
33+
34+
def to_s
35+
@full
36+
end
37+
end
38+
end

lib/git/worktrees.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
module Git
2+
# object that holds all the available worktrees
3+
class Worktrees
4+
5+
include Enumerable
6+
7+
def initialize(base)
8+
@worktrees = {}
9+
10+
@base = base
11+
12+
# Array contains [dir, git_hash]
13+
@base.lib.worktrees_all.each do |w|
14+
@worktrees[w[0]] = Git::Worktree.new(@base, w[0], w[1])
15+
end
16+
end
17+
18+
# array like methods
19+
20+
def size
21+
@worktrees.size
22+
end
23+
24+
def each(&block)
25+
@worktrees.values.each(&block)
26+
end
27+
28+
def [](worktree_name)
29+
@worktrees.values.inject(@worktrees) do |worktrees, worktree|
30+
worktrees[worktree.full] ||= worktree
31+
worktrees
32+
end[worktree_name.to_s]
33+
end
34+
35+
def to_s
36+
out = ''
37+
@worktrees.each do |k, b|
38+
out << b.to_s << "\n"
39+
end
40+
out
41+
end
42+
end
43+
end

tests/files/working/dot_git/index

0 Bytes
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0000000000000000000000000000000000000000 5e53019b3238362144c2766f02a2c00d91fcc023 Scott Chacon <schacon@gmail.com> 1596189348 +1000 branch: Created from HEAD
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5e53019b3238362144c2766f02a2c00d91fcc023
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
935badc874edd62a8629aaf103418092c73f0a56
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5e53019b3238362144c2766f02a2c00d91fcc023

0 commit comments

Comments
 (0)