splitlibdiff.patch
lib/diff.rb  

1  1 
# frozen_string_literal: true 
2  2  
3 
module RedmineDiff 

4 
class Diff 

5 
VERSION = 0.3 

6  
7 
def Diff.lcs(a, b) 

8 
astart = 0 

9 
bstart = 0 

10 
afinish = a.length1 

11 
bfinish = b.length1 

12 
mvector = [] 

13  
14 
# First we prune off any common elements at the beginning 

15 
while (astart <= afinish) && (bstart <= afinish) && (a[astart] == b[bstart]) 

16 
mvector[astart] = bstart 

17 
astart += 1 

18 
bstart += 1 

19 
end 

20  
21 
# now the end 

22 
while (astart <= afinish) && (bstart <= bfinish) && (a[afinish] == b[bfinish]) 

23 
mvector[afinish] = bfinish 

24 
afinish = 1 

25 
bfinish = 1 

26 
end 

27  
28 
bmatches = b.reverse_hash(bstart..bfinish) 

29 
thresh = [] 

30 
links = [] 

31  
32 
(astart..afinish).each { aindex 

33 
aelem = a[aindex] 

34 
next unless bmatches.has_key? aelem 

35 
k = nil 

36 
bmatches[aelem].reverse_each { bindex 

37 
if k && (thresh[k] > bindex) && (thresh[k1] < bindex) 

38 
thresh[k] = bindex 

39 
else 

40 
k = thresh.replacenextlarger(bindex, k) 

41 
end 

42 
links[k] = [ (k==0) ? nil : links[k1], aindex, bindex ] if k 

43 
} 

44 
} 

45  
46 
if !thresh.empty? 

47 
link = links[thresh.length1] 

48 
while link 

49 
mvector[link[1]] = link[2] 

50 
link = link[0] 

51 
end 

52 
end 

53  
54 
return mvector 

55 
end 

56  
57 
def makediff(a, b) 

58 
mvector = Diff.lcs(a, b) 

59 
ai = bi = 0 

60 
while ai < mvector.length 

61 
bline = mvector[ai] 

62 
if bline 

63 
while bi < bline 

64 
discardb(bi, b[bi]) 

65 
bi += 1 

66 
end 

67 
match(ai, bi) 

68 
bi += 1 

69 
else 

70 
discarda(ai, a[ai]) 

71 
end 

72 
ai += 1 

73 
end 

74 
while ai < a.length 

75 
discarda(ai, a[ai]) 

76 
ai += 1 

77 
end 

78 
while bi < b.length 

79 
discardb(bi, b[bi]) 

80 
bi += 1 

81 
end 

82 
match(ai, bi) 

83 
1 

84 
end 

85  
86 
def compactdiffs 

87 
diffs = [] 

88 
@diffs.each { df 

89 
i = 0 

90 
curdiff = [] 

91 
while i < df.length 

92 
whot = df[i][0] 

93 
s = @isstring ? df[i][2].chr : [df[i][2]] 

94 
p = df[i][1] 

95 
last = df[i][1] 

96 
i += 1 

97 
while df[i] && df[i][0] == whot && df[i][1] == last+1 

98 
s << df[i][2] 

99 
last = df[i][1] 

100 
i += 1 

101 
end 

102 
curdiff.push [whot, p, s] 

103 
end 

104 
diffs.push curdiff 

105 
} 

106 
return diffs 

107 
end 

108  
109 
attr_reader :diffs, :difftype 

110  
111 
def initialize(diffs_or_a, b = nil, isstring = nil) 

112 
if b.nil? 

113 
@diffs = diffs_or_a 

114 
@isstring = isstring 

115 
else 

116 
@diffs = [] 

117 
@curdiffs = [] 

118 
makediff(diffs_or_a, b) 

119 
@difftype = diffs_or_a.class 

120 
end 

121 
end 

122  
123 
def match(ai, bi) 

124 
@diffs.push @curdiffs unless @curdiffs.empty? 

125 
@curdiffs = [] 

126 
end 

127  
128 
def discarda(i, elem) 

129 
@curdiffs.push ['', i, elem] 

130 
end 

131  
132 
def discardb(i, elem) 

133 
@curdiffs.push ['+', i, elem] 

134 
end 

135  
136 
def compact 

137 
return Diff.new(compactdiffs) 

138 
end 

139  
140 
def compact! 

141 
@diffs = compactdiffs 

142 
end 

143  
144 
def inspect 

145 
@diffs.inspect 

146 
end 

147 
end 

148 
end 

149  
150 
module Diffable 

151 
def diff(b) 

152 
RedmineDiff::Diff.new(self, b) 

153 
end 

154  
155 
# Create a hash that maps elements of the array to arrays of indices 

