Example #1
0
def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False):
    '''Read tag definitions from a file (or any source of lines).

    This function returns two sortdicts with similar information:

    - the first dict, bintaghist, contains the tag information as expected by
      the _readtags function, i.e. a mapping from tag name to (node, hist):
        - node is the node id from the last line read for that name,
        - hist is the list of node ids previously associated with it (in file
          order). All node ids are binary, not hex.

    - the second dict, hextaglines, is a mapping from tag name to a list of
      [hexnode, line number] pairs, ordered from the oldest to the newest node.

    When calcnodelines is False the hextaglines dict is not calculated (an
    empty dict is returned). This is done to improve this function's
    performance in cases where the line numbers are not needed.
    '''

    bintaghist = util.sortdict()
    hextaglines = util.sortdict()
    count = 0

    def warn(msg):
        ui.warn(_("%s, line %s: %s\n") % (fn, count, msg))

    for nline, line in enumerate(lines):
        count += 1
        if not line:
            continue
        try:
            (nodehex, name) = line.split(" ", 1)
        except ValueError:
            warn(_("cannot parse entry"))
            continue
        name = name.strip()
        if recode:
            name = recode(name)
        try:
            nodebin = bin(nodehex)
        except TypeError:
            warn(_("node '%s' is not well formed") % nodehex)
            continue

        # update filetags
        if calcnodelines:
            # map tag name to a list of line numbers
            if name not in hextaglines:
                hextaglines[name] = []
            hextaglines[name].append([nodehex, nline])
            continue
        # map tag name to (node, hist)
        if name not in bintaghist:
            bintaghist[name] = []
        bintaghist[name].append(nodebin)
    return bintaghist, hextaglines
Example #2
0
def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False):
    '''Read tag definitions from a file (or any source of lines).

    This function returns two sortdicts with similar information:

    - the first dict, bintaghist, contains the tag information as expected by
      the _readtags function, i.e. a mapping from tag name to (node, hist):
        - node is the node id from the last line read for that name,
        - hist is the list of node ids previously associated with it (in file
          order). All node ids are binary, not hex.

    - the second dict, hextaglines, is a mapping from tag name to a list of
      [hexnode, line number] pairs, ordered from the oldest to the newest node.

    When calcnodelines is False the hextaglines dict is not calculated (an
    empty dict is returned). This is done to improve this function's
    performance in cases where the line numbers are not needed.
    '''

    bintaghist = util.sortdict()
    hextaglines = util.sortdict()
    count = 0

    def warn(msg):
        ui.warn(_("%s, line %s: %s\n") % (fn, count, msg))

    for nline, line in enumerate(lines):
        count += 1
        if not line:
            continue
        try:
            (nodehex, name) = line.split(" ", 1)
        except ValueError:
            warn(_("cannot parse entry"))
            continue
        name = name.strip()
        if recode:
            name = recode(name)
        try:
            nodebin = bin(nodehex)
        except TypeError:
            warn(_("node '%s' is not well formed") % nodehex)
            continue

        # update filetags
        if calcnodelines:
            # map tag name to a list of line numbers
            if name not in hextaglines:
                hextaglines[name] = []
            hextaglines[name].append([nodehex, nline])
            continue
        # map tag name to (node, hist)
        if name not in bintaghist:
            bintaghist[name] = []
        bintaghist[name].append(nodebin)
    return bintaghist, hextaglines
