Skip to content

adding boolean functions for git status #348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 139 additions & 57 deletions lib/git/status.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,130 @@
module Git

#
# A class for git status
#
class Status
include Enumerable

def initialize(base)
@base = base
construct_status
end


#
# Returns an Enumerable containing files that have changed from the
# git base directory
#
# @return [Enumerable]
def changed
@files.select { |k, f| f.type == 'M' }
@files.select { |_k, f| f.type == 'M' }
end


#
# Determines whether the given file has been changed.
# File path starts at git base directory
#
# @param file [String] The name of the file.
# @example Check if lib/git.rb has changed.
# changed?('lib/git.rb')
# @return [Boolean]
def changed?(file)
changed.member?(file)
end

#
# Returns an Enumerable containing files that have been added.
# File path starts at git base directory
#
# @return [Enumerable]
def added
@files.select { |k, f| f.type == 'A' }
@files.select { |_k, f| f.type == 'A' }
end

#
# Determines whether the given file has been added to the repository
# File path starts at git base directory
#
# @param file [String] The name of the file.
# @example Check if lib/git.rb is added.
# added?('lib/git.rb')
# @return [Boolean]
def added?(file)
added.member?(file)
end

#
# Returns an Enumerable containing files that have been deleted.
# File path starts at git base directory
#
# @return [Enumerable]
def deleted
@files.select { |k, f| f.type == 'D' }
@files.select { |_k, f| f.type == 'D' }
end


#
# Determines whether the given file has been deleted from the repository
# File path starts at git base directory
#
# @param file [String] The name of the file.
# @example Check if lib/git.rb is deleted.
# deleted?('lib/git.rb')
# @return [Boolean]
def deleted?(file)
deleted.member?(file)
end

#
# Returns an Enumerable containing files that are not tracked in git.
# File path starts at git base directory
#
# @return [Enumerable]
def untracked
@files.select { |k, f| f.untracked }
@files.select { |_k, f| f.untracked }
end


#
# Determines whether the given file has is tracked by git.
# File path starts at git base directory
#
# @param file [String] The name of the file.
# @example Check if lib/git.rb is an untracked file.
# untracked?('lib/git.rb')
# @return [Boolean]
def untracked?(file)
untracked.member?(file)
end

def pretty
out = ''
self.each do |file|
each do |file|
out << pretty_file(file)
end
out << "\n"
out
end

def pretty_file(file)
<<FILE
#{file.path}
\tsha(r) #{file.sha_repo.to_s} #{file.mode_repo.to_s}
\tsha(i) #{file.sha_index.to_s} #{file.mode_index.to_s}
\ttype #{file.type.to_s}
\tstage #{file.stage.to_s}
\tuntrac #{file.untracked.to_s}
FILE
end
<<-FILE.strip_heredoc
#{file.path}
\tsha(r) #{file.sha_repo} #{file.mode_repo}
\tsha(i) #{file.sha_index} #{file.mode_index}
\ttype #{file.type}
\tstage #{file.stage}
\tuntrac #{file.untracked}
FILE
end

# enumerable method

def [](file)
@files[file]
end

def each(&block)
@files.values.each(&block)
end


# subclass that does heavy lifting
class StatusFile
attr_accessor :path, :type, :stage, :untracked
attr_accessor :mode_index, :mode_repo
Expand All @@ -70,48 +141,59 @@ def initialize(base, hash)
@sha_repo = hash[:sha_repo]
@untracked = hash[:untracked]
end

def blob(type = :index)
if type == :repo
@base.object(@sha_repo)
else
@base.object(@sha_index) rescue @base.object(@sha_repo)
begin
@base.object(@sha_index)
rescue
@base.object(@sha_repo)
end
end
end


end

private

def construct_status
@files = @base.lib.ls_files
ignore = @base.lib.ignored_files

# find untracked in working dir
Dir.chdir(@base.dir.path) do
Dir.glob('**/*', File::FNM_DOTMATCH) do |file|
next if @files[file] || File.directory?(file) || ignore.include?(file) || file =~ /^.git\/.+/

@files[file] = {:path => file, :untracked => true}
end
end

# find modified in tree
@base.lib.diff_files.each do |path, data|
@files[path] ? @files[path].merge!(data) : @files[path] = data
end

# find added but not committed - new files
@base.lib.diff_index('HEAD').each do |path, data|
@files[path] ? @files[path].merge!(data) : @files[path] = data
end

@files.each do |k, file_hash|
@files[k] = StatusFile.new(@base, file_hash)

def construct_status
@files = @base.lib.ls_files

fetch_untracked
fetch_modified
fetch_added

@files.each do |k, file_hash|
@files[k] = StatusFile.new(@base, file_hash)
end
end

def fetch_untracked
ignore = @base.lib.ignored_files

Dir.chdir(@base.dir.path) do
Dir.glob('**/*', File::FNM_DOTMATCH) do |file|
next if @files[file] || File.directory?(file) ||
ignore.include?(file) || file =~ %r{^.git\/.+}

@files[file] = { path: file, untracked: true }
end
end

end

def fetch_modified
# find modified in tree
@base.lib.diff_files.each do |path, data|
@files[path] ? @files[path].merge!(data) : @files[path] = data
end
end

def fetch_added
# find added but not committed - new files
@base.lib.diff_index('HEAD').each do |path, data|
@files[path] ? @files[path].merge!(data) : @files[path] = data
end
end
end

end
65 changes: 62 additions & 3 deletions tests/units/test_status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,75 @@ def setup
def test_dot_files_status
in_temp_dir do |path|
git = Git.clone(@wdir, 'test_dot_files_status')

create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
create_file('test_dot_files_status/.test_file_2', 'content test_file_2')

git.add('test_file_1')
git.add('.test_file_2')

assert(git.status.added.assoc('test_file_1'))
assert(git.status.added.assoc('.test_file_2'))
end
end

def test_added_boolean
in_temp_dir do |path|
git = Git.clone(@wdir, 'test_dot_files_status')

create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')

git.add('test_file_1')

assert(git.status.added?('test_file_1'))
assert(!git.status.added?('test_file_2'))
end
end

def test_changed_boolean
in_temp_dir do |path|
git = Git.clone(@wdir, 'test_dot_files_status')

create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')

git.add('test_file_1')
git.add('test_file_2')
git.commit('message')
update_file('test_dot_files_status/test_file_1', 'update_content tets_file_1')

assert(git.status.changed?('test_file_1'))
assert(!git.status.changed?('test_file_2'))
end
end

def test_deleted_boolean
in_temp_dir do |path|
git = Git.clone(@wdir, 'test_dot_files_status')

create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')

git.add('test_file_1')
git.commit('message')
delete_file('test_dot_files_status/test_file_1')

assert(git.status.deleted?('test_file_1'))
assert(!git.status.deleted?('test_file_2'))
end
end

def test_untracked_boolean
in_temp_dir do |path|
git = Git.clone(@wdir, 'test_dot_files_status')

create_file('test_dot_files_status/test_file_1', 'content tets_file_1')
create_file('test_dot_files_status/test_file_2', 'content tets_file_2')
git.add('test_file_2')

assert(git.status.untracked?('test_file_1'))
assert(!git.status.untracked?('test_file_2'))
end
end
end
8 changes: 4 additions & 4 deletions tests/units/test_thread_safty.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ def setup
def test_git_init_bare
dirs = []
threads = []
5.times do

5.times do
dirs << Dir.mktmpdir
end

dirs.each do |dir|
threads << Thread.new do
Git.init(dir, :bare => true)
end
end

threads.each {|thread| thread.join}
threads.each(&:join)

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