def get_diffs(self): from mercurial import mdiff, util, patch from repo_browser.integration import Diff ctx = self.ctx parent = ctx.parents()[0] parent_date = util.datestr(parent.date()) this_date = util.datestr(ctx.date()) diffopts = patch.diffopts(self.repo.repo.ui, untrusted=True) # Returns a tuple of modified, added, removed, deleted, unknown # TODO: look up in the api what FIXME* are modified, added, removed, deleted, unknown, FIXME, FIXME2 = \ self.repo.repo.status( parent.node(), ctx.node(),) for modified_file in modified: filectx = ctx.filectx(modified_file) parent_filectx = parent.filectx(modified_file) this_data = filectx.data() parent_data = parent_filectx.data() yield Diff( mdiff.unidiff(parent_data, parent_date, this_data, this_date, modified_file, modified_file, opts=diffopts)) for added_file in added: filectx = ctx.filectx(added_file) this_data = filectx.data() yield Diff( mdiff.unidiff(None, parent_date, this_data, this_date, added_file, added_file, opts=diffopts)) for removed_file in removed: parent_filectx = parent.filectx(removed_file) parent_data = parent_filectx.data() yield Diff( mdiff.unidiff(parent_data, parent_date, None, ctx.date(), removed_file, removed_file, opts=diffopts))
def get_diffs(self): from mercurial import mdiff, util, patch from repo_browser.integration import Diff ctx = self.ctx parent = ctx.parents()[0] parent_date = util.datestr(parent.date()) this_date = util.datestr(ctx.date()) diffopts = patch.diffopts(self.repo.repo.ui, untrusted=True) # Returns a tuple of modified, added, removed, deleted, unknown # TODO: look up in the api what FIXME* are modified, added, removed, deleted, unknown, FIXME, FIXME2 = \ self.repo.repo.status( parent.node(), ctx.node(),) for modified_file in modified: filectx = ctx.filectx(modified_file) parent_filectx = parent.filectx(modified_file) this_data = filectx.data() parent_data = parent_filectx.data() yield Diff(mdiff.unidiff(parent_data, parent_date, this_data,this_date, modified_file, modified_file, opts=diffopts)) for added_file in added: filectx = ctx.filectx(added_file) this_data = filectx.data() yield Diff(mdiff.unidiff( None, parent_date, this_data, this_date, added_file, added_file, opts=diffopts)) for removed_file in removed: parent_filectx = parent.filectx(removed_file) parent_data = parent_filectx.data() yield Diff(mdiff.unidiff( parent_data, parent_date, None, ctx.date(), removed_file, removed_file, opts=diffopts))
def showDiff(self, index): 'User selected a row in the candidate tree' indexes = index.indexes() if not indexes: return index = indexes[0] ctx = self.repo['.'] hu = htmlui.htmlui() row = self.matchtv.model().getRow(index) src, dest, percent = self.matchtv.model().getRow(index) aa = self.repo.wread(dest) rr = ctx.filectx(src).data() date = hglib.displaytime(ctx.date()) difftext = mdiff.unidiff(rr, date, aa, date, src, dest, None) if not difftext: t = _('%s and %s have identical contents\n\n') % \ (hglib.tounicode(src), hglib.tounicode(dest)) hu.write(t, label='ui.error') else: for t, l in patch.difflabel(difftext.splitlines, True): hu.write(t, label=l) self.difftb.setHtml(hu.getdata()[0])
def dirtywork(f, mmap1, mmap2): lines = 0 to = mmap1 and repo.file(f).read(mmap1[f]) or None tn = mmap2 and repo.file(f).read(mmap2[f]) or None diff = mdiff.unidiff(to, "", tn, "", f, f).split("\n") for line in diff: if not line: continue # skip EOF if line.startswith(" "): continue # context line if line.startswith("--- ") or line.startswith("+++ "): continue # begining of diff if line.startswith("@@ "): continue # info line # changed lines lines += 1 return lines
def show_diff(self, selection): 'User selected a row in the candidate tree' hglib.invalidaterepo(self.repo) model, cpaths = selection.get_selected_rows() sensitive = cpaths and True or False self.acceptbtn.set_sensitive(sensitive) self.buf.set_text('') bufiter = self.buf.get_start_iter() for path in cpaths: row = model[path] src, usrc, dest, udest, percent, sensitive = row if not sensitive: continue ctx = self.repo['.'] aa = self.repo.wread(dest) rr = ctx.filectx(src).data() opts = mdiff.defaultopts difftext = mdiff.unidiff(rr, '', aa, '', src, dest, None, opts=opts) if not difftext: l = _('== %s and %s have identical contents ==\n\n') % (src, dest) self.buf.insert(bufiter, l) continue difflines = difftext.splitlines(True) for line in difflines: line = hglib.toutf(line) if line.startswith('---') or line.startswith('+++'): self.buf.insert_with_tags_by_name(bufiter, line, 'header') elif line.startswith('-'): line = hglib.diffexpand(line) self.buf.insert_with_tags_by_name(bufiter, line, 'removed') elif line.startswith('+'): line = hglib.diffexpand(line) self.buf.insert_with_tags_by_name(bufiter, line, 'added') elif line.startswith('@@'): self.buf.insert_with_tags_by_name(bufiter, line, 'position') else: line = hglib.diffexpand(line) self.buf.insert(bufiter, line)
def unidifftext(a, ad, b, bd, fn1, fn2, opts=mdiff.defaultopts): headers, hunks = mdiff.unidiff(a, ad, b, bd, fn1, fn2, opts) text = ''.join(sum((list(hlines) for _hrange, hlines in hunks), [])) return '\n'.join(headers) + '\n' + text
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 = 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.changectx(node1) c2 = r.changectx(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)) diffopts = patch.diffopts(self.repo.ui, untrusted=True) for f in modified: to = c1.filectx(f).data() tn = c2.filectx(f).data() yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f, opts=diffopts), f, tn) for f in added: to = None tn = c2.filectx(f).data() yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f, opts=diffopts), f, tn) for f in removed: to = c1.filectx(f).data() tn = None yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f, opts=diffopts), f, tn)
renamed = fctx.renamed() if not renamed: self.flabel += _(' <i>(was added)</i>') return oldname, node = renamed fr = hglib.tounicode(oldname) self.flabel += _(' <i>(renamed from %s)</i>') % fr olddata = repo.filectx(oldname, fileid=node).data() elif status == 'M': if wfile not in ctx2: # merge situation where file was added in other branch self.flabel += _(' <i>(was added)</i>') return oldname = wfile olddata = ctx2[wfile].data() else: return self.olddata = olddata newdate = util.datestr(ctx.date()) olddate = util.datestr(ctx2.date()) revs = [str(ctx), str(ctx2)] diffopts = patch.diffopts(repo.ui, {}) diffopts.git = False if isbfile: olddata += '\0' newdata += '\0' self.diff = mdiff.unidiff(olddata, olddate, newdata, newdate, oldname, wfile, revs, diffopts)
self.diff = '' return self.changes.excludecount = 0 values = [] lines = 0 for chunk in self.changes.hunks: buf = cStringIO.StringIO() chunk.write(buf) chunk.excluded = False val = buf.getvalue() values.append(val) chunk.lineno = lines chunk.linecount = len(val.splitlines()) lines += chunk.linecount self.diff = ''.join(values) else: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = False newdate = util.datestr(ctx.date()) olddate = util.datestr(ctx2.date()) if isbfile: olddata += '\0' newdata += '\0' difftext = mdiff.unidiff(olddata, olddate, newdata, newdate, oldname, wfile, opts=diffopts) if difftext: self.diff = ('diff -r %s -r %s %s\n' % (ctx, ctx2, oldname) + difftext) else: self.diff = ''
def _readStatus(self, ctx, ctx2, wfile, status, changeselect, force): def getstatus(repo, n1, n2, wfile): m = match.exact(repo.root, repo.getcwd(), [wfile]) modified, added, removed = repo.status(n1, n2, match=m)[:3] if wfile in modified: return 'M' if wfile in added: return 'A' if wfile in removed: return 'R' if wfile in ctx: return 'C' return None isbfile = False repo = ctx._repo maxdiff = repo.maxdiff self.flabel = u'<b>%s</b>' % self.filePath() if ctx2: # If a revision to compare to was provided, we must put it in # the context of the subrepo as well if ctx2._repo.root != ctx._repo.root: wsub2, wfileinsub2, sctx2 = \ hglib.getDeepestSubrepoContainingFile(wfile, ctx2) if wsub2: ctx2 = sctx2 absfile = repo.wjoin(wfile) if (wfile in ctx and 'l' in ctx.flags(wfile)) or \ os.path.islink(absfile): if wfile in ctx: data = ctx[wfile].data() else: data = os.readlink(absfile) self.contents = data self.flabel += _(' <i>(is a symlink)</i>') return if ctx2 is None: ctx2 = ctx.p1() if status is None: status = getstatus(repo, ctx2.node(), ctx.node(), wfile) mde = _('File or diffs not displayed: ' 'File is larger than the specified max size.\n' 'maxdiff = %s KB') % (maxdiff // 1024) if status in ('R', '!'): if wfile in ctx.p1(): fctx = ctx.p1()[wfile] if fctx._filelog.rawsize(fctx.filerev()) > maxdiff: self.error = mde else: olddata = fctx.data() if '\0' in olddata: self.error = 'binary file' else: self.contents = olddata self.flabel += _(' <i>(was deleted)</i>') elif hasattr(ctx.p1(), 'hasStandin') and ctx.p1().hasStandin(wfile): self.error = 'binary file' self.flabel += _(' <i>(was deleted)</i>') else: self.flabel += _(' <i>(was added, now missing)</i>') return if status in ('I', '?'): assert ctx.rev() is None self.flabel += _(' <i>(is unversioned)</i>') if os.path.getsize(absfile) > maxdiff: self.error = mde return data = util.posixfile(absfile, 'r').read() if not force and '\0' in data: self.error = 'binary file' else: self.contents = data return if status in ('M', 'A', 'C'): if ctx.hasStandin(wfile): wfile = ctx.findStandin(wfile) isbfile = True try: fctx, newdata = self._checkMaxDiff(ctx, wfile, maxdiff, force) except _BadContent: if status == 'A': self._checkRenamed(repo, ctx, ctx2, wfile) raise self.contents = newdata if status == 'C': # no further comparison is necessary return for pctx in ctx.parents(): if 'x' in fctx.flags() and 'x' not in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>set</font>") elif 'x' not in fctx.flags() and 'x' in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>unset</font>") if status == 'A': oldname = self._checkRenamed(repo, ctx, ctx2, wfile) if not oldname: return olddata = ctx2[oldname].data() elif status == 'M': if wfile not in ctx2: # merge situation where file was added in other branch self.flabel += _(' <i>(was added)</i>') return oldname = wfile olddata = ctx2[wfile].data() else: return self.olddata = olddata if changeselect: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = True m = match.exact(repo.root, repo.root, [wfile]) fp = cStringIO.StringIO() for c in patch.diff(repo, ctx.node(), None, match=m, opts=diffopts): fp.write(c) fp.seek(0) # feed diffs through parsepatch() for more fine grained # chunk selection filediffs = patch.parsepatch(fp) if filediffs and filediffs[0].hunks: self.changes = filediffs[0] else: self.diff = '' return self.changes.excludecount = 0 values = [] lines = 0 for chunk in self.changes.hunks: buf = cStringIO.StringIO() chunk.write(buf) chunk.excluded = False val = buf.getvalue() values.append(val) chunk.lineno = lines chunk.linecount = len(val.splitlines()) lines += chunk.linecount self.diff = ''.join(values) else: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = False newdate = util.datestr(ctx.date()) olddate = util.datestr(ctx2.date()) if isbfile: olddata += '\0' newdata += '\0' difftext = mdiff.unidiff(olddata, olddate, newdata, newdate, oldname, wfile, opts=diffopts) if difftext: self.diff = ('diff -r %s -r %s %s\n' % (ctx, ctx2, oldname) + difftext) else: self.diff = ''