Example #3
0
def merge(repo, fcd, fco, fca):
    '''
    Merge the tags of two revisions, taking into account the base tags
    Try to minimize the diff between the merged tags and the first parent tags
    '''
    ui = repo.ui
    # read the p1, p2 and base tags
    # only keep the line numbers for the p1 tags
    p1tags = readtagsformerge(ui,
                              repo,
                              fcd.data().splitlines(),
                              fn="p1 tags",
                              keeplinenums=True)
    p2tags = readtagsformerge(ui,
                              repo,
                              fco.data().splitlines(),
                              fn="p2 tags",
                              keeplinenums=False)
    basetags = readtagsformerge(ui,
                                repo,
                                fca.data().splitlines(),
                                fn="base tags",
                                keeplinenums=False)

    # recover the list of "lost tags" (i.e. those that were found on the base
    # revision but not on one of the revisions being merged)
    basetagset = set(basetags)
    for n, pntags in enumerate((p1tags, p2tags)):
        pntagset = set(pntags)
        pnlosttagset = basetagset - pntagset
        for t in pnlosttagset:
            pntags[t] = basetags[t]
            if pntags[t][-1][0] != hexnullid:
                pntags[t].append([hexnullid, None])

    conflictedtags = []  # for reporting purposes
    mergedtags = util.sortdict(p1tags)
    # sortdict does not implement iteritems()
    for tname, p2nodes in p2tags.items():
        if tname not in mergedtags:
            mergedtags[tname] = p2nodes
            continue
        p1nodes = mergedtags[tname]
        mergednodes = singletagmerge(p1nodes, p2nodes)
        if mergednodes is None:
            conflictedtags.append(tname)
            continue
        mergedtags[tname] = mergednodes

    if conflictedtags:
        numconflicts = len(conflictedtags)
        ui.warn(
            _('automatic .hgtags merge failed\n'
              'the following %d tags are in conflict: %s\n') %
            (numconflicts, ', '.join(sorted(conflictedtags))))
        return True, 1

    writemergedtags(repo, mergedtags)
    ui.note(_('.hgtags merged successfully\n'))
    return False, 0
Example #4
0
 def update(self, src):
     for s, n in src._unset:
         if s in self and n in self._data[s]:
             del self._data[s][n]
             del self._source[(s, n)]
     for s in src:
         if s not in self:
             self._data[s] = util.sortdict()
         self._data[s].update(src._data[s])
     self._source.update(src._source)
Example #5
0
 def update(self, src):
     for s, n in src._unset:
         if s in self and n in self._data[s]:
             del self._data[s][n]
             del self._source[(s, n)]
     for s in src:
         if s not in self:
             self._data[s] = util.sortdict()
         self._data[s].update(src._data[s])
     self._source.update(src._source)
Example #6
0
def showextras(**args):
    """:extras: List of dicts with key, value entries of the 'extras'
    field of this changeset."""
    extras = args['ctx'].extra()
    extras = util.sortdict((k, extras[k]) for k in sorted(extras))
    makemap = lambda k: {'key': k, 'value': extras[k]}
    c = [makemap(k) for k in extras]
    f = _showlist('extra', c, plural='extras', **args)
    return _hybrid(f, extras, makemap,
                   lambda x: '%s=%s' % (x['key'], x['value']))
def showextras(**args):
    """:extras: List of dicts with key, value entries of the 'extras'
    field of this changeset."""
    extras = args['ctx'].extra()
    extras = util.sortdict((k, extras[k]) for k in sorted(extras))
    makemap = lambda k: {'key': k, 'value': extras[k]}
    c = [makemap(k) for k in extras]
    f = _showlist('extra', c, plural='extras', **args)
    return _hybrid(f, extras, makemap, lambda x: '%s=%s' %
                   (x['key'], x['value']))
Example #8
0
def showfilecopiesswitch(**args):
    """:file_copies_switch: List of strings. Like "file_copies" but displayed
    only if the --copied switch is set.
    """
    copies = args['revcache'].get('copies') or []
    copies = util.sortdict(copies)
    makemap = lambda k: {'name': k, 'source': copies[k]}
    c = [makemap(k) for k in copies]
    f = _showlist('file_copy', c, plural='file_copies', **args)
    return _hybrid(f, copies, makemap,
                   lambda x: '%s (%s)' % (x['name'], x['source']))
def showfilecopiesswitch(**args):
    """:file_copies_switch: List of strings. Like "file_copies" but displayed
    only if the --copied switch is set.
    """
    copies = args['revcache'].get('copies') or []
    copies = util.sortdict(copies)
    makemap = lambda k: {'name': k, 'source': copies[k]}
    c = [makemap(k) for k in copies]
    f = _showlist('file_copy', c, plural='file_copies', **args)
    return _hybrid(f, copies, makemap, lambda x: '%s (%s)' %
                   (x['name'], x['source']))
