class Git::Status
The Status
class gets the status of a git repository. It identifies which files have been modified, added, or deleted, including untracked files. The Status
object is an Enumerable of StatusFile objects.
@api public
Public Class Methods
Source
# File lib/git/status.rb, line 16 def initialize(base) @base = base # The factory returns a hash of file paths to StatusFile objects. @files = StatusFileFactory.new(base).construct_files end
@param base [Git::Base] The base git object
Public Instance Methods
Source
# File lib/git/status.rb, line 36 def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end
Access a status file by path, or iterate over all status files.
Source
# File lib/git/status.rb, line 24 def added = @added ||= select_files { |f| f.type == 'A' } def deleted = @deleted ||= select_files { |f| f.type == 'D' } # This works with `true` or `nil` def untracked = @untracked ||= select_files(&:untracked) # Predicate methods to check the status of a specific file. def changed?(file) = file_in_collection?(:changed, file) def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data)
Source
# File lib/git/status.rb, line 31 def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data) end end
Source
# File lib/git/status.rb, line 23 def changed = @changed ||= select_files { |f| f.type == 'M' } def added = @added ||= select_files { |f| f.type == 'A' } def deleted = @deleted ||= select_files { |f| f.type == 'D' } # This works with `true` or `nil` def untracked = @untracked ||= select_files(&:untracked) # Predicate methods to check the status of a specific file. def changed?(file) = file_in_collection?(:changed, file) def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(
File status collections, memoized for performance.
Source
# File lib/git/status.rb, line 30 def changed?(file) = file_in_collection?(:changed, file) def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data) end end
Predicate methods to check the status of a specific file.
Source
# File lib/git/status.rb, line 25 def deleted = @deleted ||= select_files { |f| f.type == 'D' } # This works with `true` or `nil` def untracked = @untracked ||= select_files(&:untracked) # Predicate methods to check the status of a specific file. def changed?(file) = file_in_collection?(:changed, file) def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data)
Source
# File lib/git/status.rb, line 32 def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data) end end end
Source
# File lib/git/status.rb, line 70 def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end
Source
# File lib/git/status.rb, line 37 def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end
Source
# File lib/git/status.rb, line 61 def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end
Source
# File lib/git/status.rb, line 76 def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end
Source
# File lib/git/status.rb, line 40 def pretty map { |file| pretty_file(file) }.join << "\n" end
Returns a formatted string representation of the status.
Source
# File lib/git/status.rb, line 46 def pretty_file(file) <<~FILE #{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
Source
# File lib/git/status.rb, line 57 def select_files(&block) @files.select { |_path, file| block.call(file) } end
Source
# File lib/git/status.rb, line 27 def untracked = @untracked ||= select_files(&:untracked) # Predicate methods to check the status of a specific file. def changed?(file) = file_in_collection?(:changed, file) def added?(file) = file_in_collection?(:added, file) def deleted?(file) = file_in_collection?(:deleted, file) def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data) end
This works with ‘true` or `nil`
Source
# File lib/git/status.rb, line 33 def untracked?(file) = file_in_collection?(:untracked, file) # Access a status file by path, or iterate over all status files. def [](file) = @files[file] def each(&) = @files.values.each(&) # Returns a formatted string representation of the status. def pretty map { |file| pretty_file(file) }.join << "\n" end private def pretty_file(file) <<~FILE #{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 def select_files(&block) @files.select { |_path, file| block.call(file) } end def file_in_collection?(collection_name, file_path) collection = public_send(collection_name) if ignore_case? downcased_keys(collection_name).include?(file_path.downcase) else collection.key?(file_path) end end def downcased_keys(collection_name) @_downcased_keys ||= {} @_downcased_keys[collection_name] ||= public_send(collection_name).keys.to_set(&:downcase) end def ignore_case? return @_ignore_case if defined?(@_ignore_case) @_ignore_case = (@base.config('core.ignoreCase') == 'true') rescue Git::FailedError @_ignore_case = false end end end module Git class Status # Represents a single file's status in the git repository. Each instance # holds information about a file's state in the index and working tree. class StatusFile attr_reader :path, :type, :stage, :mode_index, :mode_repo, :sha_index, :sha_repo, :untracked def initialize(base, hash) @base = base @path = hash[:path] @type = hash[:type] @stage = hash[:stage] @mode_index = hash[:mode_index] @mode_repo = hash[:mode_repo] @sha_index = hash[:sha_index] @sha_repo = hash[:sha_repo] @untracked = hash[:untracked] end # Returns a Git::Object::Blob for either the index or repo version of the file. def blob(type = :index) sha = type == :repo ? sha_repo : (sha_index || sha_repo) @base.object(sha) if sha end end end end module Git class Status # A factory class responsible for fetching git status data and building # a hash of StatusFile objects. # @api private class StatusFileFactory def initialize(base) @base = base @lib = base.lib end # Gathers all status data and builds a hash of file paths to # StatusFile objects. def construct_files files_data = fetch_all_files_data files_data.transform_values do |data| StatusFile.new(@base, data) end end private # Fetches and merges status information from multiple git commands. def fetch_all_files_data files = @lib.ls_files # Start with files tracked in the index. merge_untracked_files(files) merge_modified_files(files) merge_head_diffs(files) files end def merge_untracked_files(files) @lib.untracked_files.each do |file| files[file] = { path: file, untracked: true } end end def merge_modified_files(files) # Merge changes between the index and the working directory. @lib.diff_files.each do |path, data| (files[path] ||= {}).merge!(data) end end def merge_head_diffs(files) return if @lib.empty? # Merge changes between HEAD and the index. @lib.diff_index('HEAD').each do |path, data| (files[path] ||= {}).merge!(data) end end end end