예제 #1
0
 def _updateannotation(self, ctx, filename):
     if ctx.rev() is None:
         return
     wsub, filename, ctx = hglib.getDeepestSubrepoContainingFile(filename, ctx)
     if wsub is None:
         # The file was not found in the repo context or its subrepos
         # This may happen for files that have been removed
         return
     self.ctx = ctx
     self.annfile = filename
     self._thread.abort()
     self._thread.start(ctx[filename])
예제 #2
0
 def _updateannotation(self, ctx, filename):
     if ctx.rev() is None:
         return
     wsub, filename, ctx = hglib.getDeepestSubrepoContainingFile(filename, ctx)
     if wsub is None:
         # The file was not found in the repo context or its subrepos
         # This may happen for files that have been removed
         return
     self.ctx = ctx
     self.annfile = filename
     self._thread.abort()
     self._thread.start(ctx[filename])
예제 #3
0
    def _findsub(self, paths):
        """Find the nearest (sub-)repository for the given paths

        All paths should be in the same repository. Otherwise, unmatched
        paths are silently omitted.
        """
        if not paths:
            return self.repo, [], self.ctx.rev()

        repopath, _relpath, ctx = hglib.getDeepestSubrepoContainingFile(
            paths[0], self.ctx)
        if not repopath:
            return self.repo, paths, self.ctx.rev()

        repo = thgrepo.repository(self.repo.ui, self.repo.wjoin(repopath))
        pfx = repopath + '/'
        relpaths = [e[len(pfx):] for e in paths if e.startswith(pfx)]
        return repo, relpaths, ctx.rev()
예제 #4
0
    def _findsub(self, paths):
        """Find the nearest (sub-)repository for the given paths

        All paths should be in the same repository. Otherwise, unmatched
        paths are silently omitted.
        """
        if not paths:
            return self.repo, [], self.ctx.rev()

        repopath, _relpath, ctx = hglib.getDeepestSubrepoContainingFile(
            paths[0], self.ctx)
        if not repopath:
            return self.repo, paths, self.ctx.rev()

        repo = thgrepo.repository(self.repo.ui, self.repo.wjoin(repopath))
        pfx = repopath + '/'
        relpaths = [e[len(pfx):] for e in paths if e.startswith(pfx)]
        return repo, relpaths, ctx.rev()