156 
# where the elements are found. 

157  
158 
def reverse_hash(range = (0...self.length)) 

159 
revmap = {} 

160 
range.each { i 

161 
elem = self[i] 

162 
if revmap.has_key? elem 

163 
revmap[elem].push i 

164 
else 

165 
revmap[elem] = [i] 

166 
end 

167 
} 

168 
return revmap 

169 
end 

170  
171 
def replacenextlarger(value, high = nil) 

172 
high = self.length 

173 
if self.empty?  value > self[1] 

174 
push value 

175 
return high 

176 
end 

177 
# binary search for replacement point 

178 
low = 0 

179 
while low < high 

180 
index = (high+low)/2 

181 
found = self[index] 

182 
return nil if value == found 

183 
if value > found 

184 
low = index + 1 

185 
else 

186 
high = index 

187 
end 

188 
end 

189  
190 
self[low] = value 

191 
# $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_highlow} off )\n" 

192 
# $stderr.puts self.inspect 

193 
# gets 

194 
# p length  low 

195 
return low 

196 
end 

197  
198 
def patch(diff) 

199 
newary = nil 

200 
if diff.difftype == String 

201 
newary = diff.difftype.new('') 

202 
else 

203 
newary = diff.difftype.new 

204 
end 

205 
ai = 0 

206 
bi = 0 

207 
diff.diffs.each { d 

208 
d.each { mod 

209 
case mod[0] 

210 
when '' 

211 
while ai < mod[1] 

212 
newary << self[ai] 

213 
ai += 1 

214 
bi += 1 

215 
end 

216 
ai += 1 

217 
when '+' 

218 
while bi < mod[1] 

219 
newary << self[ai] 

220 
ai += 1 

221 
bi += 1 

222 
end 

223 
newary << mod[2] 

224 
bi += 1 

225 
else 

226 
raise "Unknown diff action" 

227 
end 

228 
} 

229 
} 

230 
while ai < self.length 

231 
newary << self[ai] 

232 
ai += 1 

233 
bi += 1 

234 
end 

235 
return newary 

236 
end 

237 
end 

238  
239  3 
class Array 
240 
include Diffable 

4 
include Redmine::StringArrayDiff::Diffable


241  5 
end 
242  6  
243  7 
class String 
244 
include Diffable 

8 
include Redmine::StringArrayDiff::Diffable


245  9 
end 
246  10  
247  11 
=begin 
lib/redmine/string_array_diff/diff.rb  

1 
# frozen_string_literal: true 

2  
3 
module Redmine 

4 
module StringArrayDiff 

5 
class Diff 

6 
VERSION = 0.3 

7  
8 
def Diff.lcs(a, b) 

9 
astart = 0 

10 
bstart = 0 

11 
afinish = a.length1 

12 
bfinish = b.length1 

13 
mvector = [] 

14  
15 
# First we prune off any common elements at the beginning 

16 
while (astart <= afinish) && (bstart <= afinish) && (a[astart] == b[bstart]) 

17 
mvector[astart] = bstart 

18 
astart += 1 

19 
bstart += 1 

20 
end 

21  
22 
# now the end 

23 
while (astart <= afinish) && (bstart <= bfinish) && (a[afinish] == b[bfinish]) 

24 
mvector[afinish] = bfinish 

25 
afinish = 1 

26 
bfinish = 1 

27 
end 

28  
29 
bmatches = b.reverse_hash(bstart..bfinish) 

30 
thresh = [] 

31 
links = [] 

32  
33 
(astart..afinish).each { aindex 

34 
aelem = a[aindex] 

35 
next unless bmatches.has_key? aelem 

36 
k = nil 

37 
bmatches[aelem].reverse_each { bindex 

38 
if k && (thresh[k] > bindex) && (thresh[k1] < bindex) 

39 
thresh[k] = bindex 

40 
else 

41 
k = thresh.replacenextlarger(bindex, k) 

42 
end 

43 
links[k] = [ (k==0) ? nil : links[k1], aindex, bindex ] if k 

44 
} 

45 
} 

46  
47 
if !thresh.empty? 

48 
link = links[thresh.length1] 

49 
while link 

50 
mvector[link[1]] = link[2] 

51 
link = link[0] 

52 
end 

53 
end 

54  
55 
return mvector 

56 
end 

57  
58 
def makediff(a, b) 

59 
mvector = Diff.lcs(a, b) 

60 
ai = bi = 0 

61 
while ai < mvector.length 

62 
bline = mvector[ai] 

63 
if bline 

64 
while bi < bline 

65 
discardb(bi, b[bi]) 

66 
bi += 1 

67 
end 

68 
match(ai, bi) 

69 
bi += 1 

70 
else 