Example #10
0
def merge(repo, fcd, fco, fca):
    '''
    Merge the tags of two revisions, taking into account the base tags
    Try to minimize the diff between the merged tags and the first parent tags
    '''
    ui = repo.ui
    # read the p1, p2 and base tags
    # only keep the line numbers for the p1 tags
    p1tags = readtagsformerge(
        ui, repo, fcd.data().splitlines(), fn="p1 tags",
        keeplinenums=True)
    p2tags = readtagsformerge(
        ui, repo, fco.data().splitlines(), fn="p2 tags",
        keeplinenums=False)
    basetags = readtagsformerge(
        ui, repo, fca.data().splitlines(), fn="base tags",
        keeplinenums=False)

    # recover the list of "lost tags" (i.e. those that were found on the base
    # revision but not on one of the revisions being merged)
    basetagset = set(basetags)
    for n, pntags in enumerate((p1tags, p2tags)):
        pntagset = set(pntags)
        pnlosttagset = basetagset - pntagset
        for t in pnlosttagset:
            pntags[t] = basetags[t]
            if pntags[t][-1][0] != hexnullid:
                pntags[t].append([hexnullid, None])

    conflictedtags = []  # for reporting purposes
    mergedtags = util.sortdict(p1tags)
    # sortdict does not implement iteritems()
    for tname, p2nodes in p2tags.items():
        if tname not in mergedtags:
            mergedtags[tname] = p2nodes
            continue
        p1nodes = mergedtags[tname]
        mergednodes = singletagmerge(p1nodes, p2nodes)
        if mergednodes is None:
            conflictedtags.append(tname)
            continue
        mergedtags[tname] = mergednodes

    if conflictedtags:
        numconflicts = len(conflictedtags)
        ui.warn(_('automatic .hgtags merge failed\n'
            'the following %d tags are in conflict: %s\n')
            % (numconflicts, ', '.join(sorted(conflictedtags))))
        return True, 1

    writemergedtags(repo, mergedtags)
    ui.note(_('.hgtags merged successfully\n'))
    return False, 0
Example #11
0
def showfilecopies(**args):
    """:file_copies: List of strings. Files copied in this changeset with
    their sources.
    """
    cache, ctx = args['cache'], args['ctx']
    copies = args['revcache'].get('copies')
    if copies is None:
        if 'getrenamed' not in cache:
            cache['getrenamed'] = getrenamedfn(args['repo'])
        copies = []
        getrenamed = cache['getrenamed']
        for fn in ctx.files():
            rename = getrenamed(fn, ctx.rev())
            if rename:
                copies.append((fn, rename[0]))

    copies = util.sortdict(copies)
    makemap = lambda k: {'name': k, 'source': copies[k]}
    c = [makemap(k) for k in copies]
    f = _showlist('file_copy', c, plural='file_copies', **args)
    return _hybrid(f, copies, makemap,
                   lambda x: '%s (%s)' % (x['name'], x['source']))
def showfilecopies(**args):
    """:file_copies: List of strings. Files copied in this changeset with
    their sources.
    """
    cache, ctx = args['cache'], args['ctx']
    copies = args['revcache'].get('copies')
    if copies is None:
        if 'getrenamed' not in cache:
            cache['getrenamed'] = getrenamedfn(args['repo'])
        copies = []
        getrenamed = cache['getrenamed']
        for fn in ctx.files():
            rename = getrenamed(fn, ctx.rev())
            if rename:
                copies.append((fn, rename[0]))

    copies = util.sortdict(copies)
    makemap = lambda k: {'name': k, 'source': copies[k]}
    c = [makemap(k) for k in copies]
    f = _showlist('file_copy', c, plural='file_copies', **args)
    return _hybrid(f, copies, makemap, lambda x: '%s (%s)' %
                   (x['name'], x['source']))
