forked from mojombo/grit
-
Notifications
You must be signed in to change notification settings - Fork 73
/
status.rb
149 lines (123 loc) · 3.84 KB
/
status.rb
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
module Grit
class Status
include Enumerable
@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('**/*') do |file|
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