--- a/contrib/churn.py Sat Jul 21 16:18:42 2007 -0500
+++ b/contrib/churn.py Sat Jul 21 16:44:38 2007 -0500
@@ -11,9 +11,34 @@
#
# <alias email> <actual email>
-import sys
from mercurial.i18n import gettext as _
from mercurial import hg, mdiff, cmdutil, ui, util, templater, node
+import os, sys
+
+def get_tty_width():
+ if 'COLUMNS' in os.environ:
+ try:
+ return int(os.environ['COLUMNS'])
+ except ValueError:
+ pass
+ try:
+ import termios, fcntl, struct
+ buf = 'abcd'
+ for dev in (sys.stdout, sys.stdin):
+ try:
+ if buf != 'abcd':
+ break
+ fd = dev.fileno()
+ if not os.isatty(fd):
+ continue
+ buf = fcntl.ioctl(fd, termios.TIOCGWINSZ, buf)
+ except ValueError:
+ pass
+ if buf != 'abcd':
+ return struct.unpack('hh', buf)[1]
+ except ImportError:
+ pass
+ return 80
def __gather(ui, repo, node1, node2):
def dirtywork(f, mmap1, mmap2):
@@ -159,8 +184,9 @@
maximum = ordered[0][1]
- ui.note("Assuming 80 character terminal\n")
- width = 80 - 1
+ width = get_tty_width()
+ ui.note(_("assuming %i character terminal\n") % width)
+ width -= 1
for i in ordered:
person = i[0]
--- a/hgext/alias.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/alias.py Sat Jul 21 16:44:38 2007 -0500
@@ -72,6 +72,5 @@
args = target.split(' ')
tcmd = args.pop(0)
if args:
- pui = ui.parentui or ui
- pui.setconfig('defaults', cmd, ' '.join(args))
+ ui.setconfig('defaults', cmd, ' '.join(args))
cmdtable[cmd] = lazycommand(ui, cmd, tcmd)
--- a/hgext/convert/__init__.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/convert/__init__.py Sat Jul 21 16:44:38 2007 -0500
@@ -192,7 +192,7 @@
def copy(self, rev):
c = self.commitcache[rev]
files = self.source.getchanges(rev)
-
+
do_copies = (hasattr(c, 'copies') and hasattr(self.dest, 'copyfile'))
for f, v in files:
@@ -260,7 +260,7 @@
self.mapfilefd.close()
def _convert(ui, src, dest=None, mapfile=None, **opts):
- '''Convert a foreign SCM repository to a Mercurial one.
+ """Convert a foreign SCM repository to a Mercurial one.
Accepted source formats:
- GIT
@@ -293,7 +293,7 @@
that use unix logins to identify authors (eg: CVS). One line per author
mapping and the line format is:
srcauthor=whatever string you want
- '''
+ """
util._encoding = 'UTF-8'
--- a/hgext/convert/common.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/convert/common.py Sat Jul 21 16:44:38 2007 -0500
@@ -60,7 +60,7 @@
def recode(self, s, encoding=None):
if not encoding:
encoding = self.encoding or 'utf-8'
-
+
try:
return s.decode(encoding).encode("utf-8")
except:
--- a/hgext/convert/subversion.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/convert/subversion.py Sat Jul 21 16:44:38 2007 -0500
@@ -1,10 +1,21 @@
# 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
-
+import os
+import cPickle as pickle
from mercurial import util
# Subversion stuff. Works best with very recent Python SVN bindings
@@ -27,6 +38,12 @@
class CompatibilityException(Exception): pass
+class changedpath(object):
+ def __init__(self, p):
+ self.copyfrom_path = p.copyfrom_path
+ self.copyfrom_rev = p.copyfrom_rev
+ self.action = p.action
+
# SVN conversion code stolen from bzr-svn and tailor
class convert_svn(converter_source):
def __init__(self, ui, url, rev=None):
@@ -51,16 +68,18 @@
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
self.encoding = 'UTF-8' # Subversion is always nominal UTF-8
try:
- self.transport = transport.SvnRaTransport(url = url)
+ self.transport = transport.SvnRaTransport(url=url)
self.ra = self.transport.ra
- self.ctx = svn.client.create_context()
+ self.ctx = self.transport.client
self.base = svn.ra.get_repos_root(self.ra)
self.module = self.url[len(self.base):]
self.modulemap = {} # revision, module
@@ -88,26 +107,47 @@
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
@@ -116,7 +156,7 @@
self.modecache[(file, rev)] = mode
return data
- def getmode(self, file, rev):
+ def getmode(self, file, rev):
return self.modecache[(file, rev)]
def getchanges(self, rev):
@@ -140,27 +180,79 @@
del self.commits[rev]
return commit
+ def get_log(self, paths, start, end, limit=0, discover_changed_paths=True,
+ strict_node_history=False):
+ '''wrapper for svn.ra.get_log.
+ on a large repository, svn.ra.get_log pins huge amounts of
+ memory that cannot be recovered. work around it by forking
+ and writing results over a pipe.'''
+
+ def child(fp):
+ protocol = -1
+ def receiver(orig_paths, revnum, author, date, message, pool):
+ if orig_paths is not None:
+ for k, v in orig_paths.iteritems():
+ orig_paths[k] = changedpath(v)
+ pickle.dump((orig_paths, revnum, author, date, message),
+ fp, protocol)
+
+ try:
+ # Use an ra of our own so that our parent can consume
+ # our results without confusing the server.
+ t = transport.SvnRaTransport(url=self.url)
+ svn.ra.get_log(t.ra, paths, start, end, limit,
+ discover_changed_paths,
+ strict_node_history,
+ receiver)
+ except SubversionException, (_, num):
+ self.ui.print_exc()
+ pickle.dump(num, fp, protocol)
+ else:
+ pickle.dump(None, fp, protocol)
+ fp.close()
+
+ def parent(fp):
+ while True:
+ entry = pickle.load(fp)
+ try:
+ orig_paths, revnum, author, date, message = entry
+ except:
+ if entry is None:
+ break
+ raise SubversionException("child raised exception", entry)
+ yield entry
+
+ rfd, wfd = os.pipe()
+ pid = os.fork()
+ if pid:
+ os.close(wfd)
+ for p in parent(os.fdopen(rfd, 'rb')):
+ yield p
+ ret = os.waitpid(pid, 0)[1]
+ if ret:
+ raise util.Abort(_('get_log %s') % util.explain_exit(ret))
+ else:
+ os.close(rfd)
+ child(os.fdopen(wfd, 'wb'))
+ os._exit(0)
+
def gettags(self):
tags = {}
- def parselogentry(*arg, **args):
- orig_paths, revnum, author, date, message, pool = arg
- for path in orig_paths:
- if not path.startswith('/tags/'):
- continue
- ent = orig_paths[path]
- source = ent.copyfrom_path
- rev = ent.copyfrom_rev
- tag = path.split('/', 2)[2]
- tags[tag] = self.revid(rev, module=source)
-
start = self.revnum(self.head)
try:
- svn.ra.get_log(self.ra, ['/tags'], 0, start, 0, True, False,
- parselogentry)
- return tags
- except SubversionException:
+ for entry in self.get_log(['/tags'], 0, start):
+ orig_paths, revnum, author, date, message = entry
+ for path in orig_paths:
+ if not path.startswith('/tags/'):
+ continue
+ ent = orig_paths[path]
+ source = ent.copyfrom_path
+ rev = ent.copyfrom_rev
+ tag = path.split('/', 2)[2]
+ tags[tag] = self.revid(rev, module=source)
+ except SubversionException, (_, num):
self.ui.note('no tags found at revision %d\n' % start)
- return {}
+ return tags
# -- helper functions --
@@ -193,8 +285,8 @@
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
@@ -242,25 +334,10 @@
self.ui.debug('Ignoring %r since it is not under %r\n' % (path, module))
return None
- received = []
- # svn.ra.get_log requires no other calls to the ra until it completes,
- # so we just collect the log entries and parse them afterwards
- def receivelog(*arg, **args):
- received.append(arg)
-
self.child_cset = None
- def parselogentry(*arg, **args):
- orig_paths, revnum, author, date, message, pool = arg
-
- if self.is_blacklisted(revnum):
- self.ui.note('skipping blacklisted revision %d\n' % revnum)
- return
-
- self.ui.debug("parsing revision %d\n" % revnum)
-
- if orig_paths is None:
- self.ui.debug('revision %d has no entries\n' % revnum)
- return
+ def parselogentry(orig_paths, revnum, author, date, message):
+ self.ui.debug("parsing revision %d (%d changes)\n" %
+ (revnum, len(orig_paths)))
if revnum in self.modulemap:
new_module = self.modulemap[revnum]
@@ -286,12 +363,11 @@
except IndexError:
branch = None
- paths = orig_paths.keys()
- paths.sort()
- for path in paths:
+ orig_paths = orig_paths.items()
+ orig_paths.sort()
+ for path, ent in orig_paths:
# self.ui.write("path %s\n" % path)
if path == self.module: # Follow branching back in history
- ent = orig_paths[path]
if ent:
if ent.copyfrom_path:
# ent.copyfrom_rev may not be the actual last revision
@@ -310,7 +386,6 @@
self.ui.debug("boring@%s: %s\n" % (revnum, path))
continue
entry = entrypath.decode(self.encoding)
- ent = orig_paths[path]
kind = svn.ra.check_path(self.ra, entrypath, revnum)
if kind == svn.core.svn_node_file:
@@ -373,7 +448,7 @@
# print "find children %s@%d from %d action %s" % (path, revnum, ent.copyfrom_rev, ent.action)
# Sometimes this is tricky. For example: in
# The Subversion Repository revision 6940 a dir
- # was copied and one of its files was deleted
+ # was copied and one of its files was deleted
# from the new location in the same commit. This
# code can't deal with that yet.
if ent.action == 'C':
@@ -387,7 +462,7 @@
for child in children:
# Can we move a child directory and its
# parent in the same commit? (probably can). Could
- # cause problems if instead of revnum -1,
+ # cause problems if instead of revnum -1,
# we have to look in (copyfrom_path, revnum - 1)
entrypath = get_entry_from_path("/" + child, module=old_module)
if entrypath:
@@ -417,7 +492,7 @@
for child in children:
# Can we move a child directory and its
# parent in the same commit? (probably can). Could
- # cause problems if instead of revnum -1,
+ # cause problems if instead of revnum -1,
# we have to look in (copyfrom_path, revnum - 1)
entrypath = get_entry_from_path("/" + child, module=self.module)
# print child, self.module, entrypath
@@ -466,7 +541,7 @@
self.modulemap[revnum] = self.module # track backwards in time
# a list of (filename, id) where id lets us retrieve the file.
- # eg in git, id is the object hash. for svn it'll be the
+ # eg in git, id is the object hash. for svn it'll be the
self.files[rev] = zip(entries, [rev] * len(entries))
if not entries:
return
@@ -480,8 +555,8 @@
author = author and self.recode(author) or ''
cset = commit(author=author,
- date=util.datestr(date),
- desc=log,
+ date=util.datestr(date),
+ desc=log,
parents=parents,
copies=copies,
branch=branch,
@@ -492,20 +567,24 @@
self.child_cset.parents = [rev]
self.child_cset = cset
- self.ui.note('fetching revision log for "%s" from %d to %d\n' % \
+ self.ui.note('fetching revision log for "%s" from %d to %d\n' %
(self.module, from_revnum, to_revnum))
try:
discover_changed_paths = True
strict_node_history = False
- svn.ra.get_log(self.ra, [self.module], from_revnum, to_revnum, 0,
- discover_changed_paths, strict_node_history,
- receivelog)
- for entry in received:
- parselogentry(*entry)
+ for entry in self.get_log([self.module], from_revnum, to_revnum):
+ orig_paths, revnum, author, date, message = entry
+ if self.is_blacklisted(revnum):
+ self.ui.note('skipping blacklisted revision %d\n' % revnum)
+ continue
+ if orig_paths is None:
+ self.ui.debug('revision %d has no entries\n' % revnum)
+ continue
+ parselogentry(orig_paths, revnum, author, date, message)
except SubversionException, (_, num):
if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION:
- raise NoSuchRevision(branch=self,
+ raise NoSuchRevision(branch=self,
revision="Revision number %d" % to_revnum)
raise
@@ -567,7 +646,6 @@
dirents = getdir[0]
if type(dirents) == int:
# got here once due to infinite recursion bug
- # pprint.pprint(getdir)
return
c = dirents.keys()
c.sort()
--- a/hgext/convert/transport.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/convert/transport.py Sat Jul 21 16:44:38 2007 -0500
@@ -24,9 +24,10 @@
from svn.core import SubversionException, Pool
import svn.ra
+import svn.client
import svn.core
-# Some older versions of the Python bindings need to be
+# Some older versions of the Python bindings need to be
# explicitly initialized. But what we want to do probably
# won't work worth a darn against those libraries anyway!
svn.ra.initialize()
@@ -48,21 +49,6 @@
]
return svn.core.svn_auth_open(providers, pool)
-
-# # The SVN libraries don't like trailing slashes...
-# return url.rstrip('/')
-
-
-class SvnRaCallbacks(svn.ra.callbacks2_t):
- """Remote access callbacks implementation for bzr-svn."""
- def __init__(self, pool):
- svn.ra.callbacks2_t.__init__(self)
- self.auth_baton = _create_auth_baton(pool)
- self.pool = pool
-
- def open_tmp_file(self, pool):
- return mktemp(prefix='tailor-svn')
-
class NotBranchError(SubversionException):
pass
@@ -73,25 +59,30 @@
def __init__(self, url="", ra=None):
self.pool = Pool()
self.svn_url = url
+ self.username = ''
+ self.password = ''
# Only Subversion 1.4 has reparent()
if ra is None or not hasattr(svn.ra, 'reparent'):
- self.callbacks = SvnRaCallbacks(self.pool)
+ self.client = svn.client.create_context(self.pool)
+ ab = _create_auth_baton(self.pool)
+ if False:
+ svn.core.svn_auth_set_parameter(
+ ab, svn.core.SVN_AUTH_PARAM_DEFAULT_USERNAME, self.username)
+ svn.core.svn_auth_set_parameter(
+ ab, svn.core.SVN_AUTH_PARAM_DEFAULT_PASSWORD, self.password)
+ self.client.auth_baton = ab
+ self.client.config = svn_config
try:
- ver = svn.ra.version()
- try: # Older SVN bindings
- self.ra = svn.ra.open2(self.svn_url.encode('utf8'), self.callbacks, None, svn_config, None)
- except TypeError, e:
- self.ra = svn.ra.open2(self.svn_url.encode('utf8'), self.callbacks, svn_config, None)
+ self.ra = svn.client.open_ra_session(
+ self.svn_url.encode('utf8'),
+ self.client, self.pool)
except SubversionException, (_, num):
- if num == svn.core.SVN_ERR_RA_ILLEGAL_URL:
- raise NotBranchError(url)
- if num == svn.core.SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED:
- raise NotBranchError(url)
- if num == svn.core.SVN_ERR_BAD_URL:
+ if num in (svn.core.SVN_ERR_RA_ILLEGAL_URL,
+ svn.core.SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED,
+ svn.core.SVN_ERR_BAD_URL):
raise NotBranchError(url)
raise
-
else:
self.ra = ra
svn.ra.reparent(self.ra, self.svn_url.encode('utf8'))
--- a/hgext/purge.py Sat Jul 21 16:18:42 2007 -0500
+++ b/hgext/purge.py Sat Jul 21 16:44:38 2007 -0500
@@ -31,7 +31,7 @@
from mercurial.i18n import _
import os
-def dopurge(ui, repo, dirs=None, act=True, ignored=False,
+def dopurge(ui, repo, dirs=None, act=True, ignored=False,
abort_on_err=False, eol='\n',
force=False, include=None, exclude=None):
def error(msg):
--- a/mercurial/archival.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/archival.py Sat Jul 21 16:44:38 2007 -0500
@@ -200,8 +200,9 @@
prefix is name of path to put before every archive member.'''
- def write(name, mode, islink, data):
+ def write(name, mode, islink, getdata):
if matchfn and not matchfn(name): return
+ data = getdata()
if decode:
data = repo.wwritedata(name, data)
archiver.addfile(name, mode, islink, data)
@@ -212,8 +213,8 @@
items = m.items()
items.sort()
write('.hg_archival.txt', 0644, False,
- 'repo: %s\nnode: %s\n' % (hex(repo.changelog.node(0)), hex(node)))
+ lambda: 'repo: %s\nnode: %s\n' % (hex(repo.changelog.node(0)), hex(node)))
for filename, filenode in items:
write(filename, m.execf(filename) and 0755 or 0644, m.linkf(filename),
- repo.file(filename).read(filenode))
+ lambda: repo.file(filename).read(filenode))
archiver.done()
--- a/mercurial/changelog.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/changelog.py Sat Jul 21 16:44:38 2007 -0500
@@ -42,7 +42,7 @@
def flush(self):
pass
def close(self):
- close(self.fp)
+ self.fp.close()
def seek(self, offset, whence=0):
'''virtual file offset spans real file and data'''
@@ -58,7 +58,6 @@
def read(self, count=-1):
'''only trick here is reads that span real file and data'''
ret = ""
- old_offset = self.offset
if self.offset < self.size:
s = self.fp.read(count)
ret = s
--- a/mercurial/cmdutil.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/cmdutil.py Sat Jul 21 16:44:38 2007 -0500
@@ -316,7 +316,7 @@
util._fallbackencoding = fallback
fullargs = args
- cmd, func, args, options, cmdoptions = parse(ui, args)
+ cmd, func, args, options, cmdoptions = parse(lui, args)
if options["config"]:
raise util.Abort(_("Option --config may not be abbreviated!"))
--- a/mercurial/commands.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/commands.py Sat Jul 21 16:44:38 2007 -0500
@@ -8,7 +8,7 @@
import demandimport; demandimport.enable()
from node import *
from i18n import _
-import bisect, os, re, sys, urllib, shlex, stat
+import bisect, os, re, sys, urllib, stat
import ui, hg, util, revlog, bundlerepo, extensions
import difflib, patch, time, help, mdiff, tempfile
import errno, version, socket
@@ -1362,7 +1362,7 @@
addglobalopts(False)
- def helplist(select=None):
+ def helplist(header, select=None):
h = {}
cmds = {}
for c, e in table.items():
@@ -1380,6 +1380,11 @@
h[f] = doc.splitlines(0)[0].rstrip()
cmds[f] = c.lstrip("^")
+ if not h:
+ ui.status(_('no commands defined\n'))
+ return
+
+ ui.status(header)
fns = h.keys()
fns.sort()
m = max(map(len, fns))
@@ -1429,14 +1434,10 @@
try:
ct = mod.cmdtable
except AttributeError:
- ct = None
- if not ct:
- ui.status(_('no commands defined\n'))
- return
-
- ui.status(_('list of commands:\n\n'))
+ ct = {}
+
modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
- helplist(modcmds.has_key)
+ helplist(_('list of commands:\n\n'), modcmds.has_key)
if name and name != 'shortlist':
i = None
@@ -1460,11 +1461,11 @@
# list of commands
if name == "shortlist":
- ui.status(_('basic commands:\n\n'))
+ header = _('basic commands:\n\n')
else:
- ui.status(_('list of commands:\n\n'))
-
- helplist()
+ header = _('list of commands:\n\n')
+
+ helplist(header)
# list all option lists
opt_output = []
@@ -2040,14 +2041,12 @@
for name, path in ui.configitems("paths"):
ui.write("%s = %s\n" % (name, path))
-def postincoming(ui, repo, modheads, optupdate, wasempty):
+def postincoming(ui, repo, modheads, optupdate):
if modheads == 0:
return
if optupdate:
- if wasempty:
- return hg.update(repo, repo.lookup('default'))
- elif modheads == 1:
- return hg.update(repo, repo.changelog.tip()) # update
+ if modheads == 1:
+ return hg.update(repo, None)
else:
ui.status(_("not updating, since new heads added\n"))
if modheads > 1:
@@ -2108,9 +2107,8 @@
error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
raise util.Abort(error)
- wasempty = repo.changelog.count() == 0
modheads = repo.pull(other, heads=revs, force=opts['force'])
- return postincoming(ui, repo, modheads, opts['update'], wasempty)
+ return postincoming(ui, repo, modheads, opts['update'])
def push(ui, repo, dest=None, **opts):
"""push changes to the specified destination
@@ -2211,7 +2209,6 @@
Modified files and added files are not removed by default. To
remove them, use the -f/--force option.
"""
- names = []
if not opts['after'] and not pats:
raise util.Abort(_('no files specified'))
files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
@@ -2681,8 +2678,6 @@
bundle command.
"""
fnames = (fname1,) + fnames
- result = None
- wasempty = repo.changelog.count() == 0
for fname in fnames:
if os.path.exists(fname):
f = open(fname, "rb")
@@ -2691,7 +2686,7 @@
gen = changegroup.readbundle(f, fname)
modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
- return postincoming(ui, repo, modheads, opts['update'], wasempty)
+ return postincoming(ui, repo, modheads, opts['update'])
def update(ui, repo, node=None, rev=None, clean=False, date=None):
"""update working directory
--- a/mercurial/dirstate.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/dirstate.py Sat Jul 21 16:44:38 2007 -0500
@@ -21,6 +21,7 @@
self._opener = opener
self._root = root
self._dirty = False
+ self._dirtypl = False
self._ui = ui
def __getattr__(self, name):
@@ -113,7 +114,7 @@
return self._branch
def setparents(self, p1, p2=nullid):
- self._dirty = True
+ self._dirty = self._dirtypl = True
self._pl = p1, p2
def setbranch(self, branch):
@@ -123,7 +124,8 @@
def _read(self):
self._map = {}
self._copymap = {}
- self._pl = [nullid, nullid]
+ if not self._dirtypl:
+ self._pl = [nullid, nullid]
try:
st = self._opener("dirstate").read()
except IOError, err:
@@ -132,7 +134,8 @@
if not st:
return
- self._pl = [st[:20], st[20: 40]]
+ if not self._dirtypl:
+ self._pl = [st[:20], st[20: 40]]
# deref fields so they will be local in loop
dmap = self._map
@@ -157,8 +160,8 @@
def invalidate(self):
for a in "_map _copymap _branch _pl _dirs _ignore".split():
- if hasattr(self, a):
- self.__delattr__(a)
+ if a in self.__dict__:
+ delattr(self, a)
self._dirty = False
def copy(self, source, dest):
@@ -271,7 +274,7 @@
st = self._opener("dirstate", "w", atomictemp=True)
st.write(cs.getvalue())
st.rename()
- self._dirty = False
+ self._dirty = self._dirtypl = False
def _filter(self, files):
ret = {}
--- a/mercurial/hgweb/hgwebdir_mod.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/hgweb/hgwebdir_mod.py Sat Jul 21 16:44:38 2007 -0500
@@ -244,7 +244,7 @@
if up < 0:
break
virtual = virtual[:up]
-
+
req.write(tmpl("notfound", repo=virtual))
else:
if req.form.has_key('static'):
--- a/mercurial/hgweb/server.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/hgweb/server.py Sat Jul 21 16:44:38 2007 -0500
@@ -39,7 +39,7 @@
class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
url_scheme = 'http'
-
+
def __init__(self, *args, **kargs):
self.protocol_version = 'HTTP/1.1'
BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
@@ -173,7 +173,7 @@
class _shgwebhandler(_hgwebhandler):
url_scheme = 'https'
-
+
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
--- a/mercurial/lock.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/lock.py Sat Jul 21 16:44:38 2007 -0500
@@ -29,14 +29,13 @@
# old-style lock: symlink to pid
# new-style lock: symlink to hostname:pid
+ _host = None
+
def __init__(self, file, timeout=-1, releasefn=None, desc=None):
self.f = file
self.held = 0
self.timeout = timeout
self.releasefn = releasefn
- self.id = None
- self.host = None
- self.pid = None
self.desc = desc
self.lock()
@@ -59,13 +58,12 @@
inst.locker)
def trylock(self):
- if self.id is None:
- self.host = socket.gethostname()
- self.pid = os.getpid()
- self.id = '%s:%s' % (self.host, self.pid)
+ if lock._host is None:
+ lock._host = socket.gethostname()
+ lockname = '%s:%s' % (lock._host, os.getpid())
while not self.held:
try:
- util.makelock(self.id, self.f)
+ util.makelock(lockname, self.f)
self.held = 1
except (OSError, IOError), why:
if why.errno == errno.EEXIST:
@@ -93,7 +91,7 @@
host, pid = locker.split(":", 1)
except ValueError:
return locker
- if host != self.host:
+ if host != lock._host:
return locker
try:
pid = int(pid)
--- a/mercurial/patch.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/patch.py Sat Jul 21 16:44:38 2007 -0500
@@ -281,7 +281,7 @@
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 @@
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 @@
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 @@
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 @@
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.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/util.py Sat Jul 21 16:44:38 2007 -0500
@@ -616,7 +616,7 @@
"""forcibly rename a file"""
try:
os.rename(src, dst)
- except OSError, err:
+ except OSError, err: # FIXME: check err (EEXIST ?)
# on windows, rename to existing file is not allowed, so we
# must delete destination first. but if file is open, unlink
# schedules it for delete but does not delete it. rename
@@ -1303,7 +1303,11 @@
os.makedirs(dirname)
if self._can_symlink:
- os.symlink(src, linkname)
+ try:
+ os.symlink(src, linkname)
+ except OSError, err:
+ raise OSError(err.errno, _('could not symlink to %r: %s') %
+ (src, err.strerror), linkname)
else:
f = self(self, dst, "w")
f.write(src)
--- a/mercurial/util_win32.py Sat Jul 21 16:18:42 2007 -0500
+++ b/mercurial/util_win32.py Sat Jul 21 16:44:38 2007 -0500
@@ -209,9 +209,9 @@
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-extension Sat Jul 21 16:18:42 2007 -0500
+++ b/tests/test-extension Sat Jul 21 16:44:38 2007 -0500
@@ -64,3 +64,18 @@
echo '[extensions]' > $HGRCPATH
echo "empty = $emptypath" >> $HGRCPATH
hg help empty
+
+cat > debugextension.py <<EOF
+'''only debugcommands
+'''
+def debugfoobar(ui, repo, *args, **opts):
+ "yet another debug command"
+ pass
+
+cmdtable = {"debugfoobar": (debugfoobar, (), "hg debugfoobar")}
+EOF
+debugpath=`pwd`/debugextension.py
+echo '[extensions]' > $HGRCPATH
+echo "debugextension = $debugpath" >> $HGRCPATH
+hg help debugextension
+hg --debug help debugextension
--- a/tests/test-extension.out Sat Jul 21 16:18:42 2007 -0500
+++ b/tests/test-extension.out Sat Jul 21 16:44:38 2007 -0500
@@ -22,3 +22,30 @@
empty extension - empty cmdtable
no commands defined
+debugextension extension - only debugcommands
+
+no commands defined
+debugextension extension - only debugcommands
+
+list of commands:
+
+ debugfoobar:
+ yet another debug command
+
+global options:
+ -R --repository repository root directory or symbolic path name
+ --cwd change working directory
+ -y --noninteractive do not prompt, assume 'yes' for any required answers
+ -q --quiet suppress output
+ -v --verbose enable additional output
+ --config set/override config option
+ --debug enable debugging output
+ --debugger start debugger
+ --encoding set the charset encoding (default: ascii)
+ --encodingmode set the charset encoding mode (default: strict)
+ --lsprof print improved command execution profile
+ --traceback print traceback on exception
+ --time time how long the command takes
+ --profile print command execution profile
+ --version output version information and exit
+ -h --help display help and exit
--- a/tests/test-tag Sat Jul 21 16:18:42 2007 -0500
+++ b/tests/test-tag Sat Jul 21 16:44:38 2007 -0500
@@ -29,14 +29,18 @@
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