Example #13
0
    def parse(self, src, data, sections=None, remap=None, include=None):
        sectionre = util.re.compile(r'\[([^\[]+)\]')
        itemre = util.re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
        contre = util.re.compile(r'\s+(\S|\S.*\S)\s*$')
        emptyre = util.re.compile(r'(;|#|\s*$)')
        commentre = util.re.compile(r'(;|#)')
        unsetre = util.re.compile(r'%unset\s+(\S+)')
        includere = util.re.compile(r'%include\s+(\S|\S.*\S)\s*$')
        section = ""
        item = None
        line = 0
        cont = False

        for l in data.splitlines(True):
            line += 1
            if line == 1 and l.startswith('\xef\xbb\xbf'):
                # Someone set us up the BOM
                l = l[3:]
            if cont:
                if commentre.match(l):
                    continue
                m = contre.match(l)
                if m:
                    if sections and section not in sections:
                        continue
                    v = self.get(section, item) + "\n" + m.group(1)
                    self.set(section, item, v, "%s:%d" % (src, line))
                    continue
                item = None
                cont = False
            m = includere.match(l)
            if m:
                inc = util.expandpath(m.group(1))
                base = os.path.dirname(src)
                inc = os.path.normpath(os.path.join(base, inc))
                if include:
                    try:
                        include(inc, remap=remap, sections=sections)
                    except IOError, inst:
                        if inst.errno != errno.ENOENT:
                            raise error.ParseError(
                                _("cannot include %s (%s)") %
                                (inc, inst.strerror), "%s:%s" % (src, line))
                continue
            if emptyre.match(l):
                continue
            m = sectionre.match(l)
            if m:
                section = m.group(1)
                if remap:
                    section = remap.get(section, section)
                if section not in self:
                    self._data[section] = util.sortdict()
                continue
            m = itemre.match(l)
            if m:
                item = m.group(1)
                cont = True
                if sections and section not in sections:
                    continue
                self.set(section, item, m.group(2), "%s:%d" % (src, line))
                continue
            m = unsetre.match(l)
            if m:
                name = m.group(1)
                if sections and section not in sections:
                    continue
                if self.get(section, name) is not None:
                    del self._data[section][name]
                self._unset.append((section, name))
                continue

            raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
Example #14
0
 def set(self, section, item, value, source=""):
     if section not in self:
         self._data[section] = util.sortdict()
     self._data[section][item] = value
     if source:
         self._source[(section, item)] = source
Example #15
0
    def parse(self, src, data, sections=None, remap=None, include=None):
        sectionre = util.re.compile(r'\[([^\[]+)\]')
        itemre = util.re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
        contre = util.re.compile(r'\s+(\S|\S.*\S)\s*$')
        emptyre = util.re.compile(r'(;|#|\s*$)')
        commentre = util.re.compile(r'(;|#)')
        unsetre = util.re.compile(r'%unset\s+(\S+)')
        includere = util.re.compile(r'%include\s+(\S|\S.*\S)\s*$')
        section = ""
        item = None
        line = 0
        cont = False

        for l in data.splitlines(True):
            line += 1
            if line == 1 and l.startswith('\xef\xbb\xbf'):
                # Someone set us up the BOM
                l = l[3:]
            if cont:
                if commentre.match(l):
                    continue
                m = contre.match(l)
                if m:
                    if sections and section not in sections:
                        continue
                    v = self.get(section, item) + "\n" + m.group(1)
                    self.set(section, item, v, "%s:%d" % (src, line))
                    continue
                item = None
                cont = False
            m = includere.match(l)

            if m and include:
                expanded = util.expandpath(m.group(1))
                includepaths = [os.path.dirname(src)] + self._includepaths

                for base in includepaths:
                    inc = os.path.normpath(os.path.join(base, expanded))

                    try:
                        include(inc, remap=remap, sections=sections)
                        break
                    except IOError as inst:
                        if inst.errno != errno.ENOENT:
                            raise error.ParseError(_("cannot include %s (%s)")
                                                   % (inc, inst.strerror),
                                                   "%s:%s" % (src, line))
                continue
            if emptyre.match(l):
                continue
            m = sectionre.match(l)
            if m:
                section = m.group(1)
                if remap:
                    section = remap.get(section, section)
                if section not in self:
                    self._data[section] = util.sortdict()
                continue
            m = itemre.match(l)
            if m:
                item = m.group(1)
                cont = True
                if sections and section not in sections:
                    continue
                self.set(section, item, m.group(2), "%s:%d" % (src, line))
                continue
            m = unsetre.match(l)
            if m:
                name = m.group(1)
                if sections and section not in sections:
                    continue
                if self.get(section, name) is not None:
                    del self._data[section][name]
                self._unset.append((section, name))
                continue

            raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
Example #16
0
 def set(self, section, item, value, source=""):
     if section not in self:
         self._data[section] = util.sortdict()
     self._data[section][item] = value
     if source:
         self._source[(section, item)] = source