##// END OF EJS Templates
manifest: avoid corruption by dropping removed files with pure (issue5801)...
manifest: avoid corruption by dropping removed files with pure (issue5801) Previously, removed files would simply be marked by overwriting the first byte with NUL and dropping their entry in `self.position`. But no effort was made to ignore them when compacting the dictionary into text form. This allowed them to slip into the manifest revision, since the code seems to be trying to minimize the string operations by copying as large a chunk as possible. As part of this, compact() walks the existing text based on entries in the `positions` list, and consumed everything up to the next position entry. This typically resulted in a ValueError complaining about unsorted manifest entries. Sometimes it seems that files do get dropped in large repos- it seems to correspond to there being a new entry that would take the same slot. A much more trivial problem is that if the only changes were removals, `_compact()` didn't even run because `__delitem__` doesn't add anything to `self.extradata`. Now there's an explicit variable to flag this, both to allow `_compact()` to run, and to avoid searching the manifest in cases where there are no removals. In practice, this behavior was mostly obscured by the check in fastdelta() which takes a different path that explicitly drops removed files if there are fewer than 1000 changes. However, timeless has a repo where after rebasing tens of commits, a totally different path[1] is taken that bypasses the change count check and hits this problem. [1] https://www.mercurial-scm.org/repo/hg/file/2338bdea4474/mercurial/manifest.py#l1511

File last commit:

