Skip to content

Commit 4686675

Browse files
tarcinilperlun
authored andcommitted
Added boolean functions for git status (#348)
* adding boolean functions for git status * adding file to untracked?; adding tests for the reminder of the new functions * adding false test cases to new functions Signed-off-by: Vern Burton <me@vernburton.com> * fixing thread safety to pass travis for jruby * Use parentheses in method calls * More of the same * adding yard documents to the functions that I added and have knowledge about fixing rubocop - broke method to make line count while breaking up function into functional zone - fixed heredoc spacing - removed redundant self - rescue should not be used as a modifer, moved to begin/rescue
1 parent 47e3f07 commit 4686675

File tree

3 files changed

+205
-64
lines changed

3 files changed

+205
-64
lines changed

lib/git/status.rb

Lines changed: 139 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,130 @@
11
module Git
2-
2+
#
3+
# A class for git status
4+
#
35
class Status
46
include Enumerable
5-
7+
68
def initialize(base)
79
@base = base
810
construct_status
911
end
10-
12+
13+
#
14+
# Returns an Enumerable containing files that have changed from the
15+
# git base directory
16+
#
17+
# @return [Enumerable]
1118
def changed
12-
@files.select { |k, f| f.type == 'M' }
19+
@files.select { |_k, f| f.type == 'M' }
1320
end
14-
21+
22+
#
23+
# Determines whether the given file has been changed.
24+
# File path starts at git base directory
25+
#
26+
# @param file [String] The name of the file.
27+
# @example Check if lib/git.rb has changed.
28+
# changed?('lib/git.rb')
29+
# @return [Boolean]
30+
def changed?(file)
31+
changed.member?(file)
32+
end
33+
34+
#
35+
# Returns an Enumerable containing files that have been added.
36+
# File path starts at git base directory
37+
#
38+
# @return [Enumerable]
1539
def added
16-
@files.select { |k, f| f.type == 'A' }
40+
@files.select { |_k, f| f.type == 'A' }
1741
end
1842

43+
#
44+
# Determines whether the given file has been added to the repository
45+
# File path starts at git base directory
46+
#
47+
# @param file [String] The name of the file.
48+
# @example Check if lib/git.rb is added.
49+
# added?('lib/git.rb')
50+
# @return [Boolean]
51+
def added?(file)
52+
added.member?(file)
53+
end
54+
55+
#
56+
# Returns an Enumerable containing files that have been deleted.
57+
# File path starts at git base directory
58+
#
59+
# @return [Enumerable]
1960
def deleted
20-
@files.select { |k, f| f.type == 'D' }
61+
@files.select { |_k, f| f.type == 'D' }
2162
end
22-
63+
64+
#
65+
# Determines whether the given file has been deleted from the repository
66+
# File path starts at git base directory
67+
#
68+
# @param file [String] The name of the file.
69+
# @example Check if lib/git.rb is deleted.
70+
# deleted?('lib/git.rb')
71+
# @return [Boolean]
72+
def deleted?(file)
73+
deleted.member?(file)
74+
end
75+
76+
#
77+
# Returns an Enumerable containing files that are not tracked in git.
78+
# File path starts at git base directory
79+
#
80+
# @return [Enumerable]
2381
def untracked
24-
@files.select { |k, f| f.untracked }
82+
@files.select { |_k, f| f.untracked }
2583
end
26-
84+
85+
#
86+
# Determines whether the given file has is tracked by git.
87+
# File path starts at git base directory
88+
#
89+
# @param file [String] The name of the file.
90+
# @example Check if lib/git.rb is an untracked file.
91+
# untracked?('lib/git.rb')
92+
# @return [Boolean]
93+
def untracked?(file)
94+
untracked.member?(file)
95+
end
96+
2797
def pretty
2898
out = ''
29-
self.each do |file|
99+
each do |file|
30100
out << pretty_file(file)
31101
end
32102
out << "\n"
33103
out
34104
end
35105

36106
def pretty_file(file)
37-
<<FILE
38-
#{file.path}
39-
\tsha(r) #{file.sha_repo.to_s} #{file.mode_repo.to_s}
40-
\tsha(i) #{file.sha_index.to_s} #{file.mode_index.to_s}
41-
\ttype #{file.type.to_s}
42-
\tstage #{file.stage.to_s}
43-
\tuntrac #{file.untracked.to_s}
44-
FILE
45-
end
46-
107+
<<-FILE.strip_heredoc
108+
#{file.path}
109+
\tsha(r) #{file.sha_repo} #{file.mode_repo}
110+
\tsha(i) #{file.sha_index} #{file.mode_index}
111+
\ttype #{file.type}
112+
\tstage #{file.stage}
113+
\tuntrac #{file.untracked}
114+
FILE
115+
end
116+
47117
# enumerable method
48-
118+
49119
def [](file)
50120
@files[file]
51121
end
52-
122+
53123
def each(&block)
54124
@files.values.each(&block)
55125
end
56-
126+
127+
# subclass that does heavy lifting
57128
class StatusFile
58129
attr_accessor :path, :type, :stage, :untracked
59130
attr_accessor :mode_index, :mode_repo
@@ -70,48 +141,59 @@ def initialize(base, hash)
70141
@sha_repo = hash[:sha_repo]
71142
@untracked = hash[:untracked]
72143
end
73-
144+
74145
def blob(type = :index)
75146
if type == :repo
76147
@base.object(@sha_repo)
77148
else
78-
@base.object(@sha_index) rescue @base.object(@sha_repo)
149+
begin
150+
@base.object(@sha_index)
151+
rescue
152+
@base.object(@sha_repo)
153+
end
79154
end
80155
end
81-
82-
83156
end
84-
157+
85158
private
86-
87-
def construct_status
88-
@files = @base.lib.ls_files
89-
ignore = @base.lib.ignored_files
90-
91-
# find untracked in working dir
92-
Dir.chdir(@base.dir.path) do
93-
Dir.glob('**/*', File::FNM_DOTMATCH) do |file|
94-
next if @files[file] || File.directory?(file) || ignore.include?(file) || file =~ /^.git\/.+/
95-
96-
@files[file] = {:path => file, :untracked => true}
97-
end
98-
end
99-
100-
# find modified in tree
101-
@base.lib.diff_files.each do |path, data|
102-
@files[path] ? @files[path].merge!(data) : @files[path] = data
103-
end
104-
105-
# find added but not committed - new files
106-
@base.lib.diff_index('HEAD').each do |path, data|
107-
@files[path] ? @files[path].merge!(data) : @files[path] = data
108-
end
109-
110-
@files.each do |k, file_hash|
111-
@files[k] = StatusFile.new(@base, file_hash)
159+
160+
def construct_status
161+
@files = @base.lib.ls_files
162+
163+
fetch_untracked
164+
fetch_modified
165+
fetch_added
166+
167+
@files.each do |k, file_hash|
168+
@files[k] = StatusFile.new(@base, file_hash)
169+
end
170+
end
171+
172+
def fetch_untracked
173+
ignore = @base.lib.ignored_files
174+
175+
Dir.chdir(@base.dir.path) do
176+
Dir.glob('**/*', File::FNM_DOTMATCH) do |file|
177+
next if @files[file] || File.directory?(file) ||
178+
ignore.include?(file) || file =~ %r{^.git\/.+}
179+
180+
@files[file] = { path: file, untracked: true }
112181
end
113182
end
114-
183+
end
184+
185+
def fetch_modified
186+
# find modified in tree
187+
@base.lib.diff_files.each do |path, data|
188+
@files[path] ? @files[path].merge!(data) : @files[path] = data
189+
end
190+
end
191+
192+
def fetch_added
193+
# find added but not committed - new files
194+
@base.lib.diff_index('HEAD').each do |path, data|
195+
@files[path] ? @files[path].merge!(data) : @files[path] = data
196+
end
197+
end
115198
end
116-
117199
end

tests/units/test_status.rb

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,75 @@ def setup
1212
def test_dot_files_status
1313
in_temp_dir do |path|
1414
git = Git.clone(@wdir, 'test_dot_files_status')
15-
15+
1616
create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
1717
create_file('test_dot_files_status/.test_file_2', 'content test_file_2')
18-
18+
1919
git.add('test_file_1')
2020
git.add('.test_file_2')
21-
21+
2222
assert(git.status.added.assoc('test_file_1'))
2323
assert(git.status.added.assoc('.test_file_2'))
2424
end
2525
end
2626

27+
def test_added_boolean
28+
in_temp_dir do |path|
29+
git = Git.clone(@wdir, 'test_dot_files_status')
30+
31+
create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
32+
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')
33+
34+
git.add('test_file_1')
35+
36+
assert(git.status.added?('test_file_1'))
37+
assert(!git.status.added?('test_file_2'))
38+
end
39+
end
40+
41+
def test_changed_boolean
42+
in_temp_dir do |path|
43+
git = Git.clone(@wdir, 'test_dot_files_status')
44+
45+
create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
46+
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')
47+
48+
git.add('test_file_1')
49+
git.add('test_file_2')
50+
git.commit('message')
51+
update_file('test_dot_files_status/test_file_1', 'update_content tets_file_1')
52+
53+
assert(git.status.changed?('test_file_1'))
54+
assert(!git.status.changed?('test_file_2'))
55+
end
56+
end
57+
58+
def test_deleted_boolean
59+
in_temp_dir do |path|
60+
git = Git.clone(@wdir, 'test_dot_files_status')
61+
62+
create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
63+
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')
64+
65+
git.add('test_file_1')
66+
git.commit('message')
67+
delete_file('test_dot_files_status/test_file_1')
68+
69+
assert(git.status.deleted?('test_file_1'))
70+
assert(!git.status.deleted?('test_file_2'))
71+
end
72+
end
73+
74+
def test_untracked_boolean
75+
in_temp_dir do |path|
76+
git = Git.clone(@wdir, 'test_dot_files_status')
77+
78+
create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
79+
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')
80+
git.add('test_file_2')
81+
82+
assert(git.status.untracked?('test_file_1'))
83+
assert(!git.status.untracked?('test_file_2'))
84+
end
85+
end
2786
end

tests/units/test_thread_safty.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ def setup
1010
def test_git_init_bare
1111
dirs = []
1212
threads = []
13-
14-
5.times do
13+
14+
5.times do
1515
dirs << Dir.mktmpdir
1616
end
17-
17+
1818
dirs.each do |dir|
1919
threads << Thread.new do
2020
Git.init(dir, :bare => true)
2121
end
2222
end
2323

24-
threads.each {|thread| thread.join}
24+
threads.each(&:join)
2525

2626
dirs.each do |dir|
2727
Git.bare("#{dir}/.git").ls_files

0 commit comments

Comments
 (0)