##// END OF EJS Templates
narrow: validate spec files are well-formed during clone (BC)...
narrow: validate spec files are well-formed during clone (BC) Previously, specfiles would get read then normalized. We want specfiles to be normalized on read so there is no confusion about what the format of specfiles should be. This commit validates the parsed result of --specfile. If entries aren't prefixed, an error is raised. Previously, validation would occur at exchange time, hence why we dropped a line of test output related to server iteraction. Differential Revision: https://phab.mercurial-scm.org/D4526

File last commit:

r37676:34758397 default
r39577:8301741e default
Show More
cvs.py
301 lines | 10.6 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # cvs.py: CVS conversion code inspired by hg-cvs-import and git-cvsimport
#
# Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
#
# 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: cvs use absolute_import
r28413 from __future__ import absolute_import
Brendan Cully
Split convert extension into common and repository type modules
r4536
timeless
convert: cvs use absolute_import
r28413 import errno
import os
import re
import socket
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
timeless
convert: cvs use absolute_import
r28413 from mercurial import (
encoding,
error,
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 pycompat,
timeless
convert: cvs use absolute_import
r28413 util,
)
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 from mercurial.utils import (
dateutil,
procutil,
)
Brendan Cully
Split convert extension into common and repository type modules
r4536
timeless
convert: cvs use absolute_import
r28413 from . import (
common,
cvsps,
)
timeless
pycompat: switch to util.stringio for py3 compat
r28861 stringio = util.stringio
timeless
convert: cvs use absolute_import
r28413 checktool = common.checktool
commit = common.commit
converter_source = common.converter_source
makedatetimestamp = common.makedatetimestamp
NoRepo = common.NoRepo
Brendan Cully
Split convert extension into common and repository type modules
r4536
class convert_cvs(converter_source):
Matt Harbison
convert: save an indicator of the repo type for sources and sinks...
r35168 def __init__(self, ui, repotype, path, revs=None):
super(convert_cvs, self).__init__(ui, repotype, path, revs=revs)
Brendan Cully
convert: call superclass init from engine init functions
r4807
Brendan Cully
Split convert extension into common and repository type modules
r4536 cvs = os.path.join(path, "CVS")
if not os.path.exists(cvs):
Martin Geisler
convert: mark strings for translation
r10939 raise NoRepo(_("%s does not look like a CVS checkout") % path)
Brendan Cully
Split convert extension into common and repository type modules
r4536
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690 checktool('cvs')
Patrick Mezard
convert: fail if an external required tool is not found
r5497
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self.changeset = None
Brendan Cully
Split convert extension into common and repository type modules
r4536 self.files = {}
self.tags = {}
self.lastbranch = {}
self.socket = None
Augie Fackler
convert: open all files in binary mode...
r36149 self.cvsroot = open(os.path.join(cvs, "Root"), 'rb').read()[:-1]
self.cvsrepo = open(os.path.join(cvs, "Repository"), 'rb').read()[:-1]
Brodie Rao
convert: use encoding.encoding instead of locale.getpreferredencoding()...
r11987 self.encoding = encoding.encoding
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690
Brendan Cully
Split convert extension into common and repository type modules
r4536 self._connect()
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 def _parse(self):
if self.changeset is not None:
Brendan Cully
Split convert extension into common and repository type modules
r4536 return
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self.changeset = {}
Brendan Cully
Split convert extension into common and repository type modules
r4536
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 maxrev = 0
Durham Goode
convert: add support for specifying multiple revs...
r25748 if self.revs:
if len(self.revs) > 1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cvs source does not support specifying '
Durham Goode
convert: add support for specifying multiple revs...
r25748 'multiple revs'))
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 # TODO: handle tags
try:
# patchset number?
Durham Goode
convert: add support for specifying multiple revs...
r25748 maxrev = int(self.revs[0])
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 except ValueError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('revision %s is not a patchset number')
Durham Goode
convert: add support for specifying multiple revs...
r25748 % self.revs[0])
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 d = pycompat.getcwd()
Brendan Cully
Split convert extension into common and repository type modules
r4536 try:
os.chdir(self.path)
id = None
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 cache = 'update'
Boris Feld
configitems: register the 'convert.cvsps.cache' config...
r34152 if not self.ui.configbool('convert', 'cvsps.cache'):
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 cache = None
db = cvsps.createlog(self.ui, cache=cache)
db = cvsps.createchangeset(self.ui, db,
Boris Feld
configitems: register the 'convert.cvsps.fuzz' config
r34153 fuzz=int(self.ui.config('convert', 'cvsps.fuzz')),
Boris Feld
configitems: register the 'convert.cvsps.mergeto' config
r34155 mergeto=self.ui.config('convert', 'cvsps.mergeto'),
Boris Feld
configitems: register the 'convert.cvsps.mergefrom' config
r34154 mergefrom=self.ui.config('convert', 'cvsps.mergefrom'))
Thomas Arendsen Hein
CVS convert: Find correct parent for new branch (issue704)...
r5920
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 for cs in db:
Matt Mackall
many, many trivial check-code fixups
r10282 if maxrev and cs.id > maxrev:
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 break
Pulkit Goyal
py3: use b"%d" instead of str() to convert integers to bytes...
r37676 id = (b"%d" % cs.id)
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 cs.author = self.recode(cs.author)
self.lastbranch[cs.branch] = id
cs.comment = self.recode(cs.comment)
Julian Cowley
convert: add config option to use the local time zone...
r17974 if self.ui.configbool('convert', 'localtimezone'):
cs.date = makedatetimestamp(cs.date[0])
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 date = dateutil.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2')
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 self.tags.update(dict.fromkeys(cs.tags, id))
Thomas Arendsen Hein
CVS convert: Find correct parent for new branch (issue704)...
r5920
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 files = {}
for f in cs.entries:
Pulkit Goyal
py3: use b"%d" instead of str() to convert integers to bytes...
r37676 files[f.file] = "%s%s" % ('.'.join([(b"%d" % x)
Matt Mackall
many, many trivial check-code fixups
r10282 for x in f.revision]),
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 ['', '(DEAD)'][f.dead])
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 # add current commit to set
c = commit(author=cs.author, date=date,
Pulkit Goyal
py3: use b"%d" instead of str() to convert integers to bytes...
r37676 parents=[(b"%d" % p.id) for p in cs.parents],
Patrick Mezard
convert/cvs: stop supporting external cvsps
r9543 desc=cs.comment, branch=cs.branch or '')
self.changeset[id] = c
self.files[id] = files
Brendan Cully
Split convert extension into common and repository type modules
r4536
self.heads = self.lastbranch.values()
finally:
os.chdir(d)
def _connect(self):
root = self.cvsroot
conntype = None
user, host = None, None
cmd = ['cvs', 'server']
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.status(_("connecting to %s\n") % root)
Brendan Cully
Split convert extension into common and repository type modules
r4536
if root.startswith(":pserver:"):
root = root[9:]
m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
root)
if m:
conntype = "pserver"
user, passw, serv, port, root = m.groups()
if not user:
user = "anonymous"
Thomas Arendsen Hein
CVS import: Support new-style .cvspass-file format....
r5082 if not port:
port = 2401
Brendan Cully
Split convert extension into common and repository type modules
r4536 else:
Thomas Arendsen Hein
CVS import: Support new-style .cvspass-file format....
r5082 port = int(port)
format0 = ":pserver:%s@%s:%s" % (user, serv, root)
format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)
Brendan Cully
Split convert extension into common and repository type modules
r4536
if not passw:
passw = "A"
Edouard Gomez
convert: check existence of ~/.cvspass before reading it
r7442 cvspass = os.path.expanduser("~/.cvspass")
Thomas Arendsen Hein
Improvement to 14ce129cfcd: Use try/except and pass filename on errors...
r7444 try:
Augie Fackler
convert: open all files in binary mode...
r36149 pf = open(cvspass, 'rb')
Edouard Gomez
convert: check existence of ~/.cvspass before reading it
r7442 for line in pf.read().splitlines():
part1, part2 = line.split(' ', 1)
Brodie Rao
cleanup: eradicate long lines
r16683 # /1 :pserver:user@example.com:2401/cvsroot/foo
# Ah<Z
Edouard Gomez
convert: check existence of ~/.cvspass before reading it
r7442 if part1 == '/1':
part1, part2 = part2.split(' ', 1)
format = format1
Brodie Rao
cleanup: eradicate long lines
r16683 # :pserver:user@example.com:/cvsroot/foo Ah<Z
Edouard Gomez
convert: check existence of ~/.cvspass before reading it
r7442 else:
format = format0
if part1 == format:
passw = part2
break
pf.close()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Thomas Arendsen Hein
Improvement to 14ce129cfcd: Use try/except and pass filename on errors...
r7444 if inst.errno != errno.ENOENT:
if not getattr(inst, 'filename', None):
inst.filename = cvspass
raise
Brendan Cully
Split convert extension into common and repository type modules
r4536
sck = socket.socket()
sck.connect((serv, port))
sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
"END AUTH REQUEST", ""]))
if sck.recv(128) != "I LOVE YOU\n":
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("CVS pserver authentication failed"))
Brendan Cully
Split convert extension into common and repository type modules
r4536
self.writep = self.readp = sck.makefile('r+')
if not conntype and root.startswith(":local:"):
conntype = "local"
root = root[7:]
if not conntype:
# :ext:user@host/home/user/path/to/cvsroot
if root.startswith(":ext:"):
root = root[5:]
Pulkit Goyal
py3: make sure regexes are bytes...
r36411 m = re.match(br'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
Patrick Mezard
convert: avoid interpreting Windows path as CVS connection strings....
r5304 # Do not take Windows path "c:\foo\bar" for a connection strings
if os.path.isdir(root) or not m:
Brendan Cully
Split convert extension into common and repository type modules
r4536 conntype = "local"
else:
conntype = "rsh"
user, host, root = m.group(1), m.group(2), m.group(3)
if conntype != "pserver":
if conntype == "rsh":
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 5 of 5)
r30638 rsh = encoding.environ.get("CVS_RSH") or "ssh"
Brendan Cully
Split convert extension into common and repository type modules
r4536 if user:
cmd = [rsh, '-l', user, host] + cmd
else:
cmd = [rsh, host] + cmd
Patrick Mezard
convert: call popen2 in binary mode, with a command string.
r5303 # popen2 does not support argument lists under Windows
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 cmd = [procutil.shellquote(arg) for arg in cmd]
cmd = procutil.quotecommand(' '.join(cmd))
self.writep, self.readp = procutil.popen2(cmd)
Brendan Cully
Split convert extension into common and repository type modules
r4536
self.realroot = root
self.writep.write("Root %s\n" % root)
self.writep.write("Valid-responses ok error Valid-requests Mode"
" M Mbinary E Checked-in Created Updated"
" Merged Removed\n")
self.writep.write("valid-requests\n")
self.writep.flush()
r = self.readp.readline()
if not r.startswith("Valid-requests"):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('unexpected response from CVS server '
Matt Mackall
many, many trivial check-code fixups
r10282 '(expected "Valid-requests", but got %r)')
Greg Ward
convert/cvs: improve error message on unexpected server output.
r9095 % r)
Brendan Cully
Split convert extension into common and repository type modules
r4536 if "UseUnchanged" in r:
self.writep.write("UseUnchanged\n")
self.writep.flush()
r = self.readp.readline()
def getheads(self):
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self._parse()
Brendan Cully
Split convert extension into common and repository type modules
r4536 return self.heads
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 def getfile(self, name, rev):
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539
def chunkedread(fp, count):
Mads Kiilerich
fix trivial spelling errors
r17424 # file-objects returned by socket.makefile() do not handle
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 # large read() requests very well.
chunksize = 65536
timeless
pycompat: switch to util.stringio for py3 compat
r28861 output = stringio()
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 while count > 0:
data = fp.read(min(count, chunksize))
if not data:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("%d bytes missing from remote file")
Matt Mackall
many, many trivial check-code fixups
r10282 % count)
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 count -= len(data)
output.write(data)
return output.getvalue()
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 self._parse()
Brendan Cully
Split convert extension into common and repository type modules
r4536 if rev.endswith("(DEAD)"):
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None, None
Brendan Cully
Split convert extension into common and repository type modules
r4536
args = ("-N -P -kk -r %s --" % rev).split()
Patrick Mezard
convert: fix remote cvs file paths separator
r5305 args.append(self.cvsrepo + '/' + name)
Brendan Cully
Split convert extension into common and repository type modules
r4536 for x in args:
self.writep.write("Argument %s\n" % x)
self.writep.write("Directory .\n%s\nco\n" % self.realroot)
self.writep.flush()
data = ""
Mads Kiilerich
convert.cvs: Initialize state variable and abort on cvs error...
r10800 mode = None
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 while True:
Brendan Cully
Split convert extension into common and repository type modules
r4536 line = self.readp.readline()
if line.startswith("Created ") or line.startswith("Updated "):
self.readp.readline() # path
self.readp.readline() # entries
mode = self.readp.readline()[:-1]
count = int(self.readp.readline()[:-1])
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 data = chunkedread(self.readp, count)
Brendan Cully
Split convert extension into common and repository type modules
r4536 elif line.startswith(" "):
data += line[1:]
elif line.startswith("M "):
pass
elif line.startswith("Mbinary "):
count = int(self.readp.readline()[:-1])
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 data = chunkedread(self.readp, count)
Brendan Cully
Split convert extension into common and repository type modules
r4536 else:
if line == "ok\n":
Mads Kiilerich
convert.cvs: Initialize state variable and abort on cvs error...
r10800 if mode is None:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('malformed response from CVS'))
Brendan Cully
Split convert extension into common and repository type modules
r4536 return (data, "x" in mode and "x" or "")
elif line.startswith("E "):
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.warn(_("cvs server: %s\n") % line[2:])
Brendan Cully
Split convert extension into common and repository type modules
r4536 elif line.startswith("Remove"):
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 self.readp.readline()
Brendan Cully
Split convert extension into common and repository type modules
r4536 else:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("unknown CVS response: %s") % line)
Brendan Cully
Split convert extension into common and repository type modules
r4536
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def getchanges(self, rev, full):
if full:
timeless@mozdev.org
grammar: use does instead of do where appropriate
r26779 raise error.Abort(_("convert from cvs does not support --full"))
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self._parse()
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 return sorted(self.files[rev].iteritems()), {}, set()
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getcommit(self, rev):
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self._parse()
Brendan Cully
Split convert extension into common and repository type modules
r4536 return self.changeset[rev]
def gettags(self):
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self._parse()
Brendan Cully
Split convert extension into common and repository type modules
r4536 return self.tags
Alexis S. L. Carvalho
convert_cvs: add --filemap support
r5381
def getchangedfiles(self, rev, i):
Patrick Mezard
convert/cvs: delay CVS log parsing after initialization (issue1581/2)...
r8048 self._parse()
Matt Mackall
replace util.sort with sorted built-in...
r8209 return sorted(self.files[rev])