def diff(self, tmpl, node1, node2, files): def filterfiles(filters, files): l = [x for x in files if x in filters] for t in filters: if t and t[-1] != os.sep: t += os.sep l += [x for x in files if x.startswith(t)] return l parity = paritygen(self.stripecount) def diffblock(diff, f, fn): yield tmpl( "diffblock", lines=prettyprintlines(diff), parity=parity.next(), file=f, filenode=hex(fn or nullid) ) blockcount = webutil.countgen() def prettyprintlines(diff): blockno = blockcount.next() for lineno, l in enumerate(diff.splitlines(1)): if blockno == 0: lineno = lineno + 1 else: lineno = "%d.%d" % (blockno, lineno + 1) if l.startswith("+"): ltype = "difflineplus" elif l.startswith("-"): ltype = "difflineminus" elif l.startswith("@"): ltype = "difflineat" else: ltype = "diffline" yield tmpl(ltype, line=l, lineid="l%s" % lineno, linenumber="% 8s" % lineno) r = self.repo c1 = r[node1] c2 = r[node2] date1 = util.datestr(c1.date()) date2 = util.datestr(c2.date()) modified, added, removed, deleted, unknown = r.status(node1, node2)[:5] if files: modified, added, removed = map(lambda x: filterfiles(files, x), (modified, added, removed)) for f in modified: to = c1.filectx(f).data() tn = c2.filectx(f).data() yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f), f, tn) for f in added: to = None tn = c2.filectx(f).data() yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f), f, tn) for f in removed: to = c1.filectx(f).data() tn = None yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f), f, tn)
def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None): '''yields diff of changes to files between two nodes, or node and working directory. if node1 is None, use first dirstate parent instead. if node2 is None, compare node1 with working directory.''' if opts is None: opts = mdiff.defaultopts if not node1: node1 = repo.dirstate.parents()[0] def lrugetfilectx(): cache = {} order = [] def getfilectx(f, ctx): fctx = ctx.filectx(f, filelog=cache.get(f)) if f not in cache: if len(cache) > 20: del cache[order.pop(0)] cache[f] = fctx._filelog else: order.remove(f) order.append(f) return fctx return getfilectx getfilectx = lrugetfilectx() ctx1 = repo[node1] ctx2 = repo[node2] if not changes: changes = repo.status(ctx1, ctx2, match=match) modified, added, removed = changes[:3] if not modified and not added and not removed: return date1 = util.datestr(ctx1.date()) man1 = ctx1.manifest() if repo.ui.quiet: r = None else: hexfunc = repo.ui.debugflag and hex or short r = [hexfunc(node) for node in [node1, node2] if node] if opts.git: copy, diverge = copies.copies(repo, ctx1, ctx2, repo[nullid]) copy = copy.copy() for k, v in copy.items(): copy[v] = k gone = set() gitmode = {'l': '120000', 'x': '100755', '': '100644'} for f in sorted(modified + added + removed): to = None tn = None dodiff = True header = [] if f in man1: to = getfilectx(f, ctx1).data() if f not in removed: tn = getfilectx(f, ctx2).data() a, b = f, f if opts.git: if f in added: mode = gitmode[ctx2.flags(f)] if f in copy: a = copy[f] omode = gitmode[man1.flags(a)] _addmodehdr(header, omode, mode) if a in removed and a not in gone: op = 'rename' gone.add(a) else: op = 'copy' header.append('%s from %s\n' % (op, a)) header.append('%s to %s\n' % (op, f)) to = getfilectx(a, ctx1).data() else: header.append('new file mode %s\n' % mode) if util.binary(tn): dodiff = 'binary' elif f in removed: # have we already reported a copy above? if f in copy and copy[f] in added and copy[copy[f]] == f: dodiff = False else: header.append('deleted file mode %s\n' % gitmode[man1.flags(f)]) else: omode = gitmode[man1.flags(f)] nmode = gitmode[ctx2.flags(f)] _addmodehdr(header, omode, nmode) if util.binary(to) or util.binary(tn): dodiff = 'binary' r = None header.insert(0, mdiff.diffline(r, a, b, opts)) if dodiff: if dodiff == 'binary': text = b85diff(to, tn) else: text = mdiff.unidiff(to, date1, # ctx2 date may be dynamic tn, util.datestr(ctx2.date()), a, b, r, opts=opts) if header and (text or len(header) > 1): yield ''.join(header) if text: yield text
def diff(repo, node1=None, node2=None, files=None, match=util.always, fp=None, changes=None, opts=None): '''print diff of changes to files between two nodes, or node and working directory. if node1 is None, use first dirstate parent instead. if node2 is None, compare node1 with working directory.''' if opts is None: opts = mdiff.defaultopts if fp is None: fp = repo.ui if not node1: node1 = repo.dirstate.parents()[0] ccache = {} def getctx(r): if r not in ccache: ccache[r] = context.changectx(repo, r) return ccache[r] flcache = {} def getfilectx(f, ctx): flctx = ctx.filectx(f, filelog=flcache.get(f)) if f not in flcache: flcache[f] = flctx._filelog return flctx # reading the data for node1 early allows it to play nicely # with repo.status and the revlog cache. ctx1 = context.changectx(repo, node1) # force manifest reading man1 = ctx1.manifest() date1 = util.datestr(ctx1.date()) if not changes: changes = repo.status(node1, node2, files, match=match)[:5] modified, added, removed, deleted, unknown = changes if not modified and not added and not removed: return if node2: ctx2 = context.changectx(repo, node2) execf2 = ctx2.manifest().execf linkf2 = ctx2.manifest().linkf else: ctx2 = context.workingctx(repo) execf2 = util.execfunc(repo.root, None) linkf2 = util.linkfunc(repo.root, None) if execf2 is None: mc = ctx2.parents()[0].manifest().copy() execf2 = mc.execf linkf2 = mc.linkf if repo.ui.quiet: r = None else: hexfunc = repo.ui.debugflag and hex or short r = [hexfunc(node) for node in [node1, node2] if node] if opts.git: copy, diverge = copies.copies(repo, ctx1, ctx2, repo.changectx(nullid)) for k, v in copy.items(): copy[v] = k all = modified + added + removed all.sort() gone = {} for f in all: to = None tn = None dodiff = True header = [] if f in man1: to = getfilectx(f, ctx1).data() if f not in removed: tn = getfilectx(f, ctx2).data() a, b = f, f if opts.git: def gitmode(x, l): return l and '120000' or (x and '100755' or '100644') def addmodehdr(header, omode, nmode): if omode != nmode: header.append('old mode %s\n' % omode) header.append('new mode %s\n' % nmode) if f in added: mode = gitmode(execf2(f), linkf2(f)) if f in copy: a = copy[f] omode = gitmode(man1.execf(a), man1.linkf(a)) addmodehdr(header, omode, mode) if a in removed and a not in gone: op = 'rename' gone[a] = 1 else: op = 'copy' header.append('%s from %s\n' % (op, a)) header.append('%s to %s\n' % (op, f)) to = getfilectx(a, ctx1).data() else: header.append('new file mode %s\n' % mode) if util.binary(tn): dodiff = 'binary' elif f in removed: # have we already reported a copy above? if f in copy and copy[f] in added and copy[copy[f]] == f: dodiff = False else: mode = gitmode(man1.execf(f), man1.linkf(f)) header.append('deleted file mode %s\n' % mode) else: omode = gitmode(man1.execf(f), man1.linkf(f)) nmode = gitmode(execf2(f), linkf2(f)) addmodehdr(header, omode, nmode) if util.binary(to) or util.binary(tn): dodiff = 'binary' r = None header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) if dodiff: if dodiff == 'binary': text = b85diff(to, tn) else: text = mdiff.unidiff(to, date1, # ctx2 date may be dynamic tn, util.datestr(ctx2.date()), a, b, r, opts=opts) if text or len(header) > 1: fp.write(''.join(header)) fp.write(text)
def diff(repo, node1=None, node2=None, files=None, match=util.always, fp=None, changes=None, opts=None): '''print diff of changes to files between two nodes, or node and working directory. if node1 is None, use first dirstate parent instead. if node2 is None, compare node1 with working directory.''' if opts is None: opts = mdiff.defaultopts if fp is None: fp = repo.ui if not node1: node1 = repo.dirstate.parents()[0] ccache = {} def getctx(r): if r not in ccache: ccache[r] = context.changectx(repo, r) return ccache[r] flcache = {} def getfilectx(f, ctx): flctx = ctx.filectx(f, filelog=flcache.get(f)) if f not in flcache: flcache[f] = flctx._filelog return flctx # reading the data for node1 early allows it to play nicely # with repo.status and the revlog cache. ctx1 = context.changectx(repo, node1) # force manifest reading man1 = ctx1.manifest() date1 = util.datestr(ctx1.date()) if not changes: changes = repo.status(node1, node2, files, match=match)[:5] modified, added, removed, deleted, unknown = changes if not modified and not added and not removed: return if node2: ctx2 = context.changectx(repo, node2) execf2 = ctx2.manifest().execf linkf2 = ctx2.manifest().linkf else: ctx2 = context.workingctx(repo) execf2 = util.execfunc(repo.root, None) linkf2 = util.linkfunc(repo.root, None) if execf2 is None: mc = ctx2.parents()[0].manifest().copy() execf2 = mc.execf linkf2 = mc.linkf if repo.ui.quiet: r = None else: hexfunc = repo.ui.debugflag and hex or short r = [hexfunc(node) for node in [node1, node2] if node] if opts.git: copy, diverge = copies.copies(repo, ctx1, ctx2, repo.changectx(nullid)) for k, v in copy.items(): copy[v] = k all = modified + added + removed all.sort() gone = {} for f in all: to = None tn = None dodiff = True header = [] if f in man1: to = getfilectx(f, ctx1).data() if f not in removed: tn = getfilectx(f, ctx2).data() a, b = f, f if opts.git: def gitmode(x, l): return l and '120000' or (x and '100755' or '100644') def addmodehdr(header, omode, nmode): if omode != nmode: header.append('old mode %s\n' % omode) header.append('new mode %s\n' % nmode) if f in added: mode = gitmode(execf2(f), linkf2(f)) if f in copy: a = copy[f] omode = gitmode(man1.execf(a), man1.linkf(a)) addmodehdr(header, omode, mode) if a in removed and a not in gone: op = 'rename' gone[a] = 1 else: op = 'copy' header.append('%s from %s\n' % (op, a)) header.append('%s to %s\n' % (op, f)) to = getfilectx(a, ctx1).data() else: header.append('new file mode %s\n' % mode) if util.binary(tn): dodiff = 'binary' elif f in removed: # have we already reported a copy above? if f in copy and copy[f] in added and copy[copy[f]] == f: dodiff = False else: mode = gitmode(man1.execf(f), man1.linkf(f)) header.append('deleted file mode %s\n' % mode) else: omode = gitmode(man1.execf(f), man1.linkf(f)) nmode = gitmode(execf2(f), linkf2(f)) addmodehdr(header, omode, nmode) if util.binary(to) or util.binary(tn): dodiff = 'binary' r = None header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) if dodiff: if dodiff == 'binary': text = b85diff(to, tn) else: text = mdiff.unidiff( to, date1, # ctx2 date may be dynamic tn, util.datestr(ctx2.date()), a, b, r, opts=opts) if text or len(header) > 1: fp.write(''.join(header)) fp.write(text)
def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None): """yields diff of changes to files between two nodes, or node and working directory. if node1 is None, use first dirstate parent instead. if node2 is None, compare node1 with working directory.""" if opts is None: opts = mdiff.defaultopts if not node1: node1 = repo.dirstate.parents()[0] flcache = {} def getfilectx(f, ctx): flctx = ctx.filectx(f, filelog=flcache.get(f)) if f not in flcache: flcache[f] = flctx._filelog return flctx ctx1 = repo[node1] ctx2 = repo[node2] if not changes: changes = repo.status(ctx1, ctx2, match=match) modified, added, removed = changes[:3] if not modified and not added and not removed: return date1 = util.datestr(ctx1.date()) man1 = ctx1.manifest() if repo.ui.quiet: r = None else: hexfunc = repo.ui.debugflag and hex or short r = [hexfunc(node) for node in [node1, node2] if node] if opts.git: copy, diverge = copies.copies(repo, ctx1, ctx2, repo[nullid]) for k, v in copy.items(): copy[v] = k gone = {} gitmode = {"l": "120000", "x": "100755", "": "100644"} for f in util.sort(modified + added + removed): to = None tn = None dodiff = True header = [] if f in man1: to = getfilectx(f, ctx1).data() if f not in removed: tn = getfilectx(f, ctx2).data() a, b = f, f if opts.git: if f in added: mode = gitmode[ctx2.flags(f)] if f in copy: a = copy[f] omode = gitmode[man1.flags(a)] _addmodehdr(header, omode, mode) if a in removed and a not in gone: op = "rename" gone[a] = 1 else: op = "copy" header.append("%s from %s\n" % (op, a)) header.append("%s to %s\n" % (op, f)) to = getfilectx(a, ctx1).data() else: header.append("new file mode %s\n" % mode) if util.binary(tn): dodiff = "binary" elif f in removed: # have we already reported a copy above? if f in copy and copy[f] in added and copy[copy[f]] == f: dodiff = False else: header.append("deleted file mode %s\n" % gitmode[man1.flags(f)]) else: omode = gitmode[man1.flags(f)] nmode = gitmode[ctx2.flags(f)] _addmodehdr(header, omode, nmode) if util.binary(to) or util.binary(tn): dodiff = "binary" r = None header.insert(0, mdiff.diffline(r, a, b, opts)) if dodiff: if dodiff == "binary": text = b85diff(to, tn) else: text = mdiff.unidiff( to, date1, # ctx2 date may be dynamic tn, util.datestr(ctx2.date()), a, b, r, opts=opts, ) if header and (text or len(header) > 1): yield "".join(header) if text: yield text