r41925:aaad36b8 default
r42569:0546ead3 stable
Show More
subversion.py
1368 lines | 53.1 KiB | text/x-python | PythonLexer
Daniel Holth
convert extension: Add SVN converter
r4765 # Subversion 1.4/1.5 Python API backend
#
# Copyright(C) 2007 Daniel Holth et al
timeless
convert: subversion use absolute_import
r28408 from __future__ import absolute_import
Daniel Holth
convert extension: Add SVN converter
r4765
timeless
convert: subversion use absolute_import
r28408 import os
import re
Augie Fackler
convert: move import of xml.minidom.dom to its own line for check-code
r19787 import xml.dom.minidom
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
timeless
convert: subversion use absolute_import
r28408 from mercurial import (
encoding,
error,
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 pycompat,
timeless
convert: subversion use absolute_import
r28408 util,
Pierre-Yves David
vfs: use 'vfs' module directly in 'hgext.convert'...
r31246 vfs as vfsmod,
timeless
convert: subversion use absolute_import
r28408 )
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,
)
Daniel Holth
convert extension: Add SVN converter
r4765
timeless
convert: subversion use absolute_import
r28408 from . import common
Pulkit Goyal
py3: conditionalize cPickle import by adding in util...
r29324 pickle = util.pickle
timeless
pycompat: switch to util.stringio for py3 compat
r28861 stringio = util.stringio
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 propertycache = util.propertycache
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511
timeless
convert: subversion use absolute_import
r28408 commandline = common.commandline
commit = common.commit
converter_sink = common.converter_sink
converter_source = common.converter_source
decodeargs = common.decodeargs
encodeargs = common.encodeargs
makedatetimestamp = common.makedatetimestamp
mapfile = common.mapfile
MissingTool = common.MissingTool
NoRepo = common.NoRepo
Daniel Holth
convert extension: Add SVN converter
r4765 # Subversion stuff. Works best with very recent Python SVN bindings
# e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing
# these bindings.
Brendan Cully
convert: activate subversion engine...
r4766 try:
Brendan Cully
convert svn: try to extract URL from source if it is a working directory
r5010 import svn
import svn.client
Brendan Cully
convert: activate subversion engine...
r4766 import svn.core
import svn.ra
import svn.delta
FUJIWARA Katsunori
convert: make subversion import transport locally...
r28459 from . import transport
Ronny Pfannschmidt
convert: hide svn deprecation warnings
r8221 import warnings
warnings.filterwarnings('ignore',
module='svn.core',
category=DeprecationWarning)
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 svn.core.SubversionException # trigger import to catch error
Ronny Pfannschmidt
convert: hide svn deprecation warnings
r8221
Brendan Cully
convert: activate subversion engine...
r4766 except ImportError:
Azhagu Selvan SP
convert/svn: abort operation when python bindings are not available...
r13480 svn = None
Daniel Holth
convert extension: Add SVN converter
r4765
Patrick Mezard
convert: be even more tolerant when detecting svn tags...
r7381 class SvnPathNotFound(Exception):
pass
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 def revsplit(rev):
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 """Parse a revision string and return (uuid, path, revnum).
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> revsplit(b'svn:a2147622-4a9f-4db4-a8d3-13562ff547b2'
... b'/proj%20B/mytrunk/mytrunk@1')
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 ('a2147622-4a9f-4db4-a8d3-13562ff547b2', '/proj%20B/mytrunk/mytrunk', 1)
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> revsplit(b'svn:8af66a51-67f5-4354-b62c-98d67cc7be1d@1')
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 ('', '', 1)
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> revsplit(b'@7')
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 ('', '', 7)
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> revsplit(b'7')
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 ('', '', 0)
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> revsplit(b'bad')
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 ('', '', 0)
"""
parts = rev.rsplit('@', 1)
revnum = 0
if len(parts) > 1:
revnum = int(parts[1])
parts = parts[0].split('/', 1)
uuid = ''
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 mod = ''
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 if len(parts) > 1 and parts[0].startswith('svn:'):
uuid = parts[0][4:]
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 mod = '/' + parts[1]
Mads Kiilerich
convert: make subversion revsplit more stable when meeting revisions without @...
r20419 return uuid, mod, revnum
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 def quote(s):
# As of svn 1.7, many svn calls expect "canonical" paths. In
# theory, we should call svn.core.*canonicalize() on all paths
# before passing them to the API. Instead, we assume the base url
# is canonical and copy the behaviour of svn URL encoding function
# so we can extend it safely with new components. The "safe"
# characters were taken from the "svn_uri__char_validity" table in
# libsvn_subr/path.c.
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 return urlreq.quote(s, "!$&'()*+,-./:=@_~")
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599
Brendan Cully
convert: urlify svn repos if necessary....
r5008 def geturl(path):
Brendan Cully
convert svn: try to extract URL from source if it is a working directory
r5010 try:
Brendan Cully
convert svn: canonicalize path before calling url_from_path....
r5020 return svn.client.url_from_path(svn.core.svn_path_canonicalize(path))
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException:
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 # svn.client.url_from_path() fails with local repositories
Brendan Cully
convert svn: try to extract URL from source if it is a working directory
r5010 pass
Brendan Cully
convert: urlify svn repos if necessary....
r5008 if os.path.isdir(path):
Shun-ichi GOTO
convert: Accept local path on win32.
r5793 path = os.path.normpath(os.path.abspath(path))
Jun Wu
codemod: use pycompat.iswindows...
r34646 if pycompat.iswindows:
Shun-ichi GOTO
Use util.normpath() instead of direct path string operation....
r5842 path = '/' + util.normpath(path)
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 # Module URL is later compared with the repository URL returned
# by svn API, which is UTF-8.
path = encoding.tolocal(path)
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 path = 'file://%s' % quote(path)
return svn.core.svn_path_canonicalize(path)
Brendan Cully
convert: urlify svn repos if necessary....
r5008
Brendan Cully
convert: svn: add helper function for optrevs
r5117 def optrev(number):
optrev = svn.core.svn_opt_revision_t()
optrev.kind = svn.core.svn_opt_revision_number
optrev.value.number = number
return optrev
Bryan O'Sullivan
convert/subversion: work around memory leak in svn's python bindings...
r4946 class changedpath(object):
def __init__(self, p):
self.copyfrom_path = p.copyfrom_path
self.copyfrom_rev = p.copyfrom_rev
self.action = p.action
Brodie Rao
cleanup: eradicate long lines
r16683 def get_log_child(fp, url, paths, start, end, limit=0,
discover_changed_paths=True, strict_node_history=False):
Patrick Mezard
convert: replace fork with subprocess call.
r5127 protocol = -1
def receiver(orig_paths, revnum, author, date, message, pool):
Mads Kiilerich
convert: fix svn crash when svn.ra.get_log calls back with orig_paths=None...
r20057 paths = {}
Patrick Mezard
convert: replace fork with subprocess call.
r5127 if orig_paths is not None:
for k, v in orig_paths.iteritems():
Mads Kiilerich
convert: fix svn crash when svn.ra.get_log calls back with orig_paths=None...
r20057 paths[k] = changedpath(v)
pickle.dump((paths, revnum, author, date, message),
Thomas Arendsen Hein
Remove trailing spaces, fix indentation
r5143 fp, protocol)
Patrick Mezard
convert: replace fork with subprocess call.
r5127 try:
# Use an ra of our own so that our parent can consume
# our results without confusing the server.
t = transport.SvnRaTransport(url=url)
svn.ra.get_log(t.ra, paths, start, end, limit,
discover_changed_paths,
strict_node_history,
receiver)
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 except IOError:
# Caller may interrupt the iteration
pickle.dump(None, fp, protocol)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except Exception as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 pickle.dump(stringutil.forcebytestr(inst), fp, protocol)
Patrick Mezard
convert: replace fork with subprocess call.
r5127 else:
pickle.dump(None, fp, protocol)
Sascha Nemecek
convert: avoid closing ui.fout in subversion code (issue5807)...
r36529 fp.flush()
Patrick Mezard
convert: avoid svn log retrieval process cleanup...
r6397 # With large history, cleanup process goes crazy and suddenly
# consumes *huge* amount of memory. The output file being closed,
# there is no need for clean termination.
os._exit(0)
Patrick Mezard
convert: replace fork with subprocess call.
r5127
Thomas Arendsen Hein
Move debugsvnlog to subversion module.
r5139 def debugsvnlog(ui, **opts):
"""Fetch SVN log in a subprocess and channel them back to parent to
avoid memory collection issues.
"""
Mads Kiilerich
convert: check for failed svn import in debugsvnlog and abort cleanly...
r17053 if svn is None:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('debugsvnlog could not load Subversion python '
Mads Kiilerich
convert: check for failed svn import in debugsvnlog and abort cleanly...
r17053 'bindings'))
Yuya Nishihara
convert: have debugsvnlog obtain standard streams from ui...
r30261 args = decodeargs(ui.fin.read())
get_log_child(ui.fout, *args)
Thomas Arendsen Hein
Move debugsvnlog to subversion module.
r5139
Benoit Boissinot
use new style classes
r8778 class logstream(object):
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 """Interruptible revision log iterator."""
def __init__(self, stdout):
self._stdout = stdout
def __iter__(self):
while True:
Patrick Mezard
convert/svn: better error when hg cannot call itself (issue1838)
r9587 try:
entry = pickle.load(self._stdout)
except EOFError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('Mercurial failed to run itself, check'
Patrick Mezard
convert/svn: better error when hg cannot call itself (issue1838)
r9587 ' hg executable is in PATH'))
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 try:
orig_paths, revnum, author, date, message = entry
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 except (TypeError, ValueError):
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 if entry is None:
break
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("log stream exception '%s'") % entry)
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 yield entry
def close(self):
if self._stdout:
self._stdout.close()
self._stdout = None
Mads Kiilerich
convert: secret config option for disabling debugsvnlog...
r20420 class directlogstream(list):
"""Direct revision log iterator.
This can be used for debugging and development but it will probably leak
memory and is not suitable for real conversions."""
def __init__(self, url, paths, start, end, limit=0,
discover_changed_paths=True, strict_node_history=False):
def receiver(orig_paths, revnum, author, date, message, pool):
paths = {}
if orig_paths is not None:
for k, v in orig_paths.iteritems():
paths[k] = changedpath(v)
self.append((paths, revnum, author, date, message))
# Use an ra of our own so that our parent can consume
# our results without confusing the server.
t = transport.SvnRaTransport(url=url)
svn.ra.get_log(t.ra, paths, start, end, limit,
discover_changed_paths,
strict_node_history,
receiver)
def close(self):
pass
Augie Fackler
convert: Improved svn source detection.
r8074
# Check to see if the given path is a local Subversion repo. Verify this by
# looking for several svn-specific files and directories in the given
# directory.
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 def filecheck(ui, path, proto):
Matt Mackall
many, many trivial check-code fixups
r10282 for x in ('locks', 'hooks', 'format', 'db'):
Augie Fackler
convert: Improved svn source detection.
r8074 if not os.path.exists(os.path.join(path, x)):
return False
return True
# Check to see if a given path is the root of an svn repo over http. We verify
# this by requesting a version-controlled URL we know can't exist and looking
# for the svn-specific "not found" XML.
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 def httpcheck(ui, path, proto):
try:
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 opener = urlreq.buildopener()
Augie Fackler
convert: open all files in binary mode...
r36149 rsp = opener.open('%s://%s/!svn/ver/0/.svn' % (proto, path), 'rb')
Matt Mackall
many, many trivial check-code fixups
r10282 data = rsp.read()
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 except urlerr.httperror as inst:
Patrick Mezard
convert/svn: fix HTTP detection bug introduced by 1b2516a547d4...
r9838 if inst.code != 404:
# Except for 404 we cannot know for sure this is not an svn repo
Patrick Mezard
convert/svn: fix warning when repo detection failed
r9860 ui.warn(_('svn: cannot probe remote repository, assume it could '
'be a subversion repository. Use --source-type if you '
'know better.\n'))
Patrick Mezard
convert/svn: fix HTTP detection bug introduced by 1b2516a547d4...
r9838 return True
data = inst.fp.read()
Brodie Rao
cleanup: replace naked excepts with except Exception: ...
r16689 except Exception:
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 # Could be urlerr.urlerror if the URL is invalid or anything else.
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 return False
Patrick Mezard
convert/svn: fix HTTP detection bug introduced by 1b2516a547d4...
r9838 return '<m:human-readable errcode="160013">' in data
Augie Fackler
convert: Improved svn source detection.
r8074
protomap = {'http': httpcheck,
'https': httpcheck,
'file': filecheck,
}
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 def issvnurl(ui, url):
Edouard Gomez
convert: default to file protocol when no :// found for svn repo url...
r8764 try:
proto, path = url.split('://', 1)
Grauw
Fix issue 1782 don't do url2pathname conversion for urls...
r9521 if proto == 'file':
Jun Wu
codemod: use pycompat.iswindows...
r34646 if (pycompat.iswindows and path[:1] == '/'
Pulkit Goyal
py3: replace os.name with pycompat.osname (part 2 of 2)
r30640 and path[1:2].isalpha() and path[2:6].lower() == '%3a/'):
Mads Kiilerich
convert: accept Subversion 'file:///c%3A/svnrepo' syntax on Windows...
r17052 path = path[:2] + ':/' + path[6:]
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 path = urlreq.url2pathname(path)
Edouard Gomez
convert: default to file protocol when no :// found for svn repo url...
r8764 except ValueError:
proto = 'file'
path = os.path.abspath(url)
Grauw
Fix issue 1782 don't do url2pathname conversion for urls...
r9521 if proto == 'file':
FUJIWARA Katsunori
i18n: use util.pconvert() instead of 'str.replace()' for problematic encoding...
r16067 path = util.pconvert(path)
Patrick Mezard
convert/subversion: fix default URL checker prototype
r10885 check = protomap.get(proto, lambda *args: False)
Augie Fackler
convert: Improved svn source detection.
r8074 while '/' in path:
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 if check(ui, path, proto):
Augie Fackler
convert: Improved svn source detection.
r8074 return True
path = path.rsplit('/', 1)[0]
return False
Daniel Holth
convert extension: Add SVN converter
r4765 # SVN conversion code stolen from bzr-svn and tailor
Patrick Mezard
convert: document the subversion conversion model
r5876 #
# Subversion looks like a versioned filesystem, branches structures
# are defined by conventions and not enforced by the tool. First,
# we define the potential branches (modules) as "trunk" and "branches"
# children directories. Revisions are then identified by their
# module and revision number (and a repository identifier).
#
# The revision graph is really a tree (or a forest). By default, a
# revision parent is the previous revision in the same module. If the
# module directory is copied/moved from another module then the
# revision is the module root and its parent the source revision in
# the parent module. A revision has at most one parent.
#
Bryan O'Sullivan
convert: rename convert_svn to svn_source
r5438 class svn_source(converter_source):
Matt Harbison
convert: save an indicator of the repo type for sources and sinks...
r35168 def __init__(self, ui, repotype, url, revs=None):
super(svn_source, self).__init__(ui, repotype, url, revs=revs)
Brendan Cully
convert: call superclass init from engine init functions
r4807
Matt Mackall
convert: attempt to check repo type before checking for tool
r7973 if not (url.startswith('svn://') or url.startswith('svn+ssh://') or
(os.path.exists(url) and
os.path.exists(os.path.join(url, '.svn'))) or
Patrick Mezard
convert/svn: delegate to svn bindings if HTTP probe fails...
r9829 issvnurl(ui, url)):
Martin Geisler
convert: mark strings for translation
r10939 raise NoRepo(_("%s does not look like a Subversion repository")
% url)
Azhagu Selvan SP
convert/svn: abort operation when python bindings are not available...
r13480 if svn is None:
Martin Geisler
convert: lowercase status and abort messages
r16925 raise MissingTool(_('could not load Subversion python bindings'))
Patrick Mezard
convert: improve reporting of invalid svn bindings
r7447
try:
version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
if version < (1, 4):
raise MissingTool(_('Subversion python bindings %d.%d found, '
'1.4 or later required') % version)
except AttributeError:
raise MissingTool(_('Subversion python bindings are too old, 1.4 '
'or later required'))
Brendan Cully
convert: activate subversion engine...
r4766
Brendan Cully
convert: svn: use revmap to parse only new revisions in incremental conversions
r4813 self.lastrevs = {}
Brendan Cully
convert: activate subversion engine...
r4766 latest = None
Daniel Holth
convert extension: Add SVN converter
r4765 try:
# Support file://path@rev syntax. Useful e.g. to convert
# deleted branches.
Bryan O'Sullivan
convert/subversion.py: str.rsplit is not available in Python 2.3
r4927 at = url.rfind('@')
if at >= 0:
Matt Mackall
many, many trivial check-code fixups
r10282 latest = int(url[at + 1:])
Bryan O'Sullivan
convert/subversion.py: str.rsplit is not available in Python 2.3
r4927 url = url[:at]
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 except ValueError:
Brendan Cully
convert: activate subversion engine...
r4766 pass
Brendan Cully
convert: urlify svn repos if necessary....
r5008 self.url = geturl(url)
Daniel Holth
convert extension: Add SVN converter
r4765 self.encoding = 'UTF-8' # Subversion is always nominal UTF-8
try:
Brendan Cully
convert: urlify svn repos if necessary....
r5008 self.transport = transport.SvnRaTransport(url=self.url)
Daniel Holth
convert extension: Add SVN converter
r4765 self.ra = self.transport.ra
Bryan O'Sullivan
convert/subversion: work around memory leak in svn's python bindings...
r4946 self.ctx = self.transport.client
Patrick Mezard
convert: properly encode subversion URLs (issue 1224)
r7074 self.baseurl = svn.ra.get_repos_root(self.ra)
Patrick Mezard
convert: fix subpaths detection in svn source
r6538 # Module is either empty or a repository path starting with
# a slash and not ending with a slash.
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 self.module = urlreq.unquote(self.url[len(self.baseurl):])
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 self.prevmodule = None
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 self.rootmodule = self.module
Daniel Holth
convert extension: Add SVN converter
r4765 self.commits = {}
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 self.paths = {}
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 self.uuid = svn.ra.get_uuid(self.ra)
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException:
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Augie Fackler
convert: on svn failure, note libsvn version (issue4043)...
r23583 svnversion = '%d.%d.%d' % (svn.core.SVN_VER_MAJOR,
svn.core.SVN_VER_MINOR,
svn.core.SVN_VER_MICRO)
raise NoRepo(_("%s does not look like a Subversion repository "
"to libsvn version %s")
% (self.url, svnversion))
Daniel Holth
convert extension: Add SVN converter
r4765
Durham Goode
convert: add support for specifying multiple revs...
r25748 if revs:
if len(revs) > 1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('subversion source does not support '
Durham Goode
convert: add support for specifying multiple revs...
r25748 'specifying multiple revisions'))
Thomas Arendsen Hein
raise util.Abort again if specified revision is not an integer....
r5145 try:
Durham Goode
convert: add support for specifying multiple revs...
r25748 latest = int(revs[0])
Thomas Arendsen Hein
raise util.Abort again if specified revision is not an integer....
r5145 except ValueError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('svn: revision %s is not an integer') %
Durham Goode
convert: add support for specifying multiple revs...
r25748 revs[0])
Thomas Arendsen Hein
raise util.Abort again if specified revision is not an integer....
r5145
Augie Fackler
convert: register missed subversion config items...
r34891 trunkcfg = self.ui.config('convert', 'svn.trunk')
if trunkcfg is None:
trunkcfg = 'trunk'
self.trunkname = trunkcfg.strip('/')
Boris Feld
configitems: register the 'convert.svn.startrev' config
r34177 self.startrev = self.ui.config('convert', 'svn.startrev')
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 try:
self.startrev = int(self.startrev)
if self.startrev < 0:
self.startrev = 0
except ValueError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('svn: start revision %s is not an integer')
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 % self.startrev)
Mads Kiilerich
convert: handle invalid subversion source paths
r14152 try:
self.head = self.latest(self.module, latest)
except SvnPathNotFound:
self.head = None
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 if not self.head:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no revision found in module %s')
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 % self.module)
Patrick Mezard
convert: fix svn_source.latest()
r5955 self.last_changed = self.revnum(self.head)
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 self._changescache = (None, None)
Daniel Holth
convert extension: Add SVN converter
r4765
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 if os.path.exists(os.path.join(url, '.svn/entries')):
self.wc = url
else:
self.wc = None
self.convertfp = None
Bryan O'Sullivan
convert: abstract map files into a class
r5510 def setrevmap(self, revmap):
Brendan Cully
convert: svn code movement (no actual changes)
r4840 lastrevs = {}
Augie Fackler
py3: use default dict iterator instead of iterkeys...
r36313 for revid in revmap:
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 uuid, module, revnum = revsplit(revid)
Brendan Cully
convert: svn code movement (no actual changes)
r4840 lastrevnum = lastrevs.setdefault(module, revnum)
if revnum > lastrevnum:
lastrevs[module] = revnum
self.lastrevs = lastrevs
Bryan O'Sullivan
convert/subversion.py: fix bad assumptions about SVN path naming...
r4925 def exists(self, path, optrev):
try:
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 svn.client.ls(self.url.rstrip('/') + '/' + quote(path),
Bryan O'Sullivan
convert/subversion.py: fix bad assumptions about SVN path naming...
r4925 optrev, False, self.ctx)
Kirill Smelkov
convert: svn -- fix 'exists'...
r5461 return True
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException:
Kirill Smelkov
convert: svn -- fix 'exists'...
r5461 return False
Bryan O'Sullivan
convert/subversion.py: fix bad assumptions about SVN path naming...
r4925
Brendan Cully
convert: svn code movement (no actual changes)
r4840 def getheads(self):
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854
Patrick Mezard
convert: check svn branches are directories
r6491 def isdir(path, revnum):
Patrick Mezard
convert: remove leading slash from ra.check_path inputs (issue 1236)
r6848 kind = self._checkpath(path, revnum)
Patrick Mezard
convert: check svn branches are directories
r6491 return kind == svn.core.svn_node_dir
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 def getcfgpath(name, rev):
cfgpath = self.ui.config('convert', 'svn.' + name)
Patrick Mezard
convert: allow svn trunk/branches/tags detection to be skipped...
r6172 if cfgpath is not None and cfgpath.strip() == '':
return None
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 path = (cfgpath or name).strip('/')
if not self.exists(path, rev):
Pavel Boldin
convert.svn: branch name which equals trunk means `default' branch (issue2653)...
r13494 if self.module.endswith(path) and name == 'trunk':
# we are converting from inside this directory
return None
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 if cfgpath:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('expected %s to be at %r, but not found'
) % (name, path))
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 return None
self.ui.note(_('found %s at %r\n') % (name, path))
return path
Brendan Cully
convert: svn: add helper function for optrevs
r5117 rev = optrev(self.last_changed)
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 oldmodule = ''
trunk = getcfgpath('trunk', rev)
Patrick Mezard
convert: allow tags detection to be disabled...
r6400 self.tags = getcfgpath('tags', rev)
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 branches = getcfgpath('branches', rev)
# If the project has a trunk or branches, we will extract heads
# from them. We keep the project root otherwise.
if trunk:
oldmodule = self.module or ''
Bryan O'Sullivan
convert/subversion.py: fix bad assumptions about SVN path naming...
r4925 self.module += '/' + trunk
Patrick Mezard
convert: fix svn_source.latest()
r5955 self.head = self.latest(self.module, self.last_changed)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 if not self.head:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no revision found in module %s')
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 % self.module)
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854
# First head in the list is the module's head
self.heads = [self.head]
Patrick Mezard
convert: allow tags detection to be disabled...
r6400 if self.tags is not None:
self.tags = '%s/%s' % (oldmodule , (self.tags or 'tags'))
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854
# Check if branches bring a few more heads to the list
if branches:
rpath = self.url.strip('/')
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 branchnames = svn.client.ls(rpath + '/' + quote(branches),
Patrick Mezard
convert: properly encode subversion URLs (issue 1224)
r7074 rev, False, self.ctx)
Mads Kiilerich
convert: process subversion branch in a sorted order
r18374 for branch in sorted(branchnames):
Edouard Gomez
convert: separate trunk detection from branch layout detection...
r5854 module = '%s/%s/%s' % (oldmodule, branches, branch)
Patrick Mezard
convert: check svn branches are directories
r6491 if not isdir(module, self.last_changed):
continue
Patrick Mezard
convert: fix svn_source.latest()
r5955 brevid = self.latest(module, self.last_changed)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 if not brevid:
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 self.ui.note(_('ignoring empty branch %s\n') % branch)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 continue
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.note(_('found branch %s at %d\n') %
Patrick Mezard
convert: fix svn_source.latest()
r5955 (branch, self.revnum(brevid)))
self.heads.append(brevid)
Kirill Smelkov
convert: svn -- fix tags handling...
r5462
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 if self.startrev and self.heads:
if len(self.heads) > 1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('svn: start revision is not supported '
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 'with more than one branch'))
revnum = self.revnum(self.heads[0])
if revnum < self.startrev:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Mackall
many, many trivial check-code fixups
r10282 _('svn: no revision found after start revision %d')
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 % self.startrev)
Brendan Cully
convert: svn code movement (no actual changes)
r4840 return self.heads
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def _getchanges(self, rev, full):
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 (paths, parents) = self.paths[rev]
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 copies = {}
Patrick Mezard
convert: checkout svn root revisions...
r5956 if parents:
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 files, self.removed, copies = self.expandpaths(rev, paths, parents)
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if full or not parents:
Patrick Mezard
convert: checkout svn root revisions...
r5956 # Perform a full checkout on roots
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 uuid, module, revnum = revsplit(rev)
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 entries = svn.client.ls(self.baseurl + quote(module),
Patrick Mezard
convert: properly encode subversion URLs (issue 1224)
r7074 optrev(revnum), True, self.ctx)
Matt Mackall
many, many trivial check-code fixups
r10282 files = [n for n, e in entries.iteritems()
Patrick Mezard
convert: checkout svn root revisions...
r5956 if e.kind == svn.core.svn_node_file]
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 self.removed = set()
Patrick Mezard
convert: checkout svn root revisions...
r5956
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 files.sort()
files = zip(files, [rev] * len(files))
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 return (files, copies)
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def getchanges(self, rev, full):
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 # reuse cache from getchangedfiles
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if self._changescache[0] == rev and not full:
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 (files, copies) = self._changescache[1]
else:
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 (files, copies) = self._getchanges(rev, full)
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 # caller caches the result, so free it here to release memory
del self.paths[rev]
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 return (files, copies, set())
Brendan Cully
convert: svn code movement (no actual changes)
r4840
Alexis S. L. Carvalho
convert_svn: add --filemap support
r5382 def getchangedfiles(self, rev, i):
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 # called from filemap - cache computed values for reuse in getchanges
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 (files, copies) = self._getchanges(rev, False)
Mads Kiilerich
convert: refactor subversion getchanges and caching
r22298 self._changescache = (rev, (files, copies))
return [f[0] for f in files]
Alexis S. L. Carvalho
convert_svn: add --filemap support
r5382
Brendan Cully
convert: svn code movement (no actual changes)
r4840 def getcommit(self, rev):
if rev not in self.commits:
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 uuid, module, revnum = revsplit(rev)
Brendan Cully
convert: svn code movement (no actual changes)
r4840 self.module = module
self.reparent(module)
Patrick Mezard
convert: fetch less revisions when looking for a branch parent
r5875 # We assume that:
# - requests for revisions after "stop" come from the
# revision graph backward traversal. Cache all of them
# down to stop, they will be used eventually.
# - requests for revisions before "stop" come to get
# isolated branches parents. Just fetch what is needed.
Brendan Cully
convert: svn code movement (no actual changes)
r4840 stop = self.lastrevs.get(module, 0)
Patrick Mezard
convert: fetch less revisions when looking for a branch parent
r5875 if revnum < stop:
stop = revnum + 1
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871 self._fetch_revisions(revnum, stop)
Jesus Espino Garcia
convert: subversion convert abort on revision not found (issue 3205)
r15970 if rev not in self.commits:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('svn: revision %s not found') % revnum)
Mads Kiilerich
cleanup: fix some list comprehension redefinitions of existing vars...
r22201 revcommit = self.commits[rev]
Brendan Cully
convert: svn code movement (no actual changes)
r4840 # caller caches the result, so free it here to release memory
del self.commits[rev]
Mads Kiilerich
cleanup: fix some list comprehension redefinitions of existing vars...
r22201 return revcommit
Brendan Cully
convert: svn code movement (no actual changes)
r4840
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 def checkrevformat(self, revstr, mapname='splicemap'):
Ben Goswami
splicemap: improve error handling when source is subversion (issue2084)...
r19122 """ fails if revision format does not match the correct format"""
if not re.match(r'svn:[0-9a-f]{8,8}-[0-9a-f]{4,4}-'
Mateusz Kwapich
py3: use raw strings in line continuation (convert ext)...
r30132 r'[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]'
r'{12,12}(.*)\@[0-9]+$',revstr):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('%s entry %s is not a valid revision'
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 ' identifier') % (mapname, revstr))
Ben Goswami
splicemap: improve error handling when source is subversion (issue2084)...
r19122
Augie Fackler
convert: enable deterministic conversion progress bar for svn...
r22414 def numcommits(self):
return int(self.head.rsplit('@', 1)[1]) - self.startrev
Brendan Cully
convert: svn code movement (no actual changes)
r4840 def gettags(self):
tags = {}
Patrick Mezard
convert: allow svn trunk/branches/tags detection to be skipped...
r6172 if self.tags is None:
return tags
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Patrick Mezard
convert: follow svn tags history (issue953)
r6399 # svn tags are just a convention, project branches left in a
# 'tags' directory. There is no other relationship than
# ancestry, which is expensive to discover and makes them hard
# to update incrementally. Worse, past revisions may be
# referenced by tags far away in the future, requiring a deep
# history traversal on every calculation. Current code
# performs a single backward traversal, tracking moves within
# the tags directory (tag renaming) and recording a new tag
# everytime a project is copied from outside the tags
# directory. It also lists deleted tags, this behaviour may
# change in the future.
pendings = []
tagspath = self.tags
start = svn.ra.get_latest_revnum(self.ra)
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 stream = self._getlog([self.tags], start, self.startrev)
try:
for entry in stream:
origpaths, revnum, author, date, message = entry
Matt Mackall
convert: catch empty origpaths in svn gettags (issue3941)
r19468 if not origpaths:
origpaths = []
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 copies = [(e.copyfrom_path, e.copyfrom_rev, p) for p, e
in origpaths.iteritems() if e.copyfrom_path]
# Apply moves/copies from more specific to general
copies.sort(reverse=True)
Patrick Mezard
convert: follow svn tags history (issue953)
r6399
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 srctagspath = tagspath
if copies and copies[-1][2] == tagspath:
# Track tags directory moves
srctagspath = copies.pop()[0]
Patrick Mezard
convert: follow svn tags history (issue953)
r6399
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 for source, sourcerev, dest in copies:
if not dest.startswith(tagspath + '/'):
continue
for tag in pendings:
if tag[0].startswith(dest):
tagpath = source + tag[0][len(dest):]
tag[:2] = [tagpath, sourcerev]
break
else:
pendings.append([source, sourcerev, dest])
Patrick Mezard
convert/svn: ignore composite tags...
r8248
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 # Filter out tags with children coming from different
# parts of the repository like:
# /tags/tag.1 (from /trunk:10)
# /tags/tag.1/foo (from /branches/foo:12)
# Here/tags/tag.1 discarded as well as its children.
# It happens with tools like cvs2svn. Such tags cannot
# be represented in mercurial.
addeds = dict((p, e.copyfrom_path) for p, e
in origpaths.iteritems()
if e.action == 'A' and e.copyfrom_path)
badroots = set()
for destroot in addeds:
for source, sourcerev, dest in pendings:
if (not dest.startswith(destroot + '/')
or source.startswith(addeds[destroot] + '/')):
continue
badroots.add(destroot)
break
Patrick Mezard
convert/svn: ignore composite tags...
r8248
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 for badroot in badroots:
pendings = [p for p in pendings if p[2] != badroot
and not p[2].startswith(badroot + '/')]
Patrick Mezard
convert: follow svn tags history (issue953)
r6399
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 # Tell tag renamings from tag creations
Martin Geisler
convert: rename local variable
r15124 renamings = []
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 for source, sourcerev, dest in pendings:
tagname = dest.split('/')[-1]
if source.startswith(srctagspath):
Martin Geisler
convert: rename local variable
r15124 renamings.append([source, sourcerev, tagname])
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 continue
if tagname in tags:
# Keep the latest tag value
continue
# From revision may be fake, get one with changes
try:
tagid = self.latest(source, sourcerev)
if tagid and tagname not in tags:
tags[tagname] = tagid
except SvnPathNotFound:
# It happens when we are following directories
# we assumed were copied with their parents
# but were really created in the tag
# directory.
pass
Martin Geisler
convert: rename local variable
r15124 pendings = renamings
Aaron Digulla
convert/svn: close gettags() log stream (issue2196)
r11195 tagspath = srctagspath
finally:
stream.close()
Bryan O'Sullivan
convert/subversion: work around memory leak in svn's python bindings...
r4946 return tags
Brendan Cully
convert: svn code movement (no actual changes)
r4840
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 def converted(self, rev, destrev):
if not self.wc:
return
if self.convertfp is None:
self.convertfp = open(os.path.join(self.wc, '.svn', 'hg-shamap'),
Augie Fackler
convert: open all files in binary mode...
r36149 'ab')
Yuya Nishihara
convert: fix line ending of mapfile and commit.desc file...
r36166 self.convertfp.write(util.tonativeeol('%s %d\n'
% (destrev, self.revnum(rev))))
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 self.convertfp.flush()
Brendan Cully
convert: move some code into common init function
r4810 def revid(self, revnum, module=None):
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 return 'svn:%s%s@%s' % (self.uuid, module or self.module, revnum)
Brendan Cully
convert: svn: add revnum() to convert rev to revnum
r4774
def revnum(self, rev):
return int(rev.split('@')[-1])
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789
Patrick Mezard
convert/svn: clarify svn_source.latest() stop arg default value...
r16464 def latest(self, path, stop=None):
"""Find the latest revid affecting path, up to stop revision
number. If stop is None, default to repository latest
revision. It may return a revision in a different module,
since a branch may be moved without a change being
reported. Return None if computed module does not belong to
rootmodule subtree.
Patrick Mezard
convert: fix svn_source.latest()
r5955 """
Patrick Mezard
convert/svn: do not try converting empty head revisions (issue3347)...
r16466 def findchanges(path, start, stop=None):
stream = self._getlog([path], start, stop or 1)
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 try:
for entry in stream:
paths, revnum, author, date, message = entry
Patrick Mezard
convert/svn: do not try converting empty head revisions (issue3347)...
r16466 if stop is None and paths:
# We do not know the latest changed revision,
# keep the first one with changed paths.
break
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 if revnum <= stop:
break
for p in paths:
if (not path.startswith(p) or
not paths[p].copyfrom_path):
continue
newpath = paths[p].copyfrom_path + path[len(p):]
self.ui.debug("branch renamed from %s to %s at %d\n" %
(path, newpath, revnum))
path = newpath
break
Patrick Mezard
convert/svn: do not try converting empty head revisions (issue3347)...
r16466 if not paths:
revnum = None
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 return revnum, path
finally:
stream.close()
Patrick Mezard
convert: avoid querying log of foreign svn branches...
r6281 if not path.startswith(self.rootmodule):
# Requests on foreign branches may be forbidden at server level
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('ignoring foreign branch %r\n' % path)
Patrick Mezard
convert: avoid querying log of foreign svn branches...
r6281 return None
Patrick Mezard
convert/svn: clarify svn_source.latest() stop arg default value...
r16464 if stop is None:
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789 stop = svn.ra.get_latest_revnum(self.ra)
try:
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 prevmodule = self.reparent('')
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789 dirent = svn.ra.stat(self.ra, path.strip('/'), stop)
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 self.reparent(prevmodule)
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException:
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789 dirent = None
if not dirent:
Matt Mackall
many, many trivial check-code fixups
r10282 raise SvnPathNotFound(_('%s not found up to revision %d')
% (path, stop))
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789
Martin Geisler
convert/subversion: wrap long lines in comments
r8660 # stat() gives us the previous revision on this line of
# development, but it might be in *another module*. Fetch the
# log and detect renames down to the latest revision.
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 revnum, realpath = findchanges(path, stop, dirent.created_rev)
Patrick Mezard
convert/svn: do not try converting empty head revisions (issue3347)...
r16466 if revnum is None:
# Tools like svnsync can create empty revision, when
# synchronizing only a subtree for instance. These empty
# revisions created_rev still have their original values
# despite all changes having disappeared and can be
# returned by ra.stat(), at least when stating the root
# module. In that case, do not trust created_rev and scan
# the whole history.
revnum, realpath = findchanges(path, stop)
if revnum is None:
self.ui.debug('ignoring empty branch %r\n' % realpath)
return None
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 if not realpath.startswith(self.rootmodule):
self.ui.debug('ignoring foreign branch %r\n' % realpath)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 return None
Patrick Mezard
convert/svn: refactor svn_source.latest() with a nested function...
r16465 return self.revid(revnum, realpath)
Brendan Cully
convert: svn: add function to get the latest revision touching a path...
r4789
Daniel Holth
convert extension: Add SVN converter
r4765 def reparent(self, module):
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 """Reparent the svn transport and return the previous parent."""
if self.prevmodule == module:
return module
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 svnurl = self.baseurl + quote(module)
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 prevmodule = self.prevmodule
if prevmodule is None:
prevmodule = ''
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("reparent to %s\n" % svnurl)
Patrick Mezard
convert: properly encode subversion URLs (issue 1224)
r7074 svn.ra.reparent(self.ra, svnurl)
Patrick Mezard
convert: restore previous svn transport parent correctly
r6847 self.prevmodule = module
return prevmodule
Daniel Holth
convert extension: Add SVN converter
r4765
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 def expandpaths(self, rev, paths, parents):
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 changed, removed = set(), set()
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 copies = {}
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 new_module, revnum = revsplit(rev)[1:]
Patrick Mezard
convert: fix cross-branches subversion revisions handling...
r5872 if new_module != self.module:
self.module = new_module
self.reparent(self.module)
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121
Martin von Zweigbergk
convert: use progress helper...
r38425 progress = self.ui.makeprogress(_('scanning paths'), unit=_('paths'),
total=len(paths))
Patrick Mezard
convert/svn: report path discovery progress...
r11137 for i, (path, ent) in enumerate(paths):
Martin von Zweigbergk
convert: use progress helper...
r38425 progress.update(i, item=path)
Patrick Mezard
convert: rename get_entry_from_path() into an svn_source method
r6539 entrypath = self.getrelpath(path)
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120
Patrick Mezard
convert: remove leading slash from ra.check_path inputs (issue 1236)
r6848 kind = self._checkpath(entrypath, revnum)
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 if kind == svn.core.svn_node_file:
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 changed.add(self.recode(entrypath))
Patrick Mezard
convert: fix svn file copy detection code
r6546 if not ent.copyfrom_path or not parents:
Patrick Mezard
convert: cleanup svn file copy handling
r6544 continue
Martin Geisler
convert/subversion: wrap long lines in comments
r8660 # Copy sources not in parent revisions cannot be
# represented, ignore their origin for now
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 pmodule, prevnum = revsplit(parents[0])[1:]
Patrick Mezard
convert: fix svn file copy detection code
r6546 if ent.copyfrom_rev < prevnum:
continue
copyfrom_path = self.getrelpath(ent.copyfrom_path, pmodule)
Patrick Mezard
convert: cleanup svn file copy handling
r6544 if not copyfrom_path:
continue
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("copied to %s from %s@%s\n" %
Patrick Mezard
convert: cleanup svn file copy handling
r6544 (entrypath, copyfrom_path, ent.copyfrom_rev))
Patrick Mezard
convert/svn: remove confusing unicode variable
r8885 copies[self.recode(entrypath)] = self.recode(copyfrom_path)
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 elif kind == 0: # gone, but had better be a deleted *file*
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("gone from %s\n" % ent.copyfrom_rev)
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 pmodule, prevnum = revsplit(parents[0])[1:]
Patrick Mezard
convert/svn: remove dead code from entry deletion code path...
r8884 parentpath = pmodule + "/" + entrypath
Patrick Mezard
convert/svn: handle files/links replaced by dirs (issue2166)
r11128 fromkind = self._checkpath(entrypath, prevnum, pmodule)
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210
Patrick Mezard
convert/svn: remove dead code and obsolete comments
r8881 if fromkind == svn.core.svn_node_file:
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 removed.add(self.recode(entrypath))
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 elif fromkind == svn.core.svn_node_dir:
Patrick Mezard
convert/svn: tree conflicts no longer happen now we use memctx
r11123 oroot = parentpath.strip('/')
nroot = path.strip('/')
Patrick Mezard
convert/svn: remove useless sort
r11133 children = self._iterfiles(oroot, prevnum)
Patrick Mezard
convert/svn: list files explicitely, stop checking their type...
r11132 for childpath in children:
childpath = childpath.replace(oroot, nroot)
childpath = self.getrelpath("/" + childpath, pmodule)
Patrick Mezard
convert/svn: remove broken but unused copy filtering code...
r11125 if childpath:
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 removed.add(self.recode(childpath))
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 else:
Augie Fackler
cleanup: use () to wrap long lines instead of \...
r41925 self.ui.debug('unknown path in revision %d: %s\n' %
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 (revnum, path))
Martin Geisler
check-code: find trailing whitespace
r12770 elif kind == svn.core.svn_node_dir:
Patrick Mezard
convert: don't scan directories on property changes
r5870 if ent.action == 'M':
Patrick Mezard
convert/svn: handle files/links replaced by dirs (issue2166)
r11128 # If the directory just had a prop change,
# then we shouldn't need to look for its children.
Patrick Mezard
convert: don't scan directories on property changes
r5870 continue
Patrick Mezard
convert/svn: fix changed files list upon directory replacements...
r13052 if ent.action == 'R' and parents:
Patrick Mezard
convert/svn: handle files/links replaced by dirs (issue2166)
r11128 # If a directory is replacing a file, mark the previous
# file as deleted
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 pmodule, prevnum = revsplit(parents[0])[1:]
Patrick Mezard
convert/svn: handle files/links replaced by dirs (issue2166)
r11128 pkind = self._checkpath(entrypath, prevnum, pmodule)
if pkind == svn.core.svn_node_file:
removed.add(self.recode(entrypath))
Patrick Mezard
convert/svn: fix changed files list upon directory replacements...
r13052 elif pkind == svn.core.svn_node_dir:
# We do not know what files were kept or removed,
# mark them all as changed.
for childpath in self._iterfiles(pmodule, prevnum):
childpath = self.getrelpath("/" + childpath)
if childpath:
changed.add(self.recode(childpath))
Patrick Mezard
convert: don't scan directories on property changes
r5870
Patrick Mezard
convert/svn: remove useless sort
r11133 for childpath in self._iterfiles(path, revnum):
Patrick Mezard
convert/svn: list files explicitely, stop checking their type...
r11132 childpath = self.getrelpath("/" + childpath)
if childpath:
changed.add(self.recode(childpath))
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120
Patrick Mezard
convert/svn: remove dead code and obsolete comments
r8881 # Handle directory copies
Patrick Mezard
convert: handle past or foreign partial svn copies...
r6543 if not ent.copyfrom_path or not parents:
Patrick Mezard
convert: more cleanup in svn directory copy handling
r6542 continue
Martin Geisler
convert/subversion: wrap long lines in comments
r8660 # Copy sources not in parent revisions cannot be
# represented, ignore their origin for now
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 pmodule, prevnum = revsplit(parents[0])[1:]
Patrick Mezard
convert: handle past or foreign partial svn copies...
r6543 if ent.copyfrom_rev < prevnum:
continue
Patrick Mezard
convert/svn: remove useless encoding/decoding calls (issue1676)
r8882 copyfrompath = self.getrelpath(ent.copyfrom_path, pmodule)
Patrick Mezard
convert: more cleanup in svn directory copy handling
r6542 if not copyfrompath:
continue
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("mark %s came from %s:%d\n"
Patrick Mezard
convert: more cleanup in svn directory copy handling
r6542 % (path, copyfrompath, ent.copyfrom_rev))
Patrick Mezard
convert/svn: remove useless sort
r11133 children = self._iterfiles(ent.copyfrom_path, ent.copyfrom_rev)
Patrick Mezard
convert/svn: list files explicitely, stop checking their type...
r11132 for childpath in children:
childpath = self.getrelpath("/" + childpath, pmodule)
if not childpath:
Patrick Mezard
convert: more cleanup in svn directory copy handling
r6542 continue
Patrick Mezard
convert/svn: list files explicitely, stop checking their type...
r11132 copytopath = path + childpath[len(copyfrompath):]
Patrick Mezard
convert: more cleanup in svn directory copy handling
r6542 copytopath = self.getrelpath(copytopath)
Patrick Mezard
convert/svn: list files explicitely, stop checking their type...
r11132 copies[self.recode(copytopath)] = self.recode(childpath)
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120
Martin von Zweigbergk
convert: use progress helper...
r38425 progress.complete()
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 changed.update(removed)
return (list(changed), removed, copies)
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871 def _fetch_revisions(self, from_revnum, to_revnum):
if from_revnum < to_revnum:
from_revnum, to_revnum = to_revnum, from_revnum
Bryan O'Sullivan
convert/subversion: reduce memory usage by filtering early...
r4940 self.child_cset = None
Patrick Mezard
convert: fix svn branch source detection corner case...
r6545
Bryan O'Sullivan
convert/subversion: work around memory leak in svn's python bindings...
r4946 def parselogentry(orig_paths, revnum, author, date, message):
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 """Return the parsed commit object or None, and True if
Patrick Mezard
convert: fix cross-branches subversion revisions handling...
r5872 the revision is a branch root.
"""
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("parsing revision %d (%d changes)\n" %
Bryan O'Sullivan
convert/subversion: work around memory leak in svn's python bindings...
r4946 (revnum, len(orig_paths)))
Bryan O'Sullivan
convert/subversion: reduce memory usage by filtering early...
r4940
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 branched = False
Brendan Cully
convert: move some code into common init function
r4810 rev = self.revid(revnum)
Brendan Cully
convert: svn: some improvements in memory usage
r4837 # branch log might return entries for a parent we already have
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871
Martin Geisler
remove unnecessary outer parenthesis in if-statements
r8117 if rev in self.commits or revnum < to_revnum:
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 return None, branched
Brendan Cully
convert: svn: some improvements in memory usage
r4837
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 parents = []
Patrick Mezard
convert: follow svn module parent moves
r5958 # check whether this revision is the start of a branch or part
# of a branch renaming
Matt Mackall
replace util.sort with sorted built-in...
r8209 orig_paths = sorted(orig_paths.iteritems())
Matt Mackall
many, many trivial check-code fixups
r10282 root_paths = [(p, e) for p, e in orig_paths
if self.module.startswith(p)]
Patrick Mezard
convert: follow svn module parent moves
r5958 if root_paths:
path, ent = root_paths[-1]
Brendan Cully
convert: svn: hoist up branch creation check
r5119 if ent.copyfrom_path:
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 branched = True
Patrick Mezard
convert: follow svn module parent moves
r5958 newpath = ent.copyfrom_path + self.module[len(path):]
Brendan Cully
convert: svn: hoist up branch creation check
r5119 # ent.copyfrom_rev may not be the actual last revision
Patrick Mezard
convert: backout a7492fb2107b...
r7476 previd = self.latest(newpath, ent.copyfrom_rev)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 if previd is not None:
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 prevmodule, prevnum = revsplit(previd)[1:]
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 if prevnum >= self.startrev:
parents = [previd]
Matt Mackall
many, many trivial check-code fixups
r10282 self.ui.note(
_('found parent of branch %s at %d: %s\n') %
(self.module, prevnum, prevmodule))
Brendan Cully
convert: svn: hoist up branch creation check
r5119 else:
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug("no copyfrom path, don't know what to do.\n")
Brendan Cully
convert: svn: hoist up branch creation check
r5119
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 paths = []
# filter out unrelated paths
Bryan O'Sullivan
convert/subversion: reduce memory usage by filtering early...
r4940 for path, ent in orig_paths:
Patrick Mezard
convert: improve subversion branch filtering
r6540 if self.getrelpath(path) is None:
Brendan Cully
convert: svn: add an early return to move most changeset parsing out an indent level
r4788 continue
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 paths.append((path, ent))
Daniel Holth
convert extension: Add SVN converter
r4765
Brendan Cully
convert: svn: add an early return to move most changeset parsing out an indent level
r4788 # Example SVN datetime. Includes microseconds.
# ISO-8601 conformant
# '2007-01-04T17:35:00.902377Z'
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 date = dateutil.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"])
Julian Cowley
convert: add config option to use the local time zone...
r17974 if self.ui.configbool('convert', 'localtimezone'):
date = makedatetimestamp(date[0])
Daniel Holth
convert extension: Add SVN converter
r4765
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if message:
log = self.recode(message)
else:
log = ''
if author:
author = self.recode(author)
else:
author = ''
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 try:
branch = self.module.split("/")[-1]
Patrick Mezard
convert/svn: read trunk name once, use None for default
r13529 if branch == self.trunkname:
branch = None
Brendan Cully
convert: svn: pull up path to file expansion code into separate function....
r5120 except IndexError:
branch = None
Daniel Holth
convert extension: Add SVN converter
r4765
Brendan Cully
convert: svn: add an early return to move most changeset parsing out an indent level
r4788 cset = commit(author=author,
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'),
Thomas Arendsen Hein
removed trailing whitespace
r4957 desc=log,
Brendan Cully
convert: svn: get parent for branch creation events
r4795 parents=parents,
Brendan Cully
convert: record the source revision in the changelog
r4873 branch=branch,
Patrick Mezard
convert/svn: stop returning unicode revision identifiers
r8886 rev=rev)
Brendan Cully
convert: svn: add an early return to move most changeset parsing out an indent level
r4788
Brendan Cully
convert: svn: pull out broken batching code, add alpha tags support
r4796 self.commits[rev] = cset
Patrick Mezard
convert: fix cross-branches subversion revisions handling...
r5872 # The parents list is *shared* among self.paths and the
# commit object. Both will be updated below.
self.paths[rev] = (paths, cset.parents)
Brendan Cully
convert: svn: pull out broken batching code, add alpha tags support
r4796 if self.child_cset and not self.child_cset.parents:
Patrick Mezard
convert: fix cross-branches subversion revisions handling...
r5872 self.child_cset.parents[:] = [rev]
Brendan Cully
convert: svn: add an early return to move most changeset parsing out an indent level
r4788 self.child_cset = cset
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 return cset, branched
Brendan Cully
convert: svn: pull out broken batching code, add alpha tags support
r4796
Martin Geisler
i18n: mark strings for translation in convert extension
r6956 self.ui.note(_('fetching revision log for "%s" from %d to %d\n') %
Brendan Cully
convert: svn: autodetect /branches, /tags, /trunk....
r4797 (self.module, from_revnum, to_revnum))
Daniel Holth
convert extension: Add SVN converter
r4765
try:
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871 firstcset = None
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 lastonbranch = False
Patrick Mezard
convert: normalize paths sent to svn get_log (issue 1219)
r6850 stream = self._getlog([self.module], from_revnum, to_revnum)
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 try:
for entry in stream:
paths, revnum, author, date, message = entry
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 if revnum < self.startrev:
lastonbranch = True
break
Francis Barber
Fix subversion convert not detecting empty changesets....
r8172 if not paths:
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('revision %d has no entries\n' % revnum)
Patrick Mezard
convert: handle svn tree with empty roots (issue2079)
r10618 # If we ever leave the loop on an empty
# revision, do not try to get a parent branch
lastonbranch = lastonbranch or revnum == 0
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 continue
Thomas Arendsen Hein
Removed trailing spaces from everything except test output
r6210 cset, lastonbranch = parselogentry(paths, revnum, author,
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 date, message)
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 if cset:
firstcset = cset
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 if lastonbranch:
Patrick Mezard
convert: make svn revision iterator interruptible
r5873 break
finally:
stream.close()
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871
Patrick Mezard
convert: add shallow, single branch svn conversions via svn.startrev
r6173 if not lastonbranch and firstcset and not firstcset.parents:
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871 # The first revision of the sequence (the last fetched one)
# has invalid parents if not a branch root. Find the parent
# revision now, if any.
try:
firstrevnum = self.revnum(firstcset.rev)
if firstrevnum > 1:
latest = self.latest(self.module, firstrevnum - 1)
Patrick Mezard
convert: prevent svn branches to leave the root module tree
r5957 if latest:
firstcset.parents.append(latest)
Patrick Mezard
convert: be even more tolerant when detecting svn tags...
r7381 except SvnPathNotFound:
Patrick Mezard
convert: fix parents of last fetched svn revision
r5871 pass
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException as xxx_todo_changeme:
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 (inst, num) = xxx_todo_changeme.args
Daniel Holth
convert extension: Add SVN converter
r4765 if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('svn: branch has no revision %s')
Brodie Rao
cleanup: eradicate long lines
r16683 % to_revnum)
Daniel Holth
convert extension: Add SVN converter
r4765 raise
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 def getfile(self, file, rev):
Daniel Holth
convert extension: Add SVN converter
r4765 # TODO: ra.get_file transmits the whole file instead of diffs.
Patrick Mezard
convert/svn: do not retrieve removed files...
r11127 if file in self.removed:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None, None
Daniel Holth
convert extension: Add SVN converter
r4765 try:
Patrick Mezard
convert/svn: extract revsplit() in a function
r13690 new_module, revnum = revsplit(rev)[1:]
Patrick Mezard
convert: fix cross-branches subversion revisions handling...
r5872 if self.module != new_module:
self.module = new_module
Daniel Holth
convert extension: Add SVN converter
r4765 self.reparent(self.module)
timeless
pycompat: switch to util.stringio for py3 compat
r28861 io = stringio()
Daniel Holth
convert extension: Add SVN converter
r4765 info = svn.ra.get_file(self.ra, file, revnum, io)
Patrick Mezard
convert: work around svn.ra.get_files() not releasing input buffer
r7446 data = io.getvalue()
Mads Kiilerich
fix trivial spelling errors
r17424 # ra.get_file() seems to keep a reference on the input buffer
timeless@mozdev.org
spelling: Explicitly
r17479 # preventing collection. Release it explicitly.
Patrick Mezard
convert: work around svn.ra.get_files() not releasing input buffer
r7446 io.close()
Daniel Holth
convert extension: Add SVN converter
r4765 if isinstance(info, list):
info = info[-1]
mode = ("svn:executable" in info) and 'x' or ''
mode = ("svn:special" in info) and 'l' or mode
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 except svn.core.SubversionException as e:
Daniel Holth
convert extension: Add SVN converter
r4765 notfound = (svn.core.SVN_ERR_FS_NOT_FOUND,
svn.core.SVN_ERR_RA_DAV_PATH_NOT_FOUND)
if e.apr_err in notfound: # File not found
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None, None
Daniel Holth
convert extension: Add SVN converter
r4765 raise
if mode == 'l':
link_prefix = "link "
if data.startswith(link_prefix):
data = data[len(link_prefix):]
return data, mode
Patrick Mezard
convert/svn: remove useless sort
r11133 def _iterfiles(self, path, revnum):
"""Enumerate all files in path at revnum, recursively."""
Brendan Cully
convert: svn: ensure leading / is removed from paths in _find_children (broken in 2bd996d0aaf8)
r5114 path = path.strip('/')
FUJIWARA Katsunori
convert: fix relative import of stdlib module in subversion...
r28460 pool = svn.core.Pool()
Patrick Mezard
convert/svn: fix URL quoting issue with svn 1.7...
r15599 rpath = '/'.join([self.baseurl, quote(path)]).strip('/')
Matt Mackall
convert/svn: fix long line
r11167 entries = svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool)
Patrick Mezard
convert/svn: fix _iterfiles() output in root dir case (issue2647)...
r13651 if path:
path += '/'
return ((path + p) for p, e in entries.iteritems()
Patrick Mezard
convert/svn: remove useless sort
r11133 if e.kind == svn.core.svn_node_file)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
Patrick Mezard
convert: rename get_entry_from_path() into an svn_source method
r6539 def getrelpath(self, path, module=None):
if module is None:
module = self.module
# Given the repository url of this wc, say
# "http://server/plone/CMFPlone/branches/Plone-2_0-branch"
# extract the "entry" portion (a relative path) from what
Mads Kiilerich
fix trivial spelling errors
r17424 # svn log --xml says, i.e.
Patrick Mezard
convert: rename get_entry_from_path() into an svn_source method
r6539 # "/CMFPlone/branches/Plone-2_0-branch/tests/PloneTestCase.py"
# that is to say "tests/PloneTestCase.py"
if path.startswith(module):
relative = path.rstrip('/')[len(module):]
if relative.startswith('/'):
return relative[1:]
elif relative == '':
return relative
# The path is outside our tracked tree...
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('%r is not under %r, ignoring\n' % (path, module))
Patrick Mezard
convert: rename get_entry_from_path() into an svn_source method
r6539 return None
Patrick Mezard
convert/svn: handle files/links replaced by dirs (issue2166)
r11128 def _checkpath(self, path, revnum, module=None):
if module is not None:
prevmodule = self.reparent('')
path = module + '/' + path
try:
# ra.check_path does not like leading slashes very much, it leads
# to PROPFIND subversion errors
return svn.ra.check_path(self.ra, path.strip('/'), revnum)
finally:
if module is not None:
self.reparent(prevmodule)
Martin Geisler
check-code: find trailing whitespace
r12770
Patrick Mezard
convert: normalize paths sent to svn get_log (issue 1219)
r6850 def _getlog(self, paths, start, end, limit=0, discover_changed_paths=True,
strict_node_history=False):
# Normalize path names, svn >= 1.5 only wants paths relative to
# supplied URL
relpaths = []
for p in paths:
if not p.startswith('/'):
p = self.module + '/' + p
relpaths.append(p.strip('/'))
Brodie Rao
cleanup: eradicate long lines
r16683 args = [self.baseurl, relpaths, start, end, limit,
discover_changed_paths, strict_node_history]
timeless
convert/svn: quiet check-config
r27314 # developer config: convert.svn.debugsvnlog
Boris Feld
configitems: register the 'convert.svn.debugsvnlog' config
r34176 if not self.ui.configbool('convert', 'svn.debugsvnlog'):
Mads Kiilerich
convert: secret config option for disabling debugsvnlog...
r20420 return directlogstream(*args)
Patrick Mezard
convert: normalize paths sent to svn get_log (issue 1219)
r6850 arg = encodeargs(args)
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 hgexe = procutil.hgexecutable()
cmd = '%s debugsvnlog' % procutil.shellquote(hgexe)
stdin, stdout = procutil.popen2(procutil.quotecommand(cmd))
Patrick Mezard
convert: normalize paths sent to svn get_log (issue 1219)
r6850 stdin.write(arg)
Patrick Mezard
convert/svn: better handling of hg recursive call failure
r10071 try:
stdin.close()
except IOError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('Mercurial failed to run itself, check'
Patrick Mezard
convert/svn: better handling of hg recursive call failure
r10071 ' hg executable is in PATH'))
Patrick Mezard
convert: normalize paths sent to svn get_log (issue 1219)
r6850 return logstream(stdout)
Pulkit Goyal
py3: add b'' prefixes in hgext/convert/subversion.py...
r38079 pre_revprop_change = b'''#!/bin/sh
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
REPOS="$1"
REV="$2"
USER="$3"
PROPNAME="$4"
ACTION="$5"
if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-branch" ]; then exit 0; fi
if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-rev" ]; then exit 0; fi
echo "Changing prohibited revision property" >&2
exit 1
'''
class svn_sink(converter_sink, commandline):
Pulkit Goyal
py3: add b'' prefixes in hgext/convert/subversion.py...
r38079 commit_re = re.compile(br'Committed revision (\d+).', re.M)
uuid_re = re.compile(br'Repository UUID:\s*(\S+)', re.M)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
def prerun(self):
if self.wc:
os.chdir(self.wc)
def postrun(self):
if self.wc:
os.chdir(self.cwd)
def join(self, name):
return os.path.join(self.wc, '.svn', name)
Thomas Arendsen Hein
Removed tabs and trailing whitespace in python files
r5760
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 def revmapfile(self):
return self.join('hg-shamap')
def authorfile(self):
return self.join('hg-authormap')
Matt Harbison
convert: save an indicator of the repo type for sources and sinks...
r35168 def __init__(self, ui, repotype, path):
Azhagu Selvan SP
convert/svn: abort operation when python bindings are not available...
r13480
Matt Harbison
convert: save an indicator of the repo type for sources and sinks...
r35168 converter_sink.__init__(self, ui, repotype, path)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 commandline.__init__(self, ui, 'svn')
self.delete = []
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 self.setexec = []
self.delexec = []
self.copies = []
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.wc = None
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 self.cwd = encoding.getcwd()
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
created = False
if os.path.isfile(os.path.join(path, '.svn', 'entries')):
Patrick Mezard
convert/svn: handle non-local svn destination paths (issue3142)...
r17247 self.wc = os.path.realpath(path)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.run0('update')
else:
Pulkit Goyal
py3: make sure regexes are bytes...
r36473 if not re.search(br'^(file|http|https|svn|svn\+ssh)\://', path):
Patrick Mezard
convert/svn: handle non-local svn destination paths (issue3142)...
r17247 path = os.path.realpath(path)
if os.path.isdir(os.path.dirname(path)):
if not os.path.exists(os.path.join(path, 'db', 'fs-type')):
Pulkit Goyal
py3: use '%s' instead of %r in hgext/convert/subversion.py...
r40251 ui.status(_("initializing svn repository '%s'\n") %
Patrick Mezard
convert/svn: handle non-local svn destination paths (issue3142)...
r17247 os.path.basename(path))
commandline(ui, 'svnadmin').run0('create', path)
created = path
path = util.normpath(path)
if not path.startswith('/'):
path = '/' + path
path = 'file://' + path
Patrick Mezard
convert: fix svn file:// URL generation under Windows
r5535
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 wcpath = os.path.join(encoding.getcwd(), os.path.basename(path) +
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 '-wc')
Pulkit Goyal
py3: use '%s' instead of %r in hgext/convert/subversion.py...
r40251 ui.status(_("initializing svn working copy '%s'\n")
Martin Geisler
convert: write "working copy" instead of "wc"
r10940 % os.path.basename(wcpath))
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.run0('checkout', path, wcpath)
self.wc = wcpath
Pierre-Yves David
vfs: use 'vfs' module directly in 'hgext.convert'...
r31246 self.opener = vfsmod.vfs(self.wc)
self.wopener = vfsmod.vfs(self.wc)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.childmap = mapfile(ui, self.join('hg-childmap'))
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if util.checkexec(self.wc):
self.is_exec = util.isexec
else:
self.is_exec = None
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
if created:
hook = os.path.join(created, 'hooks', 'pre-revprop-change')
Augie Fackler
convert: open all files in binary mode...
r36149 fp = open(hook, 'wb')
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 fp.write(pre_revprop_change)
fp.close()
Adrian Buehlmann
rename util.set_flags to setflags
r14232 util.setflags(hook, False, True)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513
Patrick Mezard
convert/svn: stop using svn bindings when pushing to svn
r13530 output = self.run0('info')
self.uuid = self.uuid_re.search(output).group(1).strip()
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 def wjoin(self, *names):
return os.path.join(self.wc, *names)
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 @propertycache
def manifest(self):
# As of svn 1.7, the "add" command fails when receiving
# already tracked entries, so we have to track and filter them
# ourselves.
m = set()
output = self.run0('ls', recursive=True, xml=True)
doc = xml.dom.minidom.parseString(output)
Gregory Szorc
convert: use raw strings for XML strings...
r41358 for e in doc.getElementsByTagName(r'entry'):
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 for n in e.childNodes:
Gregory Szorc
convert: use raw strings for XML strings...
r41358 if n.nodeType != n.ELEMENT_NODE or n.tagName != r'name':
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 continue
Gregory Szorc
convert: use raw strings for XML strings...
r41358 name = r''.join(c.data for c in n.childNodes
if c.nodeType == c.TEXT_NODE)
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 # Entries are compared with names coming from
# mercurial, so bytes with undefined encoding. Our
# best bet is to assume they are in local
# encoding. They will be passed to command line calls
# later anyway, so they better be.
Yuya Nishihara
encoding: factor out unicode variants of from/tolocal()...
r31447 m.add(encoding.unitolocal(name))
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 break
return m
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 def putfile(self, filename, flags, data):
if 'l' in flags:
self.wopener.symlink(data, filename)
else:
try:
if os.path.islink(self.wjoin(filename)):
os.unlink(filename)
except OSError:
pass
Nikita Slyusarev
convert: handle exec bit removal while converting to svn...
r41766
if self.is_exec:
# We need to check executability of the file before the change,
# because `vfs.write` is able to reset exec bit.
wasexec = False
if os.path.exists(self.wjoin(filename)):
wasexec = self.is_exec(self.wjoin(filename))
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 self.wopener.write(filename, data)
Patrick Mezard
convert: force svn:executable when execute-bit is not supported...
r5536
if self.is_exec:
Nikita Slyusarev
convert: handle exec bit removal while converting to svn...
r41766 if wasexec:
Mads Kiilerich
convert: ignore svn:executable for subversion targets without exec bit support...
r17031 if 'x' not in flags:
self.delexec.append(filename)
else:
if 'x' in flags:
self.setexec.append(filename)
util.setflags(self.wjoin(filename), False, 'x' in flags)
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698
def _copyfile(self, source, dest):
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 # SVN's copy command pukes if the destination file exists, but
# our copyfile method expects to record a copy that has
# already occurred. Cross the semantic gap.
wdest = self.wjoin(dest)
Patrick Mezard
convert/svn: fix broken symlink renames in svn sink
r12343 exists = os.path.lexists(wdest)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if exists:
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 fd, tempname = pycompat.mkstemp(
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 prefix='hg-copy-', dir=os.path.dirname(wdest))
os.close(fd)
os.unlink(tempname)
os.rename(wdest, tempname)
try:
self.run0('copy', source, dest)
finally:
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 self.manifest.add(dest)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if exists:
try:
os.unlink(wdest)
except OSError:
pass
os.rename(tempname, wdest)
def dirs_of(self, files):
Martin Geisler
util: use built-in set and frozenset...
r8150 dirs = set()
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 for f in files:
if os.path.isdir(self.wjoin(f)):
dirs.add(f)
Yuya Nishihara
convert: inline strutil.rfindall()...
r30605 i = len(f)
for i in iter(lambda: f.rfind('/', 0, i), -1):
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 dirs.add(f[:i])
return dirs
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 def add_dirs(self, files):
Matt Mackall
replace util.sort with sorted built-in...
r8209 add_dirs = [d for d in sorted(self.dirs_of(files))
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 if d not in self.manifest]
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if add_dirs:
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 self.manifest.update(add_dirs)
Maxim Dounin
convert: add commandline.xargs(), use it in svn_sink class...
r5832 self.xargs(add_dirs, 'add', non_recursive=True, quiet=True)
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 return add_dirs
def add_files(self, files):
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 files = [f for f in files if f not in self.manifest]
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if files:
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 self.manifest.update(files)
Maxim Dounin
convert: add commandline.xargs(), use it in svn_sink class...
r5832 self.xargs(files, 'add', quiet=True)
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 return files
Thomas Arendsen Hein
Removed tabs and trailing whitespace in python files
r5760
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 def addchild(self, parent, child):
self.childmap[parent] = child
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 def revid(self, rev):
Pulkit Goyal
py3: don't return the revid as unicode in hgext/convert/subversion.py...
r39457 return "svn:%s@%s" % (self.uuid, rev)
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 def putcommit(self, files, copies, parents, commit, source, revmap, full,
cleanp2):
Patrick Mezard
convert/svn: update svn working copy only when necessary...
r15605 for parent in parents:
try:
return self.revid(self.childmap[parent])
except KeyError:
pass
Patrick Mezard
convert: reintegrate file retrieval code in sinks...
r6716 # Apply changes to working copy
for f, v in files:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 data, mode = source.getfile(f, v)
if data is None:
Patrick Mezard
convert: reintegrate file retrieval code in sinks...
r6716 self.delete.append(f)
else:
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 self.putfile(f, mode, data)
Patrick Mezard
convert: reintegrate file retrieval code in sinks...
r6716 if f in copies:
self.copies.append([copies[f], f])
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 if full:
self.delete.extend(sorted(self.manifest.difference(files)))
Patrick Mezard
convert: reintegrate file retrieval code in sinks...
r6716 files = [f[0] for f in files]
Martin Geisler
util: use built-in set and frozenset...
r8150 entries = set(self.delete)
files = frozenset(files)
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 entries.update(self.add_dirs(files.difference(entries)))
if self.copies:
for s, d in self.copies:
self._copyfile(s, d)
self.copies = []
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if self.delete:
Maxim Dounin
convert: add commandline.xargs(), use it in svn_sink class...
r5832 self.xargs(self.delete, 'delete')
Patrick Mezard
convert/svn: make svn sink work with svn 1.7...
r16511 for f in self.delete:
self.manifest.remove(f)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.delete = []
entries.update(self.add_files(files.difference(entries)))
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 if self.delexec:
Maxim Dounin
convert: add commandline.xargs(), use it in svn_sink class...
r5832 self.xargs(self.delexec, 'propdel', 'svn:executable')
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 self.delexec = []
if self.setexec:
Maxim Dounin
convert: add commandline.xargs(), use it in svn_sink class...
r5832 self.xargs(self.setexec, 'propset', 'svn:executable', '*')
Maxim Dounin
convert: svn-sink: copy and set properties after adding dirs/files...
r5698 self.setexec = []
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 fd, messagefile = pycompat.mkstemp(prefix='hg-convert-')
Yuya Nishihara
py3: use r'' instead of sysstr('') to get around code transformer...
r36853 fp = os.fdopen(fd, r'wb')
Yuya Nishihara
convert: fix line ending of mapfile and commit.desc file...
r36166 fp.write(util.tonativeeol(commit.desc))
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 fp.close()
try:
output = self.run0('commit',
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 username=stringutil.shortuser(commit.author),
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 file=messagefile,
Shun-ichi GOTO
convert: svn_sink: workaround of command line size limitation on win32....
r5790 encoding='utf-8')
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 try:
rev = self.commit_re.search(output).group(1)
except AttributeError:
Nikita Slyusarev
convert: handle empty intial commits while converting to svn...
r41765 if not files:
return parents[0] if parents else None
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 self.ui.warn(_('unexpected svn output:\n'))
self.ui.warn(output)
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('unable to cope with svn output'))
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 if commit.rev:
self.run('propset', 'hg:convert-rev', commit.rev,
revprop=True, revision=rev)
if commit.branch and commit.branch != 'default':
self.run('propset', 'hg:convert-branch', commit.branch,
revprop=True, revision=rev)
for parent in parents:
self.addchild(parent, rev)
Bryan O'Sullivan
convert: tell the source repository when a rev has been converted...
r5554 return self.revid(rev)
Bryan O'Sullivan
convert: add support for Subversion as a sink
r5513 finally:
os.unlink(messagefile)
def puttags(self, tags):
Martin Geisler
convert: less shouting in SVN sink warning
r11779 self.ui.warn(_('writing Subversion tags is not yet implemented\n'))
Daniel J. Lauk
convert: Using --dest-type svn crashed, if the source repo used tags....
r11778 return None, None
Patrick Mezard
convert: use splicemap entries when sorting revisions (issue1748)...
r16106
Mads Kiilerich
convert: introduce hascommitfrommap sink method...
r21635 def hascommitfrommap(self, rev):
# We trust that revisions referenced in a map still is present
# TODO: implement something better if necessary and feasible
return True
Mads Kiilerich
convert: rename sink hascommit to hascommitforsplicemap...
r21634 def hascommitforsplicemap(self, rev):
Patrick Mezard
convert: use splicemap entries when sorting revisions (issue1748)...
r16106 # This is not correct as one can convert to an existing subversion
# repository and childmap would not list all revisions. Too bad.
if rev in self.childmap:
return True
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('splice map revision %s not found in subversion '
Wagner Bruna
convert: fix typos in error messages
r16162 'child map (revision lookups are not implemented)')
Patrick Mezard
convert: use splicemap entries when sorting revisions (issue1748)...
r16106 % rev)