Class: Rpatch::PatchHunk
- Inherits:
-
Object
- Object
- Rpatch::PatchHunk
- Defined in:
- lib/rpatch/hunk.rb
Instance Attribute Summary collapse
-
#diffs ⇒ Object
readonly
Returns the value of attribute diffs.
-
#num ⇒ Object
readonly
Returns the value of attribute num.
-
#title ⇒ Object
readonly
Returns the value of attribute title.
Instance Method Summary collapse
-
#convert(lines) ⇒ Object
Apply patch on lines.
- #feed_line(line) ⇒ Object
-
#get_matched_size(lines, patterns) ⇒ Object
Test whether patterns match against the beginning of lines Return nil if not match, or return number of lines matched with patterns (would be replaced later).
- #has_add? ⇒ Boolean
- #head? ⇒ Boolean
-
#initialize(text, num = nil) ⇒ PatchHunk
constructor
A new instance of PatchHunk.
-
#match_after_patch(lines) ⇒ Object
Return [location, num_of_lines], which seems already patched, and match start with location and num lines are matched.
-
#match_before_patch(lines) ⇒ Object
Return [location, num_of_lines], which could apply patch at at location, and num lines would be replaced.
-
#patch(lines) ⇒ Object
Patch lines in place.
- #patterns ⇒ Object
- #patterns_after_patch ⇒ Object
- #patterns_before_patch ⇒ Object
- #tail? ⇒ Boolean
Constructor Details
#initialize(text, num = nil) ⇒ PatchHunk
Returns a new instance of PatchHunk.
89 90 91 92 93 |
# File 'lib/rpatch/hunk.rb', line 89 def initialize(text, num=nil) @title = text.chomp.sub(/^@@/, '').strip @num = num || "#" @diffs = [] end |
Instance Attribute Details
#diffs ⇒ Object (readonly)
Returns the value of attribute diffs.
87 88 89 |
# File 'lib/rpatch/hunk.rb', line 87 def diffs @diffs end |
#num ⇒ Object (readonly)
Returns the value of attribute num.
87 88 89 |
# File 'lib/rpatch/hunk.rb', line 87 def num @num end |
#title ⇒ Object (readonly)
Returns the value of attribute title.
87 88 89 |
# File 'lib/rpatch/hunk.rb', line 87 def title @title end |
Instance Method Details
#convert(lines) ⇒ Object
Apply patch on lines. Return array of strings contain result of applying patch.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rpatch/hunk.rb', line 135 def convert(lines) lines = lines.dup result = [] i = j = 0 while i < diffs.size case diffs[i] when /^\??\/? / while true match = patterns[j].match lines.first if not match raise PatchFormatError.new("Hunk #{num} (#{title}) FAILED to apply. No match \"#{patterns[j]}\" with #{lines.first.inspect}.") elsif match > 0 result << lines.shift break elsif match == 0 result << lines.shift end end when /^\??\/?[-]/ while true match = patterns[j].match lines.first if not match raise PatchFormatError.new("Hunk #{num} (#{title}) FAILED to apply. No match pattern \"#{patterns[j]}\" against #{lines.first.inspect}.") elsif match > 0 lines.shift break elsif match == 0 lines.shift end end when /^(\??\/?\+)/ result << diffs[i][$1.size..-1] when /^(<|>)$/ # patterns do not have locaiton direction j -= 1 else raise PatchFormatError.new("Hunk #{num} (#{title}) FAILED to apply. Unknow syntax in hunk: #{diffs[i]}") end i += 1 j += 1 end result end |
#feed_line(line) ⇒ Object
95 96 97 |
# File 'lib/rpatch/hunk.rb', line 95 def feed_line(line) @diffs << line.chomp end |
#get_matched_size(lines, patterns) ⇒ Object
Test whether patterns match against the beginning of lines Return nil if not match, or return number of lines matched with patterns (would be replaced later).
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/rpatch/hunk.rb', line 256 def get_matched_size(lines, patterns) i = 0 found = true patterns.each do |pattern| unless lines[i] found = false break end while true match = pattern.match lines[i] if not match found = false break # Match precisely for the first line of pattern (i==0), # Not pass blank lines. elsif match == 0 and i == 0 found = false break # Matched. elsif match > 0 break # Match next line if this line is blank. elsif match == 0 i += 1 unless lines[i] found = false break end # Never comes here. else found = false break end end break unless found i += 1 end if found i else nil end end |
#has_add? ⇒ Boolean
107 108 109 110 111 |
# File 'lib/rpatch/hunk.rb', line 107 def has_add? @has_add ||= begin patterns.select{|p| p.is_add?}.any? end end |
#head? ⇒ Boolean
99 100 101 |
# File 'lib/rpatch/hunk.rb', line 99 def head? not tail? end |
#match_after_patch(lines) ⇒ Object
Return [location, num_of_lines], which seems already patched, and match start with location and num lines are matched. Return nil, if nothing matched.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/rpatch/hunk.rb', line 182 def match_after_patch(lines) if patterns_after_patch.size == 0 return head? ? [0, 0] : [lines.size, 0] end if head? i = 0 loop_n = lines.size - patterns_after_patch.size while i <= loop_n matched_size = get_matched_size(lines[i..-1], patterns_after_patch) if matched_size return [i, matched_size] else i += 1 end end else i = lines.size - patterns_after_patch.size while i >= 0 matched_size = get_matched_size(lines[i..-1], patterns_after_patch) if matched_size return [i, matched_size] else i -= 1 end end end nil end |
#match_before_patch(lines) ⇒ Object
Return [location, num_of_lines], which could apply patch at at location, and num lines would be replaced. Return nil, if nothing matched.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/rpatch/hunk.rb', line 215 def match_before_patch(lines) # puts "="*90 # puts patterns_before_patch.inspect # puts patterns_before_patch.size # puts "-"*90 # puts diffs.inspect #puts "-"*90 #puts patterns.map{|p| [p.pattern.inspect, p.is_in_before?.inspect, p.is_in_after?.inspect]}.inspect if patterns_before_patch.size == 0 return head? ? [0, 0] : [lines.size, 0] end if head? i = 0 loop_n = lines.size - patterns_before_patch.size while i <= loop_n matched_size = get_matched_size(lines[i..-1], patterns_before_patch) if matched_size return [i, matched_size] else i += 1 end end else i = lines.size - patterns_before_patch.size while i >= 0 matched_size = get_matched_size(lines[i..-1], patterns_before_patch) if matched_size return [i, matched_size] else i -= 1 end end end nil end |
#patch(lines) ⇒ Object
Patch lines in place.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/rpatch/hunk.rb', line 114 def patch(lines) matched_before = match_before_patch lines matched_after = match_after_patch lines if matched_after if not matched_before raise AlreadyPatchedError.new("Hunk #{num} (#{title}) is already patched.") elsif has_add? raise AlreadyPatchedError.new("Hunk #{num} (#{title}) is already patched.") end elsif not matched_before raise PatchHunkError, "Hunk #{num} (#{title}) FAILED to apply. Match failed." end n, size = matched_before lines[n...(n+size)] = convert lines[n...(n+size)] lines end |
#patterns ⇒ Object
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/rpatch/hunk.rb', line 315 def patterns @patterns ||= begin result = [] diffs.each do |line| case line when /^(RE: |RE:-)/ raise PatchFormatError.new("Obsolete pattern, subsitude \"RE:\" with \"/\":\n=> #{line}") when /^(<|>)$/ # ignore locaiton direction else result << Pattern.new(line) end end result end end |
#patterns_after_patch ⇒ Object
309 310 311 312 313 |
# File 'lib/rpatch/hunk.rb', line 309 def patterns_after_patch @patterns_after_patch ||= begin patterns.select{|p| p.is_in_after?} end end |
#patterns_before_patch ⇒ Object
303 304 305 306 307 |
# File 'lib/rpatch/hunk.rb', line 303 def patterns_before_patch @patterns_before_patch ||= begin patterns.select{|p| p.is_in_before?} end end |
#tail? ⇒ Boolean
103 104 105 |
# File 'lib/rpatch/hunk.rb', line 103 def tail? diffs.first == ">" end |