comparison mercurial/mdiff.py @ 31271:b3861be6aa6c

mdiff: distinguish diff headers from hunks in unidiff() Let unidiff return the list of headers it produces (lines '--- <original>' and '+++ <new>') apart from diff hunks. In patch.diff(), we combine headers generated there (not specific to unified format) with those from unidiff(). By returning a list of header lines, we do not append new lines in datetag inner function of unidiff() so that all header lines are '\n'.join-ed in a similar way.
author Denis Laxalde <denis.laxalde@logilab.fr>
date Fri, 03 Mar 2017 13:51:22 +0100
parents 5e7fd3a0b17f
children e41946f39724
comparison
equal deleted inserted replaced
31270:59aec562a50b 31271:b3861be6aa6c
194 type = '~' 194 type = '~'
195 yield s, type 195 yield s, type
196 yield s1, '=' 196 yield s1, '='
197 197
198 def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts): 198 def unidiff(a, ad, b, bd, fn1, fn2, opts=defaultopts):
199 """Return a unified diff as a (headers, hunkstext) tuple.
200
201 If the diff is not null, `headers` is a list with unified diff header
202 lines "--- <original>" and "+++ <new>" and `hunkstext` is a string
203 containing diff hunks. Otherwise, both `headers` and `hunkstext` are
204 empty.
205 """
199 def datetag(date, fn=None): 206 def datetag(date, fn=None):
200 if not opts.git and not opts.nodates: 207 if not opts.git and not opts.nodates:
201 return '\t%s\n' % date 208 return '\t%s' % date
202 if fn and ' ' in fn: 209 if fn and ' ' in fn:
203 return '\t\n' 210 return '\t'
204 return '\n' 211 return ''
205 212
213 sentinel = [], ""
206 if not a and not b: 214 if not a and not b:
207 return "" 215 return sentinel
208 216
209 if opts.noprefix: 217 if opts.noprefix:
210 aprefix = bprefix = '' 218 aprefix = bprefix = ''
211 else: 219 else:
212 aprefix = 'a/' 220 aprefix = 'a/'
217 fn1 = util.pconvert(fn1) 225 fn1 = util.pconvert(fn1)
218 fn2 = util.pconvert(fn2) 226 fn2 = util.pconvert(fn2)
219 227
220 if not opts.text and (util.binary(a) or util.binary(b)): 228 if not opts.text and (util.binary(a) or util.binary(b)):
221 if a and b and len(a) == len(b) and a == b: 229 if a and b and len(a) == len(b) and a == b:
222 return "" 230 return sentinel
231 headerlines = []
223 l = ['Binary file %s has changed\n' % fn1] 232 l = ['Binary file %s has changed\n' % fn1]
224 elif not a: 233 elif not a:
225 b = splitnewlines(b) 234 b = splitnewlines(b)
226 if a is None: 235 if a is None:
227 l1 = '--- /dev/null%s' % datetag(epoch) 236 l1 = '--- /dev/null%s' % datetag(epoch)
228 else: 237 else:
229 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)) 238 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
230 l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2)) 239 l2 = "+++ %s%s" % (bprefix + fn2, datetag(bd, fn2))
231 l3 = "@@ -0,0 +1,%d @@\n" % len(b) 240 headerlines = [l1, l2]
232 l = [l1, l2, l3] + ["+" + e for e in b] 241 l = ["@@ -0,0 +1,%d @@\n" % len(b)] + ["+" + e for e in b]
233 elif not b: 242 elif not b:
234 a = splitnewlines(a) 243 a = splitnewlines(a)
235 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)) 244 l1 = "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))
236 if b is None: 245 if b is None:
237 l2 = '+++ /dev/null%s' % datetag(epoch) 246 l2 = '+++ /dev/null%s' % datetag(epoch)
238 else: 247 else:
239 l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)) 248 l2 = "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))
240 l3 = "@@ -1,%d +0,0 @@\n" % len(a) 249 headerlines = [l1, l2]
241 l = [l1, l2, l3] + ["-" + e for e in a] 250 l = ["@@ -1,%d +0,0 @@\n" % len(a)] + ["-" + e for e in a]
242 else: 251 else:
243 l = sum((hlines for hrange, hlines in _unidiff(a, b, opts=opts)), []) 252 l = sum((hlines for hrange, hlines in _unidiff(a, b, opts=opts)), [])
244 if not l: 253 if not l:
245 return "" 254 return sentinel
246 255
247 l.insert(0, "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1))) 256 headerlines = [
248 l.insert(1, "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2))) 257 "--- %s%s%s" % (aprefix, fn1, datetag(ad, fn1)),
258 "+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)),
259 ]
249 260
250 for ln in xrange(len(l)): 261 for ln in xrange(len(l)):
251 if l[ln][-1] != '\n': 262 if l[ln][-1] != '\n':
252 l[ln] += "\n\ No newline at end of file\n" 263 l[ln] += "\n\ No newline at end of file\n"
253 264
254 return "".join(l) 265 return headerlines, "".join(l)
255 266
256 def _unidiff(t1, t2, opts=defaultopts): 267 def _unidiff(t1, t2, opts=defaultopts):
257 """Yield hunks of a headerless unified diff from t1 and t2 texts. 268 """Yield hunks of a headerless unified diff from t1 and t2 texts.
258 269
259 Each hunk consists of a (hunkrange, hunklines) tuple where `hunkrange` is a 270 Each hunk consists of a (hunkrange, hunklines) tuple where `hunkrange` is a