def diff_app(request): # XXX TODO: error handling if 'repo' not in request.GET: raise Http404("repo must be supplied") reponame = request.GET['repo'] repopath = settings.REPOSITORY_BASE + '/' + reponame repo_url = Repository.objects.filter(name=reponame).values_list('url', flat=True)[0] from mercurial.ui import ui as _ui from mercurial.hg import repository ui = _ui() repo = repository(ui, repopath) ctx1 = repo.changectx(request.GET['from']) ctx2 = repo.changectx(request.GET['to']) match = None # maybe get something from l10n.ini and cmdutil changed, added, removed = repo.status(ctx1, ctx2, match=match)[:3] paths = ([(f, 'changed') for f in changed] + [(f, 'removed') for f in removed] + [(f, 'added') for f in added]) diffs = DataTree(dict) for path, action in paths: lines = [] try: p = getParser(path) except UserWarning: diffs[path].update({'path': path, 'isFile': True, 'rev': ((action == 'removed') and request.GET['from'] or request.GET['to']), 'class': action}) continue if action == 'added': a_entities = [] a_map = {} else: data = ctx1.filectx(path).data() data = _universal_newlines(data) try: p.readContents(data) a_entities, a_map = p.parse() except: diffs[path].update({'path': path, 'isFile': True, 'rev': ((action == 'removed') and request.GET['from'] or request.GET['to']), 'class': action}) continue if action == 'removed': c_entities = [] c_map = {} else: data = ctx2.filectx(path).data() data = _universal_newlines(data) try: p.readContents(data) c_entities, c_map = p.parse() except: diffs[path].update({'path': path, 'isFile': True, 'rev': ((action == 'removed') and request.GET['from'] or request.GET['to']), 'class': action}) continue a_list = sorted(a_map.keys()) c_list = sorted(c_map.keys()) ar = AddRemove() ar.set_left(a_list) ar.set_right(c_list) for action, item_or_pair in ar: if action == 'delete': lines.append({'class': 'removed', 'oldval': [{'value':a_entities[a_map[item_or_pair]].val}], 'newval': '', 'entity': item_or_pair}) elif action == 'add': lines.append({'class': 'added', 'oldval': '', 'newval':[{'value': c_entities[c_map[item_or_pair]].val}], 'entity': item_or_pair}) else: oldval = a_entities[a_map[item_or_pair[0]]].val newval = c_entities[c_map[item_or_pair[1]]].val if oldval == newval: continue sm = SequenceMatcher(None, oldval, newval) oldhtml = [] newhtml = [] for op, o1, o2, n1, n2 in sm.get_opcodes(): if o1 != o2: oldhtml.append({'class':op, 'value':oldval[o1:o2]}) if n1 != n2: newhtml.append({'class':op, 'value':newval[n1:n2]}) lines.append({'class':'changed', 'oldval': oldhtml, 'newval': newhtml, 'entity': item_or_pair[0]}) container_class = lines and 'file' or 'empty-diff' diffs[path].update({'path': path, 'class': container_class, 'lines': lines}) diffs = diffs.toJSON().get('children', []) return render_to_response('shipping/diff.html', {'given_title': request.GET.get('title', None), 'repo': reponame, 'repo_url': repo_url, 'old_rev': request.GET['from'], 'new_rev': request.GET['to'], 'diffs': diffs}, context_instance=RequestContext(request))
def diffLines(self, path, action): lines = [] try: p = getParser(path) except UserWarning: return None if action == 'added': a_entities = [] a_map = {} else: realpath = (action == 'moved' and self.moved[path] or action == 'copied' and self.copied[path] or path) data = self.ctx1.filectx(realpath).data() data = self._universal_newlines(data) try: p.readContents(data) a_entities, a_map = p.parse() except: # consider doing something like: # logging.warn('Unable to parse %s', path, exc_info=True) return None if action == 'removed': c_entities, c_map = [], {} else: data = self.ctx2.filectx(path).data() data = self._universal_newlines(data) try: p.readContents(data) c_entities, c_map = p.parse() except: # consider doing something like: # logging.warn('Unable to parse %s', path, exc_info=True) return None a_list = sorted(a_map.keys()) c_list = sorted(c_map.keys()) ar = AddRemove() ar.set_left(a_list) ar.set_right(c_list) for action, item_or_pair in ar: if action == 'delete': lines.append({ 'class': 'removed', 'oldval': [{ 'value': a_entities[a_map[item_or_pair]].val }], 'newval': '', 'entity': item_or_pair }) elif action == 'add': lines.append({ 'class': 'added', 'oldval': '', 'newval': [{ 'value': c_entities[c_map[item_or_pair]].val }], 'entity': item_or_pair }) else: oldval = a_entities[a_map[item_or_pair[0]]].val newval = c_entities[c_map[item_or_pair[1]]].val if oldval == newval: continue sm = SequenceMatcher(None, oldval, newval) oldhtml = [] newhtml = [] for op, o1, o2, n1, n2 in sm.get_opcodes(): if o1 != o2: oldhtml.append({'class': op, 'value': oldval[o1:o2]}) if n1 != n2: newhtml.append({'class': op, 'value': newval[n1:n2]}) lines.append({ 'class': 'changed', 'oldval': oldhtml, 'newval': newhtml, 'entity': item_or_pair[0] }) return lines