71 
discarda(ai, a[ai]) 

72 
end 

73 
ai += 1 

74 
end 

75 
while ai < a.length 

76 
discarda(ai, a[ai]) 

77 
ai += 1 

78 
end 

79 
while bi < b.length 

80 
discardb(bi, b[bi]) 

81 
bi += 1 

82 
end 

83 
match(ai, bi) 

84 
1 

85 
end 

86  
87 
def compactdiffs 

88 
diffs = [] 

89 
@diffs.each { df 

90 
i = 0 

91 
curdiff = [] 

92 
while i < df.length 

93 
whot = df[i][0] 

94 
s = @isstring ? df[i][2].chr : [df[i][2]] 

95 
p = df[i][1] 

96 
last = df[i][1] 

97 
i += 1 

98 
while df[i] && df[i][0] == whot && df[i][1] == last+1 

99 
s << df[i][2] 

100 
last = df[i][1] 

101 
i += 1 

102 
end 

103 
curdiff.push [whot, p, s] 

104 
end 

105 
diffs.push curdiff 

106 
} 

107 
return diffs 

108 
end 

109  
110 
attr_reader :diffs, :difftype 

111  
112 
def initialize(diffs_or_a, b = nil, isstring = nil) 

113 
if b.nil? 

114 
@diffs = diffs_or_a 

115 
@isstring = isstring 

116 
else 

117 
@diffs = [] 

118 
@curdiffs = [] 

119 
makediff(diffs_or_a, b) 

120 
@difftype = diffs_or_a.class 

121 
end 

122 
end 

123  
124 
def match(ai, bi) 

125 
@diffs.push @curdiffs unless @curdiffs.empty? 

126 
@curdiffs = [] 

127 
end 

128  
129 
def discarda(i, elem) 

130 
@curdiffs.push ['', i, elem] 

131 
end 

132  
133 
def discardb(i, elem) 

134 
@curdiffs.push ['+', i, elem] 

135 
end 

136  
137 
def compact 

138 
return Diff.new(compactdiffs) 

139 
end 

140  
141 
def compact! 

142 
@diffs = compactdiffs 

143 
end 

144  
145 
def inspect 

146 
@diffs.inspect 

147 
end 

148 
end 

149 
end 

150 
end 
lib/redmine/string_array_diff/diffable.rb  

1 
# frozen_string_literal: true 

2  
3 
module Redmine 

4 
module StringArrayDiff 

5 
module Diffable 

6 
def diff(b) 

7 
Redmine::StringArrayDiff::Diff.new(self, b) 

8 
end 

9  
10 
# Create a hash that maps elements of the array to arrays of indices 

11 
# where the elements are found. 

12  
13 
def reverse_hash(range = (0...self.length)) 

14 
revmap = {} 

15 
range.each { i 

16 
elem = self[i] 

17 
if revmap.has_key? elem 

18 
revmap[elem].push i 

19 
else 

20 
revmap[elem] = [i] 

21 
end 

22 
} 

23 
return revmap 

24 
end 

25  
26 
def replacenextlarger(value, high = nil) 

27 
high = self.length 

28 
if self.empty?  value > self[1] 

29 
push value 

30 
return high 

31 
end 

32 
# binary search for replacement point 

33 
low = 0 

34 
while low < high 

35 
index = (high+low)/2 

36 
found = self[index] 

37 
return nil if value == found 

38 
if value > found 

39 
low = index + 1 

40 
else 

41 
high = index 

42 
end 

43 
end 

44  
45 
self[low] = value 

46 
# $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_highlow} off )\n" 

47 
# $stderr.puts self.inspect 

48 
# gets 

49 
# p length  low 

50 
return low 

51 
end 

52  
53 
def patch(diff) 

54 
newary = nil 

55 
if diff.difftype == String 

56 
newary = diff.difftype.new('') 

57 
else 

58 
newary = diff.difftype.new 

59 
end 

60 
ai = 0 

61 
bi = 0 

62 
diff.diffs.each { d 

63 
d.each { mod 

64 
case mod[0] 

65 
when '' 

66 
while ai < mod[1] 

67 
newary << self[ai] 

68 
ai += 1 

69 
bi += 1 

70 
end 

71 
ai += 1 

72 
when '+' 

73 
while bi < mod[1] 

74 
newary << self[ai] 

75 
ai += 1 

76 
bi += 1 

77 
end 

78 
newary << mod[2] 

79 
bi += 1 

80 
else 

81 
raise "Unknown diff action" 

82 
end 

83 
} 

84 
} 

85 
while ai < self.length 

86 
newary << self[ai] 

87 
ai += 1 

88 
bi += 1 

89 
end 

90 
return newary 

91 
end 

92 
end 

93 
end 

94 
end 