##// END OF EJS Templates
log: add support for bookmarks...
log: add support for bookmarks A bookmark can already be pushed with 'hg push origin -B topic-foo'. The pull command also supports bookmarks. This patch adds support for bookmarks using the '_opt2logrevset' code path. The list of changesets for a bookmark can now be obtained simply with: 'hg log -B topic-foo'. Reviewed-by: Elenie Godzaridis <arangradient@gmail.com> Differential Revision: https://phab.mercurial-scm.org/D8973

File last commit:

r44187:c190f271 default
r46123:2517df77 default
Show More
cvsps.py
1070 lines | 35.5 KiB | text/x-python | PythonLexer
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # Mercurial built-in replacement for cvsps.
#
# Copyright 2008, Frank Kingswood <frank@kingswood-consulting.co.uk>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
timeless
convert: cvsps use absolute_import
r28369 from __future__ import absolute_import
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
cvsps: wrap cmp methods (deprecated) in functools.cmp_to_key...
r37903 import functools
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 import os
import re
timeless
convert: cvsps use absolute_import
r28369
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from mercurial.pycompat import open
timeless
convert: cvsps use absolute_import
r28369 from mercurial import (
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 5 of 5)
r30638 encoding,
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 error,
timeless
convert: cvsps use absolute_import
r28369 hook,
Pulkit Goyal
py3: replace os.sep with pycompat.ossep (part 4 of 4)
r30616 pycompat,
timeless
convert: cvsps use absolute_import
r28369 util,
)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from mercurial.utils import (
dateutil,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 procutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Pulkit Goyal
py3: conditionalize cPickle import by adding in util...
r29324 pickle = util.pickle
Augie Fackler
formatting: blacken the codebase...
r43346
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 class logentry(object):
'''Class logentry has the following attributes:
.author - author name as CVS knows it
.branch - name of branch this revision is on
.branches - revision tuple of branches starting at this revision
.comment - commit message
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 .commitid - CVS commitid or None
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 .date - the commit date as a (time, tz) tuple
.dead - true if file revision is dead
.file - Name of file
.lines - a tuple (+lines, -lines) or None
.parent - Previous revision of this entry
.rcs - name of file as returned from CVS
.revision - revision number as tuple
.tags - list of tags on the file
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 .synthetic - is this a synthetic "file ... added on ..." revision?
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 .mergepoint - the branch that has been merged from (if present in
rlog output) or None
.branchpoints - the branches that start at the current entry or empty
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 '''
Augie Fackler
formatting: blacken the codebase...
r43346
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 def __init__(self, **entries):
Benoit Boissinot
cvsps: fix traceback involving 'synthetic'...
r10701 self.synthetic = False
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 self.__dict__.update(entries)
Greg Ward
cvsps: make debugging easier by adding __repr__() methods.
r8080 def __repr__(self):
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 items = ("%s=%r" % (k, self.__dict__[k]) for k in sorted(self.__dict__))
return "%s(%s)" % (type(self).__name__, ", ".join(items))
Augie Fackler
formatting: blacken the codebase...
r43346
Greg Ward
cvsps: make debugging easier by adding __repr__() methods.
r8080
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 class logerror(Exception):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 def getrepopath(cvspath):
"""Return the repository path from a CVS path.
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b'/foo/bar')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b'c:/foo/bar')
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:10/foo/bar')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:10c:/foo/bar')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:/foo/bar')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:c:/foo/bar')
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:truc@foo.bar:/foo/bar')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b':pserver:truc@foo.bar:c:/foo/bar')
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 '/foo/bar'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> getrepopath(b'user@server/path/to/repository')
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 '/path/to/repository'
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 """
# According to CVS manual, CVS paths are expressed like:
# [:method:][[user][:password]@]hostname[:[port]]/path/to/repository
#
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 # CVSpath is splitted into parts and then position of the first occurrence
# of the '/' char after the '@' is located. The solution is the rest of the
# string after that '/' sign including it
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 parts = cvspath.split(b':')
atposition = parts[-1].find(b'@')
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 start = 0
if atposition != -1:
start = atposition
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repopath = parts[-1][parts[-1].find(b'/', start) :]
Blesso
convert: fix bug of wrong CVS path parsing without port number (issue3678)...
r19145 return repopath
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def createlog(ui, directory=None, root=b"", rlog=True, cache=None):
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 '''Collect the CVS rlog'''
# Because we store many duplicate commit log messages, reusing strings
# saves a lot of memory and pickle storage space.
_scache = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 def scache(s):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """return a shared version of a string"""
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 return _scache.setdefault(s, s)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'collecting CVS rlog\n'))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
formatting: blacken the codebase...
r43346 log = [] # list of logentry objects containing the CVS state
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# patterns to match in CVS (r)log output, by state of use
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 re_00 = re.compile(b'RCS file: (.+)$')
re_01 = re.compile(b'cvs \\[r?log aborted\\]: (.+)$')
re_02 = re.compile(b'cvs (r?log|server): (.+)\n$')
Augie Fackler
formatting: blacken the codebase...
r43346 re_03 = re.compile(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b"(Cannot access.+CVSROOT)|(can't create temporary directory.+)$"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 re_10 = re.compile(b'Working file: (.+)$')
re_20 = re.compile(b'symbolic names:')
re_30 = re.compile(b'\t(.+): ([\\d.]+)$')
re_31 = re.compile(b'----------------------------$')
Augie Fackler
formatting: blacken the codebase...
r43346 re_32 = re.compile(
b'======================================='
b'======================================$'
)
Gregory Szorc
global: use raw strings for regular expressions with escapes...
r41673 re_50 = re.compile(br'revision ([\d.]+)(\s+locked by:\s+.+;)?$')
Augie Fackler
formatting: blacken the codebase...
r43346 re_60 = re.compile(
br'date:\s+(.+);\s+author:\s+(.+);\s+state:\s+(.+?);'
br'(\s+lines:\s+(\+\d+)?\s+(-\d+)?;)?'
br'(\s+commitid:\s+([^;]+);)?'
br'(.*mergepoint:\s+([^;]+);)?'
)
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 re_70 = re.compile(b'branches: (.+);$')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 file_added_re = re.compile(br'file [^/]+ was (initially )?added on branch')
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix = b'' # leading path to strip of what we get from CVS
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if directory is None:
# Current working directory
# Get the real directory in the repository
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(os.path.join(b'CVS', b'Repository'), b'rb') as f:
Augie Fackler
cvsps: switch a file open to a with statement...
r43322 prefix = f.read().strip()
Mathieu Clabaut
convert: teach cvsps to handle . repository (issue1649)...
r10695 directory = prefix
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if prefix == b".":
prefix = b""
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 except IOError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise logerror(_(b'not a CVS sandbox'))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Pulkit Goyal
py3: replace os.sep with pycompat.ossep (part 4 of 4)
r30616 if prefix and not prefix.endswith(pycompat.ossep):
prefix += pycompat.ossep
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# Use the Root file in the sandbox, if it exists
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 root = open(os.path.join(b'CVS', b'Root'), b'rb').read().strip()
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 except IOError:
pass
if not root:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 root = encoding.environ.get(b'CVSROOT', b'')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# read log cache if one exists
oldlog = []
date = None
if cache:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachedir = os.path.expanduser(b'~/.hg.cvsps')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if not os.path.exists(cachedir):
os.mkdir(cachedir)
# The cvsps cache pickle needs a uniquified name, based on the
# repository location. The address may have all sort of nasties
# in it, slashes, colons and such. So here we take just the
Mads Kiilerich
fix trivial spelling errors
r17424 # alphanumeric characters, concatenated in a way that does not
# mix up the various components, so that
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # :pserver:user@server:/path
# and
# /pserver/user/server/path
# are mapped to different cache file names.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachefile = root.split(b":") + [directory, b"cache"]
cachefile = [b'-'.join(re.findall(br'\w+', s)) for s in cachefile if s]
Augie Fackler
formatting: blacken the codebase...
r43346 cachefile = os.path.join(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cachedir, b'.'.join([s for s in cachefile if s])
Augie Fackler
formatting: blacken the codebase...
r43346 )
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cache == b'update':
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'reading cvs log cache %s\n') % cachefile)
oldlog = pickle.load(open(cachefile, b'rb'))
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 for e in oldlog:
Augie Fackler
formatting: blacken the codebase...
r43346 if not (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 util.safehasattr(e, b'branchpoints')
and util.safehasattr(e, b'commitid')
and util.safehasattr(e, b'mergepoint')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'ignoring old cache\n'))
Idan Kamara
cvsps: fix indentation
r18286 oldlog = []
break
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'cache has %d log entries\n') % len(oldlog))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except Exception as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'error reading cache: %r\n') % e)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if oldlog:
Augie Fackler
formatting: blacken the codebase...
r43346 date = oldlog[-1].date # last commit date as a (time,tz) tuple
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 date = dateutil.datestr(date, b'%Y/%m/%d %H:%M:%S %1%2')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# build the CVS commandline
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd = [b'cvs', b'-q']
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if root:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd.append(b'-d%s' % root)
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 p = util.normpath(getrepopath(root))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not p.endswith(b'/'):
p += b'/'
Mathieu Clabaut
convert: teach cvsps to handle . repository (issue1649)...
r10695 if prefix:
# looks like normpath replaces "" by "."
prefix = p + util.normpath(prefix)
else:
prefix = p
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd.append([b'log', b'rlog'][rlog])
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if date:
# no space between option and date string
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd.append(b'-d>%s' % date)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 cmd.append(directory)
# state machine begins here
Augie Fackler
formatting: blacken the codebase...
r43346 tags = {} # dictionary of revisions on current file with their tags
branchmap = {} # mapping between branch names and revision numbers
Emanuele Giaquinta
cvsps: fix computation of parent revisions when log caching is on...
r26593 rcsmap = {}
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 0
Augie Fackler
formatting: blacken the codebase...
r43346 store = False # set when a new record can be appended
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 cmd = [procutil.shellquote(arg) for arg in cmd]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"running %s\n") % (b' '.join(cmd)))
ui.debug(b"prefix=%r directory=%r root=%r\n" % (prefix, directory, root))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pfp = procutil.popen(b' '.join(cmd), b'rb')
Yuya Nishihara
procutil: always popen() in binary mode...
r37476 peek = util.fromnativeeol(pfp.readline())
David Champion
cvsps: cvs log loop uses lookahead to avoid misleading text...
r7593 while True:
line = peek
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if line == b'':
David Champion
cvsps: cvs log loop uses lookahead to avoid misleading text...
r7593 break
Yuya Nishihara
procutil: always popen() in binary mode...
r37476 peek = util.fromnativeeol(pfp.readline())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if line.endswith(b'\n'):
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 line = line[:-1]
Augie Fackler
formatting: blacken the codebase...
r43346 # ui.debug('state=%d line=%r\n' % (state, line))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if state == 0:
# initial state, consume input until we see 'RCS file'
match = re_00.match(line)
if match:
rcs = match.group(1)
tags = {}
if rlog:
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 filename = util.normpath(rcs[:-2])
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if filename.startswith(prefix):
Augie Fackler
formatting: blacken the codebase...
r43346 filename = filename[len(prefix) :]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if filename.startswith(b'/'):
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 filename = filename[1:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if filename.startswith(b'Attic/'):
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 filename = filename[6:]
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 filename = filename.replace(b'/Attic/', b'/')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 2
continue
state = 1
continue
match = re_01.match(line)
if match:
Matt Mackall
clean up remaining generic exceptions
r11122 raise logerror(match.group(1))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 match = re_02.match(line)
if match:
Matt Mackall
clean up remaining generic exceptions
r11122 raise logerror(match.group(2))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if re_03.match(line):
Matt Mackall
clean up remaining generic exceptions
r11122 raise logerror(line)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
elif state == 1:
# expect 'Working file' (only when using log instead of rlog)
match = re_10.match(line)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert match, _(b'RCS file must be followed by working file')
Patrick Mezard
convert: fix builtin cvsps under Windows...
r7097 filename = util.normpath(match.group(1))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 2
elif state == 2:
# expect 'symbolic names'
if re_20.match(line):
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 branchmap = {}
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 3
elif state == 3:
# read the symbolic names and store as tags
match = re_30.match(line)
if match:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rev = [int(x) for x in match.group(2).split(b'.')]
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# Convert magic branch number to an odd-numbered one
revn = len(rev)
Matt Mackall
cvsps: fix up some whitespace
r6688 if revn > 3 and (revn % 2) == 0 and rev[-2] == 0:
rev = rev[:-2] + rev[-1:]
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 rev = tuple(rev)
if rev not in tags:
tags[rev] = []
tags[rev].append(match.group(1))
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 branchmap[match.group(1)] = match.group(2)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
elif re_31.match(line):
state = 5
elif re_32.match(line):
state = 0
elif state == 4:
# expecting '------' separator before first revision
if re_31.match(line):
state = 5
else:
Augie Fackler
formatting: blacken the codebase...
r43346 assert not re_32.match(line), _(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'must have at least some revisions'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
elif state == 5:
# expecting revision number and possibly (ignored) lock indication
# we create the logentry here from values stored in states 0 to 4,
# as this state is re-entered for subsequent revisions of a file.
match = re_50.match(line)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert match, _(b'expected revision number')
Augie Fackler
formatting: blacken the codebase...
r43346 e = logentry(
rcs=scache(rcs),
file=scache(filename),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revision=tuple([int(x) for x in match.group(1).split(b'.')]),
Augie Fackler
formatting: blacken the codebase...
r43346 branches=[],
parent=None,
commitid=None,
mergepoint=None,
branchpoints=set(),
)
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 6
elif state == 6:
# expecting date, author, state, lines changed
match = re_60.match(line)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert match, _(b'revision must be followed by date line')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 d = match.group(1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if d[2] == b'/':
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # Y2K
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d = b'19' + d
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if len(d.split()) != 3:
# cvs log dates always in GMT
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d = d + b' UTC'
Augie Fackler
formatting: blacken the codebase...
r43346 e.date = dateutil.parsedate(
d,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 [
b'%y/%m/%d %H:%M:%S',
b'%Y/%m/%d %H:%M:%S',
b'%Y-%m-%d %H:%M:%S',
],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 e.author = scache(match.group(2))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e.dead = match.group(3).lower() == b'dead'
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if match.group(5):
if match.group(6):
e.lines = (int(match.group(5)), int(match.group(6)))
else:
e.lines = (int(match.group(5)), 0)
elif match.group(6):
e.lines = (0, int(match.group(6)))
else:
e.lines = None
Henrik Stuart
convert: added cvsnt mergepoint support
r7956
Augie Fackler
formatting: blacken the codebase...
r43346 if match.group(7): # cvs 1.12 commitid
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 e.commitid = match.group(8)
Augie Fackler
formatting: blacken the codebase...
r43346 if match.group(9): # cvsnt mergepoint
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 myrev = match.group(10).split(b'.')
Augie Fackler
formatting: blacken the codebase...
r43346 if len(myrev) == 2: # head
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e.mergepoint = b'HEAD'
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 myrev = b'.'.join(myrev[:-2] + [b'0', myrev[-2]])
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 branches = [b for b in branchmap if branchmap[b] == myrev]
Augie Fackler
formatting: blacken the codebase...
r43346 assert len(branches) == 1, (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unknown branch: %s' % e.mergepoint
Augie Fackler
formatting: blacken the codebase...
r43346 )
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 e.mergepoint = branches[0]
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 e.comment = []
state = 7
elif state == 7:
Matt Mackall
cvsps: fix up some whitespace
r6688 # read the revision numbers of branches that start at this revision
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # or store the commit log message otherwise
m = re_70.match(line)
if m:
Augie Fackler
formatting: blacken the codebase...
r43346 e.branches = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tuple([int(y) for y in x.strip().split(b'.')])
for x in m.group(1).split(b';')
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 8
David Champion
cvsps: cvs log loop uses lookahead to avoid misleading text...
r7593 elif re_31.match(line) and re_50.match(peek):
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 state = 5
store = True
elif re_32.match(line):
state = 0
store = True
else:
e.comment.append(line)
elif state == 8:
# store commit log message
if re_31.match(line):
jakob krainz
convert: detect false cset boundaries in cvsps descriptions
r15205 cpeek = peek
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cpeek.endswith(b'\n'):
jakob krainz
convert: detect false cset boundaries in cvsps descriptions
r15205 cpeek = cpeek[:-1]
if re_50.match(cpeek):
state = 5
store = True
else:
e.comment.append(line)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 elif re_32.match(line):
state = 0
store = True
else:
e.comment.append(line)
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 # When a file is added on a branch B1, CVS creates a synthetic
# dead trunk revision 1.1 so that the branch has a root.
# Likewise, if you merge such a file to a later branch B2 (one
# that already existed when the file was added on B1), CVS
# creates a synthetic dead revision 1.1.x.1 on B2. Don't drop
# these revisions now, but mark them synthetic so
# createchangeset() can take care of them.
Augie Fackler
formatting: blacken the codebase...
r43346 if (
store
and e.dead
and e.revision[-1] == 1
and len(e.comment) == 1 # 1.1 or 1.1.x.1
and file_added_re.match(e.comment[0])
):
ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'found synthetic revision in %s: %r\n' % (e.rcs, e.comment[0])
Augie Fackler
formatting: blacken the codebase...
r43346 )
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 e.synthetic = True
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if store:
# clean up the results and save in the log.
store = False
Matt Mackall
replace util.sort with sorted built-in...
r8209 e.tags = sorted([scache(x) for x in tags.get(e.revision, [])])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e.comment = scache(b'\n'.join(e.comment))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
revn = len(e.revision)
Matt Mackall
cvsps: fix up some whitespace
r6688 if revn > 3 and (revn % 2) == 0:
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 e.branch = tags.get(e.revision[:-1], [None])[0]
else:
e.branch = None
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 # find the branches starting from this revision
branchpoints = set()
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for branch, revision in pycompat.iteritems(branchmap):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revparts = tuple([int(i) for i in revision.split(b'.')])
Augie Fackler
formatting: blacken the codebase...
r43346 if len(revparts) < 2: # bad tags
Brandon Parsons
cvs: skip bad tags...
r10950 continue
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 if revparts[-2] == 0 and revparts[-1] % 2 == 0:
# normal branch
if revparts[:-2] == e.revision:
branchpoints.add(branch)
Augie Fackler
formatting: blacken the codebase...
r43346 elif revparts == (1, 1, 1): # vendor branch
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 if revparts in e.branches:
branchpoints.add(branch)
e.branchpoints = branchpoints
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 log.append(e)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rcsmap[e.rcs.replace(b'/Attic/', b'/')] = e.rcs
Emanuele Giaquinta
cvsps: fix computation of parent revisions when log caching is on...
r26593
Matt Mackall
cvsps: fix up some whitespace
r6688 if len(log) % 100 == 0:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 stringutil.ellipsis(b'%d %s' % (len(log), e.file), 80)
+ b'\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Alejandro Santos
compat: use 'key' argument instead of 'cmp' when sorting a list
r9032 log.sort(key=lambda x: (x.rcs, x.revision))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# find parent revisions of individual files
versions = {}
Emanuele Giaquinta
cvsps: fix computation of parent revisions when log caching is on...
r26593 for e in sorted(oldlog, key=lambda x: (x.rcs, x.revision)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rcs = e.rcs.replace(b'/Attic/', b'/')
Emanuele Giaquinta
cvsps: fix computation of parent revisions when log caching is on...
r26593 if rcs in rcsmap:
e.rcs = rcsmap[rcs]
branch = e.revision[:-1]
versions[(e.rcs, branch)] = e.revision
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 for e in log:
branch = e.revision[:-1]
p = versions.get((e.rcs, branch), None)
if p is None:
p = e.revision[:-2]
e.parent = p
versions[(e.rcs, branch)] = e.revision
# update the log cache
if cache:
if log:
# join up the old and new logs
Alejandro Santos
compat: use 'key' argument instead of 'cmp' when sorting a list
r9032 log.sort(key=lambda x: x.date)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if oldlog and oldlog[-1].date >= log[0].date:
Augie Fackler
formatting: blacken the codebase...
r43346 raise logerror(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'log cache overlaps with new log entries,'
b' re-run without cache.'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Matt Mackall
cvsps: fix up some whitespace
r6688 log = oldlog + log
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# write the new cachefile
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'writing cvs log cache %s\n') % cachefile)
pickle.dump(log, open(cachefile, b'wb'))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 else:
log = oldlog
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'%d log entries\n') % len(log))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 encodings = ui.configlist(b'convert', b'cvsps.logencoding')
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 if encodings:
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 def revstr(r):
# this is needed, because logentry.revision is a tuple of "int"
# (e.g. (1, 2) for "1.2")
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'.'.join(pycompat.maplist(pycompat.bytestr, r))
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388
for entry in log:
comment = entry.comment
for e in encodings:
try:
Augie Fackler
formatting: blacken the codebase...
r43346 entry.comment = comment.decode(pycompat.sysstr(e)).encode(
'utf-8'
)
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 if ui.debugflag:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"transcoding by %s: %s of %s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (e, revstr(entry.revision), entry.file)
)
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 break
except UnicodeDecodeError:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # try next encoding
except LookupError as inst: # unknown encoding, maybe
raise error.Abort(
inst,
hint=_(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'check convert.cvsps.logencoding configuration'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"no encoding can transcode"
b" CVS log message for %s of %s"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (revstr(entry.revision), entry.file),
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 hint=_(b'check convert.cvsps.logencoding configuration'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
convert: transcode CVS log messages by specified encoding (issue5597)...
r33388
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hook.hook(ui, None, b"cvslog", True, log=log)
Frank Kingswood
convert: implement two hooks in builtin cvsps
r10095
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 return log
class changeset(object):
'''Class changeset has the following attributes:
Greg Ward
cvsps: update docstring for changeset class.
r8079 .id - integer identifying this changeset (list index)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 .author - author name as CVS knows it
.branch - name of branch this changeset is on, or None
.comment - commit message
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 .commitid - CVS commitid or None
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 .date - the commit date as a (time,tz) tuple
.entries - list of logentry objects in this changeset
.parents - list of one or two parent changesets
.tags - list of tags on this changeset
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 .synthetic - from synthetic revision "file ... added on branch ..."
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 .mergepoint- the branch that has been merged from or None
.branchpoints- the branches that start at the current entry or empty
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 '''
Augie Fackler
formatting: blacken the codebase...
r43346
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 def __init__(self, **entries):
Frank Kingswood
convert: handle changeset sorting errors without traceback (issue3961)
r19505 self.id = None
Benoit Boissinot
cvsps: fix traceback involving 'synthetic'...
r10701 self.synthetic = False
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 self.__dict__.update(entries)
Greg Ward
cvsps: make debugging easier by adding __repr__() methods.
r8080 def __repr__(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 items = (
b"%s=%r" % (k, self.__dict__[k]) for k in sorted(self.__dict__)
)
return b"%s(%s)" % (type(self).__name__, b", ".join(items))
Augie Fackler
formatting: blacken the codebase...
r43346
Greg Ward
cvsps: make debugging easier by adding __repr__() methods.
r8080
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 def createchangeset(ui, log, fuzz=60, mergefrom=None, mergeto=None):
'''Convert log into changesets.'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'creating changesets\n'))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Matt Mackall
convert: stabilize cvsps commitid sort order
r18718 # try to order commitids by date
mindate = {}
for e in log:
if e.commitid:
Augie Fackler
cvsps: avoid comparison between None and a tuple in date sorting...
r38313 if e.commitid not in mindate:
mindate[e.commitid] = e.date
else:
mindate[e.commitid] = min(e.date, mindate[e.commitid])
Matt Mackall
convert: stabilize cvsps commitid sort order
r18718
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # Merge changesets
Augie Fackler
formatting: blacken the codebase...
r43346 log.sort(
key=lambda x: (
mindate.get(x.commitid, (-1, 0)),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 x.commitid or b'',
Augie Fackler
formatting: blacken the codebase...
r43346 x.comment,
x.author,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 x.branch or b'',
Augie Fackler
formatting: blacken the codebase...
r43346 x.date,
x.branchpoints,
)
)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
changesets = []
Benoit Boissinot
convert: use set instead of dict
r8456 files = set()
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 c = None
for i, e in enumerate(log):
# Check if log entry belongs to the current changeset or not.
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756
Mads Kiilerich
fix trivial spelling errors
r17424 # Since CVS is file-centric, two different file revisions with
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 # different branchpoints should be treated as belonging to two
# different changesets (and the ordering is important and not
# honoured by cvsps at this point).
#
# Consider the following case:
# foo 1.1 branchpoints: [MYBRANCH]
# bar 1.1 branchpoints: [MYBRANCH, MYBRANCH2]
#
# Here foo is part only of MYBRANCH, but not MYBRANCH2, e.g. a
# later version of foo may be in MYBRANCH2, so foo should be the
# first changeset and bar the next and MYBRANCH and MYBRANCH2
# should both start off of the bar changeset. No provisions are
# made to ensure that this is, in fact, what happens.
Augie Fackler
formatting: blacken the codebase...
r43346 if not (
c
and e.branchpoints == c.branchpoints
and ( # cvs commitids
(e.commitid is not None and e.commitid == c.commitid)
or ( # no commitids, use fuzzy commit detection
(e.commitid is None or c.commitid is None)
and e.comment == c.comment
and e.author == c.author
and e.branch == c.branch
and (
(c.date[0] + c.date[1])
<= (e.date[0] + e.date[1])
<= (c.date[0] + c.date[1]) + fuzz
)
and e.file not in files
)
)
):
c = changeset(
comment=e.comment,
author=e.author,
branch=e.branch,
date=e.date,
entries=[],
mergepoint=e.mergepoint,
branchpoints=e.branchpoints,
commitid=e.commitid,
)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 changesets.append(c)
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261
Benoit Boissinot
convert: use set instead of dict
r8456 files = set()
Matt Mackall
cvsps: fix up some whitespace
r6688 if len(changesets) % 100 == 0:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 t = b'%d %s' % (len(changesets), repr(e.comment)[1:-1])
ui.status(stringutil.ellipsis(t, 80) + b'\n')
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
c.entries.append(e)
Benoit Boissinot
convert: use set instead of dict
r8456 files.add(e.file)
Augie Fackler
formatting: blacken the codebase...
r43346 c.date = e.date # changeset date is date of latest commit in it
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 # Mark synthetic changesets
for c in changesets:
# Synthetic revisions always get their own changeset, because
# the log message includes the filename. E.g. if you add file3
# and file4 on a branch, you get four log entries and three
# changesets:
# "File file3 was added on branch ..." (synthetic, 1 entry)
# "File file4 was added on branch ..." (synthetic, 1 entry)
# "Add file3 and file4 to fix ..." (real, 2 entries)
# Hence the check for 1 entry here.
Benoit Boissinot
cvsps: fix traceback involving 'synthetic'...
r10701 c.synthetic = len(c.entries) == 1 and c.entries[0].synthetic
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # Sort files in each changeset
Martin Geisler
cvsps: pull function definition out of loop
r15790 def entitycompare(l, r):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Mimic cvsps sorting order"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 l = l.file.split(b'/')
r = r.file.split(b'/')
Martin Geisler
cvsps: pull function definition out of loop
r15790 nl = len(l)
nr = len(r)
n = min(nl, nr)
for i in range(n):
if i + 1 == nl and nl < nr:
return -1
elif i + 1 == nr and nl > nr:
return +1
elif l[i] < r[i]:
return -1
elif l[i] > r[i]:
return +1
return 0
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 for c in changesets:
Augie Fackler
cvsps: wrap cmp methods (deprecated) in functools.cmp_to_key...
r37903 c.entries.sort(key=functools.cmp_to_key(entitycompare))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# Sort changesets by date
Frank Kingswood
convert: handle changeset sorting errors without traceback (issue3961)
r19505 odd = set()
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
convert: don't use mutable default argument value...
r31408 def cscmp(l, r):
Matt Mackall
cvsps: fix up some whitespace
r6688 d = sum(l.date) - sum(r.date)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if d:
return d
# detect vendor branches and initial commits on a branch
le = {}
for e in l.entries:
le[e.rcs] = e.revision
re = {}
for e in r.entries:
re[e.rcs] = e.revision
d = 0
for e in l.entries:
if re.get(e.rcs, None) == e.parent:
assert not d
d = 1
break
for e in r.entries:
if le.get(e.rcs, None) == e.parent:
Frank Kingswood
convert: handle changeset sorting errors without traceback (issue3961)
r19505 if d:
odd.add((l, r))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 d = -1
break
Augie Fackler
cvsps: add two more tiebreakers in cscmp...
r22267 # By this point, the changesets are sufficiently compared that
# we don't really care about ordering. However, this leaves
# some race conditions in the tests, so we compare on the
Augie Fackler
cvsps: use a different tiebreaker to avoid flaky test...
r24305 # number of files modified, the files contained in each
# changeset, and the branchpoints in the change to ensure test
# output remains stable.
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
cvsps: add two more tiebreakers in cscmp...
r22267 # recommended replacement for cmp from
# https://docs.python.org/3.0/whatsnew/3.0.html
c = lambda x, y: (x > y) - (x < y)
Augie Fackler
cvsps: use a different tiebreaker to avoid flaky test...
r24305 # Sort bigger changes first.
Augie Fackler
cvsps: add two more tiebreakers in cscmp...
r22267 if not d:
d = c(len(l.entries), len(r.entries))
Augie Fackler
cvsps: use a different tiebreaker to avoid flaky test...
r24305 # Try sorting by filename in the change.
if not d:
d = c([e.file for e in l.entries], [e.file for e in r.entries])
# Try and put changes without a branch point before ones with
# a branch point.
Augie Fackler
cvsps: add two more tiebreakers in cscmp...
r22267 if not d:
d = c(len(l.branchpoints), len(r.branchpoints))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 return d
Augie Fackler
cvsps: wrap cmp methods (deprecated) in functools.cmp_to_key...
r37903 changesets.sort(key=functools.cmp_to_key(cscmp))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# Collect tags
globaltags = {}
for c in changesets:
for e in c.entries:
for tag in e.tags:
# remember which is the latest changeset to have this tag
globaltags[tag] = c
for c in changesets:
Benoit Boissinot
convert: use set instead of dict
r8456 tags = set()
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 for e in c.entries:
Martin Geisler
convert/cvsps: use set.update for bulk update
r8483 tags.update(e.tags)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # remember tags only if this is the latest changeset to have it
Benoit Boissinot
convert: use set instead of dict
r8456 c.tags = sorted(tag for tag in tags if globaltags[tag] is c)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# Find parent changesets, handle {{mergetobranch BRANCHNAME}}
# by inserting dummy changesets with two parents, and handle
# {{mergefrombranch BRANCHNAME}} by setting two parents.
if mergeto is None:
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 mergeto = br'{{mergetobranch ([-\w]+)}}'
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if mergeto:
mergeto = re.compile(mergeto)
if mergefrom is None:
Augie Fackler
cvsps: add b prefixes to regular expressions...
r37901 mergefrom = br'{{mergefrombranch ([-\w]+)}}'
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if mergefrom:
mergefrom = re.compile(mergefrom)
Augie Fackler
formatting: blacken the codebase...
r43346 versions = {} # changeset index where we saw any particular file version
branches = {} # changeset index where we saw a branch
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 n = len(changesets)
i = 0
Matt Mackall
many, many trivial check-code fixups
r10282 while i < n:
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 c = changesets[i]
for f in c.entries:
versions[(f.rcs, f.revision)] = i
p = None
if c.branch in branches:
p = branches[c.branch]
else:
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 # first changeset on a new branch
# the parent is a changeset with the branch in its
# branchpoints such that it is the latest possible
# commit without any intervening, unrelated commits.
Gregory Szorc
global: use pycompat.xrange()...
r38806 for candidate in pycompat.xrange(i):
Henrik Stuart
convert: better support for CVS branchpoints (issue1447)...
r8756 if c.branch not in changesets[candidate].branchpoints:
if p is not None:
break
continue
p = candidate
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
c.parents = []
if p is not None:
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 p = changesets[p]
# Ensure no changeset has a synthetic changeset as a parent.
while p.synthetic:
Augie Fackler
formatting: blacken the codebase...
r43346 assert len(p.parents) <= 1, _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'synthetic changeset cannot have multiple parents'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 if p.parents:
p = p.parents[0]
else:
p = None
break
if p is not None:
c.parents.append(p)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 if c.mergepoint:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if c.mergepoint == b'HEAD':
Henrik Stuart
convert: added cvsnt mergepoint support
r7956 c.mergepoint = None
c.parents.append(changesets[branches[c.mergepoint]])
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if mergefrom:
m = mergefrom.search(c.comment)
if m:
m = m.group(1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if m == b'HEAD':
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 m = None
Greg Ward
cvsps: fix crash when log message refers to non-existent branch (issue1615).
r8171 try:
candidate = changesets[branches[m]]
except KeyError:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"warning: CVS commit message references "
b"non-existent branch %r:\n%s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (pycompat.bytestr(m), c.comment)
)
Greg Ward
issue1578: fix crash: do not use synthetic changesets as merge parents.
r7950 if m in branches and c.branch != m and not candidate.synthetic:
c.parents.append(candidate)
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
if mergeto:
m = mergeto.search(c.comment)
if m:
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 if m.groups():
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 m = m.group(1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if m == b'HEAD':
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 m = None
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 else:
Augie Fackler
formatting: blacken the codebase...
r43346 m = None # if no group found then merge to HEAD
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 if m in branches and c.branch != m:
# insert empty changeset for merge
Matt Mackall
many, many trivial check-code fixups
r10282 cc = changeset(
Augie Fackler
formatting: blacken the codebase...
r43346 author=c.author,
branch=m,
date=c.date,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 comment=b'convert-repo: CVS merge from branch %s'
Matt Mackall
many, many trivial check-code fixups
r10282 % c.branch,
Augie Fackler
formatting: blacken the codebase...
r43346 entries=[],
tags=[],
parents=[changesets[branches[m]], c],
)
Matt Mackall
cvsps: fix up some whitespace
r6688 changesets.insert(i + 1, cc)
branches[m] = i + 1
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
# adjust our loop counters now we have inserted a new entry
n += 1
i += 2
continue
branches[c.branch] = i
i += 1
Greg Ward
cvsps: recognize and eliminate CVS' synthetic "file added" revisions.
r7862 # Drop synthetic changesets (safe now that we have ensured no other
# changesets can have them as parents).
i = 0
while i < len(changesets):
if changesets[i].synthetic:
del changesets[i]
else:
i += 1
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 # Number changesets
for i, c in enumerate(changesets):
Matt Mackall
cvsps: fix up some whitespace
r6688 c.id = i + 1
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Frank Kingswood
convert: handle changeset sorting errors without traceback (issue3961)
r19505 if odd:
for l, r in odd:
if l.id is not None and r.id is not None:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'changeset %d is both before and after %d\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (l.id, r.id)
)
Frank Kingswood
convert: handle changeset sorting errors without traceback (issue3961)
r19505
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'%d changeset entries\n') % len(changesets))
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hook.hook(ui, None, b"cvschangesets", True, changesets=changesets)
Frank Kingswood
convert: implement two hooks in builtin cvsps
r10095
Frank Kingswood
convert: cvsps.py - code to generate changesets from a CVS repository
r6687 return changesets
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502
def debugcvsps(ui, *args, **opts):
Martin Geisler
convert/cvsps: wrap long lines
r8661 '''Read CVS rlog for current directory or named path in
repository, and convert the log to changesets based on matching
commit log entries and dates.
'''
Pulkit Goyal
py3: use pycompat.byteskwargs in hgext/convert/...
r36347 opts = pycompat.byteskwargs(opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b"new_cache"]:
cache = b"write"
elif opts[b"update_cache"]:
cache = b"update"
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 else:
cache = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revisions = opts[b"revisions"]
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502
try:
if args:
log = []
for d in args:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 log += createlog(ui, d, root=opts[b"root"], cache=cache)
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 log = createlog(ui, root=opts[b"root"], cache=cache)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except logerror as e:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b"%r\n" % e)
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changesets = createchangeset(ui, log, opts[b"fuzz"])
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 del log
# Print changesets (optionally filtered)
off = len(revisions)
Augie Fackler
formatting: blacken the codebase...
r43346 branches = {} # latest version number in each branch
ancestors = {} # parent branch
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 for cs in changesets:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b"ancestors"]:
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 if cs.branch not in branches and cs.parents and cs.parents[0].id:
Augie Fackler
formatting: blacken the codebase...
r43346 ancestors[cs.branch] = (
changesets[cs.parents[0].id - 1].branch,
cs.parents[0].id,
)
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 branches[cs.branch] = cs.id
# limit by branches
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if (
opts[b"branches"]
and (cs.branch or b'HEAD') not in opts[b"branches"]
):
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 continue
if not off:
# Note: trailing spaces on several lines here are needed to have
# bug-for-bug compatibility with cvsps.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b'---------------------\n')
ui.write((b'PatchSet %d \n' % cs.id))
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Date: %s\n'
% dateutil.datestr(cs.date, b'%Y/%m/%d %H:%M:%S %1%2')
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write((b'Author: %s\n' % cs.author))
ui.write((b'Branch: %s\n' % (cs.branch or b'HEAD')))
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Tag%s: %s \n'
Augie Fackler
formatting: blacken the codebase...
r43346 % (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 [b'', b's'][len(cs.tags) > 1],
b','.join(cs.tags) or b'(none)',
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
)
Frank Kingswood
cvsps: use commitids (when present) to detect changesets...
r18261 if cs.branchpoints:
Augie Fackler
cleanup: mark some ui.(status|note|warn|write) calls as not needing i18n...
r43350 ui.writenoi18n(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Branchpoints: %s \n' % b', '.join(sorted(cs.branchpoints))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b"parents"] and cs.parents:
Matt Mackall
many, many trivial check-code fixups
r10282 if len(cs.parents) > 1:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Parents: %s\n'
% (b','.join([(b"%d" % p.id) for p in cs.parents]))
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write((b'Parent: %d\n' % cs.parents[0].id))
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b"ancestors"]:
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 b = cs.branch
r = []
while b:
b, c = ancestors[b]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 r.append(b'%s:%d:%d' % (b or b"HEAD", c, branches[b]))
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 if r:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write((b'Ancestors: %s\n' % (b','.join(r))))
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502
Augie Fackler
cleanup: mark some ui.(status|note|warn|write) calls as not needing i18n...
r43350 ui.writenoi18n(b'Log:\n')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b'%s\n\n' % cs.comment)
Augie Fackler
cleanup: mark some ui.(status|note|warn|write) calls as not needing i18n...
r43350 ui.writenoi18n(b'Members: \n')
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 for f in cs.entries:
fn = f.file
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if fn.startswith(opts[b"prefix"]):
fn = fn[len(opts[b"prefix"]) :]
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'\t%s:%s->%s%s \n'
Augie Fackler
formatting: blacken the codebase...
r43346 % (
Augie Fackler
cvsps: portably convert int to bytes...
r37904 fn,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'.'.join([b"%d" % x for x in f.parent]) or b'INITIAL',
b'.'.join([(b"%d" % x) for x in f.revision]),
[b'', b'(DEAD)'][f.dead],
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.write(b'\n')
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502
# have we seen the start tag?
if revisions and off:
Augie Fackler
formatting: blacken the codebase...
r43346 if revisions[0] == (b"%d" % cs.id) or revisions[0] in cs.tags:
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 off = False
# see if we reached the end tag
Matt Mackall
many, many trivial check-code fixups
r10282 if len(revisions) > 1 and not off:
Augie Fackler
formatting: blacken the codebase...
r43346 if revisions[1] == (b"%d" % cs.id) or revisions[1] in cs.tags:
Frank Kingswood
Add debugcvsps command, replacing cvsps script
r7502 break