diff --git a/lib/git/status.rb b/lib/git/status.rb index d59bc777..23050e08 100644 --- a/lib/git/status.rb +++ b/lib/git/status.rb @@ -1,32 +1,102 @@ 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" @@ -34,26 +104,27 @@ def pretty end def pretty_file(file) - < 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 diff --git a/tests/units/test_status.rb b/tests/units/test_status.rb index 6479b628..0cb863da 100644 --- a/tests/units/test_status.rb +++ b/tests/units/test_status.rb @@ -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 diff --git a/tests/units/test_thread_safty.rb b/tests/units/test_thread_safty.rb index fd2dd2c0..401659a5 100644 --- a/tests/units/test_thread_safty.rb +++ b/tests/units/test_thread_safty.rb @@ -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