##// END OF EJS Templates
hg: obtain lock when creating share from pooled repo (issue5104)...
hg: obtain lock when creating share from pooled repo (issue5104) There are race conditions between clients performing a shared clone to pooled storage: 1) Clients race to create the new shared repo in the pool directory 2) 1 client is seeding the repo in the pool directory and another goes to share it before it is fully cloned We prevent these race conditions by obtaining a lock in the pool directory that is derived from the name of the repo we will be accessing. To test this, a simple generic "lockdelay" extension has been added. The extension inserts an optional, configurable delay before or after lock acquisition. In the test, we delay 2 seconds after lock acquisition in the first process and 1 second before lock acquisition in the 2nd process. This means the first process has 1s to obtain the lock. There is a race condition here. If we encounter it in the wild, we could change the dummy extension to wait on the lock file to appear instead of relying on timing. But that's more complicated. Let's see what happens first.

File last commit:

r26779:aaa33ec3 default
r28289:d493d647 3.7.2 stable
Show More
cvs.py
280 lines | 10.3 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.
Brendan Cully
Split convert extension into common and repository type modules
r4536
Brodie Rao
convert: use encoding.encoding instead of locale.getpreferredencoding()...
r11987 import os, re, socket, errno
Patrick Mezard
convert: read CVS files in chunks (issue 800)...
r5539 from cStringIO import StringIO
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 from mercurial import encoding, util, error
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690 from mercurial.i18n import _
Brendan Cully
Split convert extension into common and repository type modules
r4536
Patrick Mezard
convert: fail if an external required tool is not found
r5497 from common import NoRepo, commit, converter_source, checktool
Julian Cowley
convert: add config option to use the local time zone...
r17974 from common import makedatetimestamp
Frank Kingswood
convert: cvs.py - Allow user to use built-in CVS changeset code....
r6690 import cvsps
Brendan Cully
Split convert extension into common and repository type modules
r4536
class convert_cvs(converter_source):
Durham Goode
convert: add support for specifying multiple revs...
r25748 def __init__(self, ui, path, revs=None):
super(convert_cvs, self).__init__(ui, 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
Alejandro Santos
compat: use open() instead of file() everywhere
r9031 self.cvsroot = open(os.path.join(cvs, "Root")).read()[:-1]
self.cvsrepo = open(os.path.join(cvs, "Repository")).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
Brendan Cully
Split convert extension into common and repository type modules
r4536 d = os.getcwd()
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'
if not self.ui.configbool('convert', 'cvsps.cache', True):
cache = None
db = cvsps.createlog(self.ui, cache=cache)
db = cvsps.createchangeset(self.ui, db,
fuzz=int(self.ui.config('convert', 'cvsps.fuzz', 60)),
mergeto=self.ui.config('convert', 'cvsps.mergeto', None),
mergefrom=self.ui.config('convert', 'cvsps.mergefrom', None))
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
id = str(cs.id)
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])
FUJIWARA Katsunori
i18n: use locale insensitive format for datetimes as intermediate representation (issue3398)...
r16514 date = util.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:
Matt Mackall
many, many trivial check-code fixups
r10282 files[f.file] = "%s%s" % ('.'.join([str(x)
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,
parents=[str(p.id) for p in cs.parents],
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:
Edouard Gomez
convert: check existence of ~/.cvspass before reading it
r7442 pf = open(cvspass)
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:]
m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', 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":
Kostantinos Koukopoulos
convert should use default value when CVS_RSH is not set, that value...
r5860 rsh = os.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
cmd = [util.shellquote(arg) for arg in cmd]
cmd = util.quotecommand(' '.join(cmd))
Martin Geisler
util: remove ignored mode argument in popen[23]
r8339 self.writep, self.readp = util.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
output = StringIO()
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])