1
1
module Git
2
-
2
+
3
3
# object that holds the last X commits on given branch
4
4
class Diff
5
5
include Enumerable
6
-
6
+
7
7
def initialize ( base , from = nil , to = nil )
8
8
@base = base
9
- @from = from && from . to_s
9
+ @from = from && from . to_s
10
10
@to = to && to . to_s
11
11
12
12
@path = nil
@@ -15,7 +15,7 @@ def initialize(base, from = nil, to = nil)
15
15
@stats = nil
16
16
end
17
17
attr_reader :from , :to
18
-
18
+
19
19
def name_status
20
20
cache_name_status
21
21
end
@@ -24,55 +24,55 @@ def path(path)
24
24
@path = path
25
25
return self
26
26
end
27
-
27
+
28
28
def size
29
29
cache_stats
30
30
@stats [ :total ] [ :files ]
31
31
end
32
-
32
+
33
33
def lines
34
34
cache_stats
35
35
@stats [ :total ] [ :lines ]
36
36
end
37
-
37
+
38
38
def deletions
39
39
cache_stats
40
40
@stats [ :total ] [ :deletions ]
41
41
end
42
-
42
+
43
43
def insertions
44
44
cache_stats
45
45
@stats [ :total ] [ :insertions ]
46
46
end
47
-
47
+
48
48
def stats
49
49
cache_stats
50
50
@stats
51
51
end
52
-
52
+
53
53
# if file is provided and is writable, it will write the patch into the file
54
54
def patch ( file = nil )
55
55
cache_full
56
56
@full_diff
57
57
end
58
58
alias_method :to_s , :patch
59
-
59
+
60
60
# enumerable methods
61
-
61
+
62
62
def []( key )
63
63
process_full
64
64
@full_diff_files . assoc ( key ) [ 1 ]
65
65
end
66
-
66
+
67
67
def each ( &block ) # :yields: each Git::DiffFile in turn
68
68
process_full
69
69
@full_diff_files . map { |file | file [ 1 ] } . each ( &block )
70
70
end
71
-
71
+
72
72
class DiffFile
73
73
attr_accessor :patch , :path , :mode , :src , :dst , :type
74
74
@base = nil
75
-
75
+
76
76
def initialize ( base , hash )
77
77
@base = base
78
78
@patch = hash [ :patch ]
@@ -87,7 +87,7 @@ def initialize(base, hash)
87
87
def binary?
88
88
!!@binary
89
89
end
90
-
90
+
91
91
def blob ( type = :dst )
92
92
if type == :src
93
93
@base . object ( @src ) if @src != '0000000'
@@ -96,27 +96,27 @@ def blob(type = :dst)
96
96
end
97
97
end
98
98
end
99
-
99
+
100
100
private
101
-
101
+
102
102
def cache_full
103
103
@full_diff ||= @base . lib . diff_full ( @from , @to , { :path_limiter => @path } )
104
104
end
105
-
105
+
106
106
def process_full
107
107
return if @full_diff_files
108
108
cache_full
109
109
@full_diff_files = process_full_diff
110
110
end
111
-
111
+
112
112
def cache_stats
113
113
@stats ||= @base . lib . diff_stats ( @from , @to , { :path_limiter => @path } )
114
114
end
115
115
116
116
def cache_name_status
117
117
@name_status ||= @base . lib . diff_name_status ( @from , @to , { :path => @path } )
118
118
end
119
-
119
+
120
120
# break up @diff_full
121
121
def process_full_diff
122
122
defaults = {
@@ -127,7 +127,11 @@ def process_full_diff
127
127
}
128
128
final = { }
129
129
current_file = nil
130
- @full_diff . split ( "\n " ) . each do |line |
130
+ full_diff_utf8_encoded = @full_diff . encode ( "UTF-8" , "binary" , {
131
+ :invalid => :replace ,
132
+ :undef => :replace
133
+ } )
134
+ full_diff_utf8_encoded . split ( "\n " ) . each do |line |
131
135
if m = /^diff --git a\/ (.*?) b\/ (.*?)/ . match ( line )
132
136
current_file = m [ 1 ]
133
137
final [ current_file ] = defaults . merge ( { :patch => line , :path => current_file } )
@@ -144,11 +148,11 @@ def process_full_diff
144
148
if m = /^Binary files / . match ( line )
145
149
final [ current_file ] [ :binary ] = true
146
150
end
147
- final [ current_file ] [ :patch ] << "\n " + line
151
+ final [ current_file ] [ :patch ] << "\n " + line
148
152
end
149
153
end
150
154
final . map { |e | [ e [ 0 ] , DiffFile . new ( @base , e [ 1 ] ) ] }
151
155
end
152
-
156
+
153
157
end
154
158
end
0 commit comments