--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -275,16 +275,16 @@ def _convert(ui, src, dest=None, mapfile
understood by the source).
If no destination directory name is specified, it defaults to the
- basename of the source with '-hg' appended. If the destination
- repository doesn't exist, it will be created.
+ basename of the source with \'-hg\' appended. If the destination
+ repository doesn\'t exist, it will be created.
- If <mapfile> isn't given, it will be put in a default location
+ If <mapfile> isn\'t given, it will be put in a default location
(<dest>/.hg/shamap by default). The <mapfile> is a simple text
file that maps each source commit ID to the destination ID for
that revision, like so:
<source ID> <destination ID>
- If the file doesn't exist, it's automatically created. It's updated
+ If the file doesn\'t exist, it\'s automatically created. It\'s updated
on each commit copied, so convert-repo can be interrupted and can
be run repeatedly to copy new commits.
--- a/hgext/convert/subversion.py
+++ b/hgext/convert/subversion.py
@@ -1,6 +1,17 @@
# Subversion 1.4/1.5 Python API backend
#
# Copyright(C) 2007 Daniel Holth et al
+#
+# Configuration options:
+#
+# convert.svn.trunk
+# Relative path to the trunk (default: "trunk")
+# convert.svn.branches
+# Relative path to tree of branches (default: "branches")
+#
+# Set these in a hgrc, or on the command line as follows:
+#
+# hg convert --config convert.svn.trunk=wackoname [...]
import pprint
import locale
@@ -51,8 +62,10 @@ class convert_svn(converter_source):
try:
# Support file://path@rev syntax. Useful e.g. to convert
# deleted branches.
- url, latest = url.rsplit("@", 1)
- latest = int(latest)
+ at = url.rfind('@')
+ if at >= 0:
+ latest = int(url[at+1:])
+ url = url[:at]
except ValueError, e:
pass
self.url = url
@@ -88,26 +101,47 @@ class convert_svn(converter_source):
lastrevs[module] = revnum
self.lastrevs = lastrevs
+ def exists(self, path, optrev):
+ try:
+ return svn.client.ls(self.url.rstrip('/') + '/' + path,
+ optrev, False, self.ctx)
+ except SubversionException, err:
+ return []
+
def getheads(self):
# detect standard /branches, /tags, /trunk layout
optrev = svn.core.svn_opt_revision_t()
optrev.kind = svn.core.svn_opt_revision_number
optrev.value.number = self.last_changed
rpath = self.url.strip('/')
- paths = svn.client.ls(rpath, optrev, False, self.ctx)
- if 'branches' in paths and 'trunk' in paths:
- self.module += '/trunk'
+ cfgtrunk = self.ui.config('convert', 'svn.trunk')
+ cfgbranches = self.ui.config('convert', 'svn.branches')
+ trunk = (cfgtrunk or 'trunk').strip('/')
+ branches = (cfgbranches or 'branches').strip('/')
+ if self.exists(trunk, optrev) and self.exists(branches, optrev):
+ self.ui.note('found trunk at %r and branches at %r\n' %
+ (trunk, branches))
+ oldmodule = self.module
+ self.module += '/' + trunk
lt = self.latest(self.module, self.last_changed)
self.head = self.revid(lt)
self.heads = [self.head]
- branches = svn.client.ls(rpath + '/branches', optrev, False, self.ctx)
- for branch in branches.keys():
- module = '/branches/' + branch
+ branchnames = svn.client.ls(rpath + '/' + branches, optrev, False,
+ self.ctx)
+ for branch in branchnames.keys():
+ if oldmodule:
+ module = '/' + oldmodule + '/' + branches + '/' + branch
+ else:
+ module = '/' + branches + '/' + branch
brevnum = self.latest(module, self.last_changed)
brev = self.revid(brevnum, module)
self.ui.note('found branch %s at %d\n' % (branch, brevnum))
self.heads.append(brev)
+ elif cfgtrunk or cfgbranches:
+ raise util.Abort(_('trunk/branch layout expected, '
+ 'but not found'))
else:
+ self.ui.note('working with one branch\n')
self.heads = [self.head]
return self.heads
@@ -193,8 +227,8 @@ class convert_svn(converter_source):
except SubversionException:
dirent = None
if not dirent:
- raise util.Abort('%s not found up to revision %d' \
- % (path, stop))
+ print self.base, path
+ raise util.Abort('%s not found up to revision %d' % (path, stop))
return dirent.created_rev
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -281,7 +281,7 @@ def externalpatch(patcher, args, patchna
def internalpatch(patchname, ui, strip, cwd, files):
"""use builtin patch to apply <patchname> to the working directory.
returns whether patch was applied with fuzz factor."""
- fp = file(patchname)
+ fp = file(patchname, 'rb')
if cwd:
curdir = os.getcwd()
os.chdir(cwd)
@@ -303,7 +303,7 @@ class patchfile:
self.fname = fname
self.ui = ui
try:
- fp = file(fname, 'r')
+ fp = file(fname, 'rb')
self.lines = fp.readlines()
self.exists = True
except IOError:
@@ -383,7 +383,7 @@ class patchfile:
try: os.unlink(fname)
except:
pass
- fp = file(fname, 'w')
+ fp = file(fname, 'wb')
base = os.path.basename(self.fname)
fp.write("--- %s\n+++ %s\n" % (base, base))
for x in self.rej:
@@ -402,7 +402,7 @@ class patchfile:
if st.st_nlink > 1:
os.unlink(dest)
except: pass
- fp = file(dest, 'w')
+ fp = file(dest, 'wb')
if st:
os.chmod(dest, st.st_mode)
fp.writelines(self.lines)
@@ -777,13 +777,13 @@ def selectfile(afile_orig, bfile_orig, h
if count == 0:
return path.rstrip()
while count > 0:
- i = path.find(os.sep, i)
+ i = path.find('/', i)
if i == -1:
raise PatchError(_("unable to strip away %d dirs from %s") %
(count, path))
i += 1
# consume '//' in the path
- while i < pathlen - 1 and path[i] == os.sep:
+ while i < pathlen - 1 and path[i] == '/':
i += 1
count -= 1
return path[i:].rstrip()
--- a/mercurial/util_win32.py
+++ b/mercurial/util_win32.py
@@ -209,9 +209,9 @@ class posixfile_nt(object):
def __init__(self, name, mode='rb'):
access = 0
- if 'r' in mode or '+' in mode:
+ if 'r' in mode:
access |= win32file.GENERIC_READ
- if 'w' in mode or 'a' in mode:
+ if 'w' in mode or 'a' in mode or '+' in mode:
access |= win32file.GENERIC_WRITE
if 'r' in mode:
creation = win32file.OPEN_EXISTING
--- a/tests/test-tag
+++ b/tests/test-tag
@@ -29,14 +29,18 @@ newline'
hg tag -l 'xx:xx'
echo % issue 601
-mv .hg/localtags .hg/ltags
-head -1 .hg/ltags | tr -d '\n' > .hg/localtags
+python << EOF
+f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
+f = file('.hg/localtags', 'w'); f.write(last); f.close()
+EOF
cat .hg/localtags
hg tag -l localnewline
cat .hg/localtags
-mv .hgtags hgtags
-head -1 hgtags | tr -d '\n' > .hgtags
+python << EOF
+f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
+f = file('.hgtags', 'w'); f.write(last); f.close()
+EOF
hg ci -d '1000000 0' -m'broken manual edit of .hgtags'
cat .hgtags
hg tag -d '1000000 0' newline