예제 #5
0
    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()

            copy = {}
            if oldname != wfile:
                copy[wfile] = oldname
            patches = patch.diff(repo, ctx.node(), None, match=m,
                                 opts=diffopts, copy=copy)

            for c in patches:
                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 = hglib.unidifftext(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 = ''
예제 #6
0
    def readStatus(self, ctx, ctx2, wfile, status):
        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
        self.flabel += u'<b>%s</b>' % hglib.tounicode(wfile)

        if isinstance(ctx, patchctx.patchctx):
            self.diff = ctx.thgmqpatchdata(wfile)
            flags = ctx.flags(wfile)
            if flags == 'x':
                self.elabel = _(
                    "exec mode has been <font color='red'>set</font>")
            elif flags == '-':
                self.elabel = _(
                    "exec mode has been <font color='red'>unset</font>")
            elif flags == 'l':
                self.flabel += _(' <i>(is a symlink)</i>')
            return

        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 status is None:
            status = getstatus(repo, ctx.p1().node(), ctx.node(), wfile)
        if ctx2 is None:
            ctx2 = ctx.p1()

        if status == 'S':
            try:
                from mercurial import subrepo, commands

                def genSubrepoRevChangedDescription(subrelpath, sfrom, sto,
                                                    repo):
                    """Generate a subrepository revision change description"""
                    out = []

                    def getLog(_ui, srepo, opts):
                        _ui.pushbuffer()
                        try:
                            commands.log(_ui, srepo, **opts)
                            logOutput = _ui.popbuffer()
                        except error.ParseError, e:
                            # Some mercurial versions have a bug that results in
                            # saving a subrepo node id in the .hgsubstate file
                            # which ends with a "+" character. If that is the
                            # case, add a warning to the output, but try to
                            # get the revision information anyway
                            logOutput = ''
                            for n, rev in enumerate(opts['rev']):
                                if rev.endswith('+'):
                                    logOutput += _(
                                        '[WARNING] Invalid subrepo '
                                        'revision ID:\n\t%s\n\n') % rev
                                    opts['rev'][n] = rev[:-1]
                            commands.log(_ui, srepo, **opts)
                            logOutput += _ui.popbuffer()
                        return logOutput

                    opts = {'date': None, 'user': None, 'rev': [sfrom]}
                    subabspath = os.path.join(repo.root, subrelpath)
                    missingsub = not os.path.isdir(subabspath)
                    incompletesub = False
                    sfromlog = ''

                    def isinitialrevision(rev):
                        return all([el == '0' for el in rev])

                    if isinitialrevision(sfrom):
                        sfrom = ''
                    if isinitialrevision(sto):
                        sto = ''
                    if not sfrom and not sto:
                        sstatedesc = 'new'
                        out.append(
                            _('Subrepo created and set to initial revision.') +
                            u'\n\n')
                        return out, sstatedesc
                    elif not sfrom:
                        sstatedesc = 'new'
                        out.append(
                            _('Subrepo initialized to revision:') + u'\n\n')
                    elif not sto:
                        sstatedesc = 'removed'
                        out.append(
                            _('Subrepo removed from repository.') + u'\n\n')
                        return out, sstatedesc
                    elif sfrom == sto:
                        sstatedesc = 'unchanged'
                        out.append(_('Subrepo was not changed.') + u'\n\n')
                        out.append(_('Subrepo state is:') + u'\n\n')
                        if missingsub:
                            out.append(_('changeset: %s') % sfrom + u'\n')
                        else:
                            out.append(
                                hglib.tounicode(getLog(_ui, srepo, opts)))
                        return out, sstatedesc
                    else:
                        sstatedesc = 'changed'

                        out.append(_('Revision has changed to:') + u'\n\n')

                        if missingsub:
                            sfromlog = _('changeset: %s') % sfrom + u'\n\n'
                        else:
                            sfromlog = hglib.tounicode(getLog(
                                _ui, srepo, opts))
                            if not sfromlog:
                                incompletesub = True
                                sfromlog = _('changeset: %s') % sfrom + u'\n\n'
                        sfromlog = _('From:') + u'\n' + sfromlog

                    if missingsub:
                        stolog = _('changeset: %s') % sto + '\n\n'
                        sfromlog += _('Subrepository not found in the working '
                                      'directory.') + '\n'
                        sfromlog += _(
                            'Further subrepository revision '
                            'information cannot be retrieved.') + '\n'
                    elif incompletesub:
                        stolog = _('changeset: %s') % sto + '\n\n'
                        sfromlog += _('Subrepository is either damaged or '
                                      'missing some revisions') + '\n'
                        sfromlog += _(
                            'Further subrepository revision '
                            'information cannot be retrieved.') + '\n'
                        sfromlog += _('You may need to open the missing '
                                      'subrepository and manually\n'
                                      'pull the missing revisions from its '
                                      'source repository.') + '\n'
                    else:
                        opts['rev'] = [sto]
                        stolog = getLog(_ui, srepo, opts)

                    if not stolog:
                        stolog = _('Initial revision') + u'\n'
                    out.append(hglib.tounicode(stolog))

                    if sfromlog:
                        out.append(hglib.tounicode(sfromlog))

                    return out, sstatedesc

                srev = ctx.substate.get(wfile, subrepo.nullstate)[1]
                srepo = None
                try:
                    subabspath = os.path.join(ctx._repo.root, wfile)
                    if not os.path.isdir(subabspath):
                        sactual = ''
                    else:
                        sub = ctx.sub(wfile)
                        if isinstance(sub, subrepo.hgsubrepo):
                            srepo = sub._repo
                            sactual = srepo['.'].hex()
                        else:
                            self.error = _(
                                'Not a Mercurial subrepo, not previewable')
                            return
                except (util.Abort, KeyError), e:
                    sactual = ''

                out = []
                _ui = uimod.ui()

                if srepo is None or ctx.rev() is not None:
                    data = []
                else:
                    _ui.pushbuffer()
                    commands.status(_ui,
                                    srepo,
                                    modified=True,
                                    added=True,
                                    removed=True,
                                    deleted=True)
                    data = _ui.popbuffer()
                    if data:
                        out.append(
                            _('The subrepository is dirty.') + u' ' +
                            _('File Status:') + u'\n')
                        out.append(hglib.tounicode(data))
                        out.append(u'\n')

                sstatedesc = 'changed'
                if ctx.rev() is not None:
                    sparent = ctx.p1().substate.get(wfile,
                                                    subrepo.nullstate)[1]
                    subrepochange, sstatedesc = \
                        genSubrepoRevChangedDescription(wfile,
                            sparent, srev, ctx._repo)
                    out += subrepochange
                else:
                    sstatedesc = 'dirty'
                    if srev != sactual:
                        subrepochange, sstatedesc = \
                            genSubrepoRevChangedDescription(wfile,
                                srev, sactual, ctx._repo)
                        out += subrepochange
                        if data:
                            sstatedesc += ' and dirty'
                    elif srev and not sactual:
                        sstatedesc = 'removed'
                self.ucontents = u''.join(out).strip()

                lbl = {
                    'changed':
                    _('(is a changed sub-repository)'),
                    'unchanged':
                    _('(is an unchanged sub-repository)'),
                    'dirty':
                    _('(is a dirty sub-repository)'),
                    'new':
                    _('(is a new sub-repository)'),
                    'removed':
                    _('(is a removed sub-repository)'),
                    'changed and dirty':
                    _('(is a changed and dirty sub-repository)'),
                    'new and dirty':
                    _('(is a new and dirty sub-repository)'),
                    'removed and dirty':
                    _('(is a removed sub-repository)')
                }[sstatedesc]
                self.flabel += ' <i>' + lbl + '</i>'
                if sactual:
                    lbl = _(' <a href="subrepo:%s">open...</a>')
                    self.flabel += lbl % hglib.tounicode(srepo.root)
예제 #7
0
    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>' % hglib.tounicode(wfile)

        if isinstance(ctx, patchctx.patchctx):
            self.diff = ctx.thgmqpatchdata(wfile)
            flags = ctx.flags(wfile)
            if flags == 'x':
                self.elabel = _("exec mode has been <font color='red'>set</font>")
            elif flags == '-':
                self.elabel = _("exec mode has been <font color='red'>unset</font>")
            elif flags == 'l':
                self.flabel += _(' <i>(is a symlink)</i>')

            # Do not show patches that are too big or may be binary
            if not force:
                p = _('Diff not displayed: ')
                data = self.diff
                size = len(data)
                if (size > maxdiff):
                    self.error = p + _('File is larger than the specified max size.\n'
                                   'maxdiff = %s KB') % (maxdiff // 1024)
                elif '\0' in data:
                    self.error = p + _('File is binary')
                elif _exceedsMaxLineLength(data):
                    # it's incredibly slow to render long line by QScintilla
                    self.error = p + \
                        _('File may be binary (maximum line length exceeded)')
                if self.error:
                    self.error += u'\n\n' + forcedisplaymsg

            return

        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 status is None:
            status = getstatus(repo, ctx.p1().node(), ctx.node(), wfile)
        if ctx2 is None:
            ctx2 = ctx.p1()

        if status == 'S':
            try:
                from mercurial import subrepo, commands

                def genSubrepoRevChangedDescription(subrelpath, sfrom, sto, repo):
                    """Generate a subrepository revision change description"""
                    out = []
                    def getLog(_ui, srepo, opts):
                        _ui.pushbuffer()
                        try:
                            commands.log(_ui, srepo, **opts)
                            logOutput = _ui.popbuffer()
                        except error.ParseError, e:
                            # Some mercurial versions have a bug that results in
                            # saving a subrepo node id in the .hgsubstate file
                            # which ends with a "+" character. If that is the
                            # case, add a warning to the output, but try to
                            # get the revision information anyway
                            logOutput = ''
                            for n, rev in enumerate(opts['rev']):
                                if rev.endswith('+'):
                                    logOutput += _('[WARNING] Invalid subrepo '
                                        'revision ID:\n\t%s\n\n') % rev
                                    opts['rev'][n] = rev[:-1]
                            commands.log(_ui, srepo, **opts)
                            logOutput += _ui.popbuffer()
                        return logOutput

                    opts = {'date':None, 'user':None, 'rev':[sfrom]}
                    subabspath = os.path.join(repo.root, subrelpath)
                    missingsub = not os.path.isdir(subabspath)
                    incompletesub = False
                    sfromlog = ''
                    def isinitialrevision(rev):
                        return all([el == '0' for el in rev])
                    if isinitialrevision(sfrom):
                        sfrom = ''
                    if isinitialrevision(sto):
                        sto = ''
                    if not sfrom and not sto:
                        sstatedesc = 'new'
                        out.append(_('Subrepo created and set to initial revision.') + u'\n\n')
                        return out, sstatedesc
                    elif not sfrom:
                        sstatedesc = 'new'
                        out.append(_('Subrepo initialized to revision:') + u'\n\n')
                    elif not sto:
                        sstatedesc = 'removed'
                        out.append(_('Subrepo removed from repository.') + u'\n\n')
                        return out, sstatedesc
                    elif sfrom == sto:
                        sstatedesc = 'unchanged'
                        out.append(_('Subrepo was not changed.') + u'\n\n')
                        out.append(_('Subrepo state is:') + u'\n\n')
                        if missingsub:
                            out.append(_('changeset: %s') % sfrom + u'\n')
                        else:
                            out.append(hglib.tounicode(getLog(_ui, srepo, opts)))
                        return out, sstatedesc
                    else:
                        sstatedesc = 'changed'

                        out.append(_('Revision has changed to:') + u'\n\n')

                        if missingsub:
                            sfromlog = _('changeset: %s') % sfrom + u'\n\n'
                        else:
                            sfromlog = hglib.tounicode(getLog(_ui, srepo, opts))
                            if not sfromlog:
                                incompletesub = True
                                sfromlog = _('changeset: %s') % sfrom + u'\n\n'
                        sfromlog = _('From:') + u'\n' + sfromlog

                    if missingsub:
                        stolog = _('changeset: %s') % sto + '\n\n'
                        sfromlog += _('Subrepository not found in the working '
                            'directory.') + '\n'
                        sfromlog += _('Further subrepository revision '
                            'information cannot be retrieved.') + '\n'
                    elif incompletesub:
                        stolog = _('changeset: %s') % sto + '\n\n'
                        sfromlog += _('Subrepository is either damaged or '
                            'missing some revisions') + '\n'
                        sfromlog += _('Further subrepository revision '
                            'information cannot be retrieved.') + '\n'
                        sfromlog += _('You may need to open the missing '
                            'subrepository and manually\n'
                            'pull the missing revisions from its '
                            'source repository.') + '\n'
                    else:
                        opts['rev'] = [sto]
                        stolog = getLog(_ui, srepo, opts)

                    if not stolog:
                        stolog = _('Initial revision') + u'\n'
                    out.append(hglib.tounicode(stolog))

                    if sfromlog:
                        out.append(hglib.tounicode(sfromlog))

                    return out, sstatedesc

                srev = ctx.substate.get(wfile, subrepo.nullstate)[1]
                srepo = None
                try:
                    subabspath = os.path.join(ctx._repo.root, wfile)
                    if not os.path.isdir(subabspath):
                        sactual = ''
                    else:
                        sub = ctx.sub(wfile)
                        if isinstance(sub, subrepo.hgsubrepo):
                            srepo = sub._repo
                            sactual = srepo['.'].hex()
                        else:
                            self.error = _('Not a Mercurial subrepo, not previewable')
                            return
                except (util.Abort, KeyError), e:
                    self.error = (_('Error previewing subrepo: %s')
                                  % hglib.tounicode(str(e)))
                    return

                out = []
                _ui = uimod.ui()

                if srepo is None or ctx.rev() is not None:
                    data = []
                else:
                    _ui.pushbuffer()
                    commands.status(_ui, srepo, modified=True, added=True, removed=True, deleted=True)
                    data = _ui.popbuffer()
                    if data:
                        out.append(_('The subrepository is dirty.') + u' ' + _('File Status:') + u'\n')
                        out.append(hglib.tounicode(data))
                        out.append(u'\n')

                sstatedesc = 'changed'
                if ctx.rev() is not None:
                    sparent = ctx.p1().substate.get(wfile, subrepo.nullstate)[1]
                    subrepochange, sstatedesc = \
                        genSubrepoRevChangedDescription(wfile,
                            sparent, srev, ctx._repo)
                    out += subrepochange
                else:
                    sstatedesc = 'dirty'
                    if srev != sactual:
                        subrepochange, sstatedesc = \
                            genSubrepoRevChangedDescription(wfile,
                                srev, sactual, ctx._repo)
                        out += subrepochange
                        if data:
                            sstatedesc += ' and dirty'
                    elif srev and not sactual:
                        sstatedesc = 'removed'
                self.ucontents = u''.join(out).strip()

                lbl = {
                    'changed':   _('(is a changed sub-repository)'),
                    'unchanged':   _('(is an unchanged sub-repository)'),
                    'dirty':   _('(is a dirty sub-repository)'),
                    'new':   _('(is a new sub-repository)'),
                    'removed':   _('(is a removed sub-repository)'),
                    'changed and dirty':   _('(is a changed and dirty sub-repository)'),
                    'new and dirty':   _('(is a new and dirty sub-repository)'),
                    'removed and dirty':   _('(is a removed sub-repository)')
                }[sstatedesc]
                self.flabel += ' <i>' + lbl + '</i>'
                if sactual:
                    lbl = ' <a href="repo:%%s">%s</a>' % _('open...')
                    self.flabel += lbl % hglib.tounicode(srepo.root)
예제 #8
0
    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 = ''