1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
module Grit
class Status
include Enumerable
attr_reader :files
@base = nil
@files = nil
def initialize(base)
@base = base
construct_status
end
def changed
@files.select { |k, f| f.type == 'M' }
end
def added
@files.select { |k, f| f.type == 'A' }
end
def deleted
@files.select { |k, f| f.type == 'D' }
end
def untracked
@files.select { |k, f| f.untracked }
end
def pretty
out = ''
self.each do |file|
out << file.path
out << "\n\tsha(r) " + file.sha_repo.to_s + ' ' + file.mode_repo.to_s
out << "\n\tsha(i) " + file.sha_index.to_s + ' ' + file.mode_index.to_s
out << "\n\ttype " + file.type.to_s
out << "\n\tstage " + file.stage.to_s
out << "\n\tuntrac " + file.untracked.to_s
out << "\n"
end
out << "\n"
out
end
# enumerable method
def [](file)
@files[file]
end
def each
@files.each do |k, file|
yield file
end
end
class StatusFile
attr_accessor :path, :type, :stage, :untracked
attr_accessor :mode_index, :mode_repo
attr_accessor :sha_index, :sha_repo
@base = nil
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
def blob(type = :index)
if type == :repo
@base.object(@sha_repo)
else
@base.object(@sha_index) rescue @base.object(@sha_repo)
end
end
end
private
def construct_status
@files = ls_files
# find untracked in working dir
Dir.glob(File.join(@base.working_dir, '**/*')) do |full_file|
file = full_file.gsub "#{@base.working_dir}/", ""
if !@files[file]
@files[file] = {:path => file, :untracked => true} if !File.directory?(file)
end
end
# find modified in tree
diff_files.each do |path, data|
@files[path] ? @files[path].merge!(data) : @files[path] = data
end
# find added but not committed - new files
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)
end
end
# compares the index and the working directory
def diff_files
hsh = {}
@base.git.diff_files({}).split("\n").each do |line|
(info, file) = line.split("\t")
(mode_src, mode_dest, sha_src, sha_dest, type) = info.split
hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
:sha_file => sha_src, :sha_index => sha_dest, :type => type}
end
hsh
end
# compares the index and the repository
def diff_index(treeish)
hsh = {}
@base.git.diff_index({}, treeish).split("\n").each do |line|
(info, file) = line.split("\t")
(mode_src, mode_dest, sha_src, sha_dest, type) = info.split
hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
:sha_repo => sha_src, :sha_index => sha_dest, :type => type}
end
hsh
end
def ls_files
hsh = {}
lines = @base.git.ls_files({:stage => true})
lines.split("\n").each do |line|
(info, file) = line.split("\t")
(mode, sha, stage) = info.split
hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
end
hsh
end
end
end
|