--- a/contrib/bash_completion Sat Oct 03 23:36:08 2009 +0200
+++ b/contrib/bash_completion Sat Oct 03 23:38:10 2009 +0200
@@ -530,3 +530,20 @@
return
}
+# shelve
+_hg_shelves()
+{
+ local shelves="$("$hg" unshelve -l . 2>/dev/null)"
+ local IFS=$'\n'
+ COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur"))
+}
+
+_hg_cmd_shelve()
+{
+ _hg_status "mard"
+}
+
+_hg_cmd_unshelve()
+{
+ _hg_shelves
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/shrink-revlog.py Sat Oct 03 23:38:10 2009 +0200
@@ -0,0 +1,218 @@
+#!/usr/bin/env python
+
+"""\
+Reorder a revlog (by default the the manifest file in the current
+repository) to save space. Specifically, this topologically sorts the
+revisions in the revlog so that revisions on the same branch are adjacent
+as much as possible. This is a workaround for the fact that Mercurial
+computes deltas relative to the previous revision rather than relative to a
+parent revision. This is *not* safe to run on a changelog.
+"""
+
+# Originally written by Benoit Boissinot <benoit.boissinot at ens-lyon.org>
+# as a patch to rewrite-log. Cleaned up, refactored, documented, and
+# renamed by Greg Ward <greg at gerg.ca>.
+
+# XXX would be nice to have a way to verify the repository after shrinking,
+# e.g. by comparing "before" and "after" states of random changesets
+# (maybe: export before, shrink, export after, diff).
+
+import sys, os, tempfile
+import optparse
+from mercurial import ui as ui_, hg, revlog, transaction, node, util
+
+def toposort(rl):
+ write = sys.stdout.write
+
+ children = {}
+ root = []
+ # build children and roots
+ write('reading %d revs ' % len(rl))
+ try:
+ for i in rl:
+ children[i] = []
+ parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
+ # in case of duplicate parents
+ if len(parents) == 2 and parents[0] == parents[1]:
+ del parents[1]
+ for p in parents:
+ assert p in children
+ children[p].append(i)
+
+ if len(parents) == 0:
+ root.append(i)
+
+ if i % 1000 == 0:
+ write('.')
+ finally:
+ write('\n')
+
+ # XXX this is a reimplementation of the 'branchsort' topo sort
+ # algorithm in hgext.convert.convcmd... would be nice not to duplicate
+ # the algorithm
+ write('sorting ...')
+ visit = root
+ ret = []
+ while visit:
+ i = visit.pop(0)
+ ret.append(i)
+ if i not in children:
+ # This only happens if some node's p1 == p2, which can
+ # happen in the manifest in certain circumstances.
+ continue
+ next = []
+ for c in children.pop(i):
+ parents_unseen = [p for p in rl.parentrevs(c)
+ if p != node.nullrev and p in children]
+ if len(parents_unseen) == 0:
+ next.append(c)
+ visit = next + visit
+ write('\n')
+ return ret
+
+def writerevs(r1, r2, order, tr):
+ write = sys.stdout.write
+ write('writing %d revs ' % len(order))
+ try:
+ count = 0
+ for rev in order:
+ n = r1.node(rev)
+ p1, p2 = r1.parents(n)
+ l = r1.linkrev(rev)
+ t = r1.revision(n)
+ n2 = r2.addrevision(t, tr, l, p1, p2)
+
+ if count % 1000 == 0:
+ write('.')
+ count += 1
+ finally:
+ write('\n')
+
+def report(olddatafn, newdatafn):
+ oldsize = float(os.stat(olddatafn).st_size)
+ newsize = float(os.stat(newdatafn).st_size)
+
+ # argh: have to pass an int to %d, because a float >= 2^32
+ # blows up under Python 2.5 or earlier
+ sys.stdout.write('old file size: %12d bytes (%6.1f MiB)\n'
+ % (int(oldsize), oldsize/1024/1024))
+ sys.stdout.write('new file size: %12d bytes (%6.1f MiB)\n'
+ % (int(newsize), newsize/1024/1024))
+
+ shrink_percent = (oldsize - newsize) / oldsize * 100
+ shrink_factor = oldsize / newsize
+ sys.stdout.write('shrinkage: %.1f%% (%.1fx)\n'
+ % (shrink_percent, shrink_factor))
+
+def main():
+
+ # Unbuffer stdout for nice progress output.
+ sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+ write = sys.stdout.write
+
+ parser = optparse.OptionParser(description=__doc__)
+ parser.add_option('-R', '--repository',
+ default=os.path.curdir,
+ metavar='REPO',
+ help='repository root directory [default: current dir]')
+ parser.add_option('--revlog',
+ metavar='FILE',
+ help='shrink FILE [default: REPO/hg/store/00manifest.i]')
+ (options, args) = parser.parse_args()
+ if args:
+ parser.error('too many arguments')
+
+ # Open the specified repository.
+ ui = ui_.ui()
+ repo = hg.repository(ui, options.repository)
+ if not repo.local():
+ parser.error('not a local repository: %s' % options.repository)
+
+ if options.revlog is None:
+ indexfn = repo.sjoin('00manifest.i')
+ else:
+ if not options.revlog.endswith('.i'):
+ parser.error('--revlog option must specify the revlog index file '
+ '(*.i), not %s' % options.revlog)
+
+ indexfn = os.path.realpath(options.revlog)
+ store = repo.sjoin('')
+ if not indexfn.startswith(store):
+ parser.error('--revlog option must specify a revlog in %s, not %s'
+ % (store, indexfn))
+
+ datafn = indexfn[:-2] + '.d'
+ if not os.path.exists(indexfn):
+ parser.error('no such file: %s' % indexfn)
+ if '00changelog' in indexfn:
+ parser.error('shrinking the changelog will corrupt your repository')
+ if not os.path.exists(datafn):
+ # This is just a lazy shortcut because I can't be bothered to
+ # handle all the special cases that entail from no .d file.
+ parser.error('%s does not exist: revlog not big enough '
+ 'to be worth shrinking' % datafn)
+
+ oldindexfn = indexfn + '.old'
+ olddatafn = datafn + '.old'
+ if os.path.exists(oldindexfn) or os.path.exists(olddatafn):
+ parser.error('one or both of\n'
+ ' %s\n'
+ ' %s\n'
+ 'exists from a previous run; please clean up before '
+ 'running again'
+ % (oldindexfn, olddatafn))
+
+ write('shrinking %s\n' % indexfn)
+ prefix = os.path.basename(indexfn)[:-1]
+ (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn),
+ prefix=prefix,
+ suffix='.i')
+ tmpdatafn = tmpindexfn[:-2] + '.d'
+ os.close(tmpfd)
+
+ r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), indexfn)
+ r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), tmpindexfn)
+
+ # Don't use repo.transaction(), because then things get hairy with
+ # paths: some need to be relative to .hg, and some need to be
+ # absolute. Doing it this way keeps things simple: everything is an
+ # absolute path.
+ lock = repo.lock(wait=False)
+ tr = transaction.transaction(sys.stderr.write,
+ open,
+ repo.sjoin('journal'))
+
+ try:
+ try:
+ order = toposort(r1)
+ writerevs(r1, r2, order, tr)
+ report(datafn, tmpdatafn)
+ tr.close()
+ except:
+ # Abort transaction first, so we truncate the files before
+ # deleting them.
+ tr.abort()
+ if os.path.exists(tmpindexfn):
+ os.unlink(tmpindexfn)
+ if os.path.exists(tmpdatafn):
+ os.unlink(tmpdatafn)
+ raise
+ finally:
+ lock.release()
+
+ os.link(indexfn, oldindexfn)
+ os.link(datafn, olddatafn)
+ os.rename(tmpindexfn, indexfn)
+ os.rename(tmpdatafn, datafn)
+ write('note: old revlog saved in:\n'
+ ' %s\n'
+ ' %s\n'
+ '(You can delete those files when you are satisfied that your\n'
+ 'repository is still sane. '
+ 'Running \'hg verify\' is strongly recommended.)\n'
+ % (oldindexfn, olddatafn))
+
+try:
+ main()
+except KeyboardInterrupt:
+ sys.exit("interrupted")
--- a/doc/hg.1.txt Sat Oct 03 23:36:08 2009 +0200
+++ b/doc/hg.1.txt Sat Oct 03 23:38:10 2009 +0200
@@ -95,6 +95,6 @@
-------
Copyright \(C) 2005-2009 Matt Mackall.
Free use of this software is granted under the terms of the GNU General
-Public License (GPL).
+Public License version 2.
.. include:: common.txt
--- a/doc/hgignore.5.txt Sat Oct 03 23:36:08 2009 +0200
+++ b/doc/hgignore.5.txt Sat Oct 03 23:38:10 2009 +0200
@@ -106,6 +106,6 @@
This manual page is copyright 2006 Vadim Gelfer.
Mercurial is copyright 2005-2009 Matt Mackall.
Free use of this software is granted under the terms of the GNU General
-Public License (GPL).
+Public License version 2.
.. include:: common.txt
--- a/doc/hgrc.5.txt Sat Oct 03 23:36:08 2009 +0200
+++ b/doc/hgrc.5.txt Sat Oct 03 23:38:10 2009 +0200
@@ -946,6 +946,6 @@
This manual page is copyright 2005 Bryan O'Sullivan.
Mercurial is copyright 2005-2009 Matt Mackall.
Free use of this software is granted under the terms of the GNU General
-Public License (GPL).
+Public License version 2.
.. include:: common.txt
--- a/hgext/color.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/color.py Sat Oct 03 23:38:10 2009 +0200
@@ -160,9 +160,8 @@
return retval
_patch_effects = { 'applied': ['blue', 'bold', 'underline'],
- 'missing': ['red', 'bold'],
- 'unapplied': ['black', 'bold'], }
-
+ 'missing': ['red', 'bold'],
+ 'unapplied': ['black', 'bold'], }
def colorwrap(orig, s):
'''wrap ui.write for colored diff output'''
lines = s.split('\n')
--- a/hgext/convert/subversion.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/convert/subversion.py Sat Oct 03 23:38:10 2009 +0200
@@ -153,11 +153,13 @@
def issvnurl(url):
try:
proto, path = url.split('://', 1)
- path = urllib.url2pathname(path)
+ if proto == 'file':
+ path = urllib.url2pathname(path)
except ValueError:
proto = 'file'
path = os.path.abspath(url)
- path = path.replace(os.sep, '/')
+ if proto == 'file':
+ path = path.replace(os.sep, '/')
check = protomap.get(proto, lambda p, p2: False)
while '/' in path:
if check(path, proto):
--- a/hgext/extdiff.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/extdiff.py Sat Oct 03 23:38:10 2009 +0200
@@ -42,9 +42,9 @@
'''
from mercurial.i18n import _
-from mercurial.node import short
+from mercurial.node import short, nullid
from mercurial import cmdutil, util, commands
-import os, shlex, shutil, tempfile
+import os, shlex, shutil, tempfile, re
def snapshot(ui, repo, files, node, tmproot):
'''snapshot files as of some revision
@@ -69,7 +69,7 @@
for fn in files:
wfn = util.pconvert(fn)
if not wfn in ctx:
- # skipping new file after a merge ?
+ # File doesn't exist; could be a bogus modify
continue
ui.note(' %s\n' % wfn)
dest = os.path.join(base, wfn)
@@ -96,52 +96,95 @@
revs = opts.get('rev')
change = opts.get('change')
+ args = ' '.join(diffopts)
+ do3way = '$parent2' in args
if revs and change:
msg = _('cannot specify --rev and --change at the same time')
raise util.Abort(msg)
elif change:
node2 = repo.lookup(change)
- node1 = repo[node2].parents()[0].node()
+ node1a, node1b = repo.changelog.parents(node2)
else:
- node1, node2 = cmdutil.revpair(repo, revs)
+ node1a, node2 = cmdutil.revpair(repo, revs)
+ if not revs:
+ node1b = repo.dirstate.parents()[1]
+ else:
+ node1b = nullid
+
+ # Disable 3-way merge if there is only one parent
+ if do3way:
+ if node1b == nullid:
+ do3way = False
matcher = cmdutil.match(repo, pats, opts)
- modified, added, removed = repo.status(node1, node2, matcher)[:3]
- if not (modified or added or removed):
- return 0
+ mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
+ if do3way:
+ mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
+ else:
+ mod_b, add_b, rem_b = set(), set(), set()
+ modadd = mod_a | add_a | mod_b | add_b
+ common = modadd | rem_a | rem_b
+ if not common:
+ return 0
tmproot = tempfile.mkdtemp(prefix='extdiff.')
- dir2root = ''
try:
- # Always make a copy of node1
- dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0]
- changes = len(modified) + len(removed) + len(added)
+ # Always make a copy of node1a (and node1b, if applicable)
+ dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
+ dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
+ if do3way:
+ dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
+ dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
+ else:
+ dir1b = None
+
+ fns_and_mtime = []
# If node2 in not the wc or there is >1 change, copy it
- if node2 or changes > 1:
- dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot)
+ dir2root = ''
+ if node2:
+ dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
+ elif len(common) > 1:
+ #we only actually need to get the files to copy back to the working
+ #dir in this case (because the other cases are: diffing 2 revisions
+ #or single file -- in which case the file is already directly passed
+ #to the diff tool).
+ dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
else:
# This lets the diff tool open the changed file directly
dir2 = ''
dir2root = repo.root
- fns_and_mtime = []
# If only one change, diff the files instead of the directories
- if changes == 1 :
- if len(modified):
- dir1 = os.path.join(dir1, util.localpath(modified[0]))
- dir2 = os.path.join(dir2root, dir2, util.localpath(modified[0]))
- elif len(removed) :
- dir1 = os.path.join(dir1, util.localpath(removed[0]))
- dir2 = os.devnull
- else:
- dir1 = os.devnull
- dir2 = os.path.join(dir2root, dir2, util.localpath(added[0]))
+ # Handle bogus modifies correctly by checking if the files exist
+ if len(common) == 1:
+ common_file = util.localpath(common.pop())
+ dir1a = os.path.join(dir1a, common_file)
+ if not os.path.isfile(os.path.join(tmproot, dir1a)):
+ dir1a = os.devnull
+ if do3way:
+ dir1b = os.path.join(dir1b, common_file)
+ if not os.path.isfile(os.path.join(tmproot, dir1b)):
+ dir1b = os.devnull
+ dir2 = os.path.join(dir2root, dir2, common_file)
- cmdline = ('%s %s %s %s' %
- (util.shellquote(diffcmd), ' '.join(diffopts),
- util.shellquote(dir1), util.shellquote(dir2)))
+ # Function to quote file/dir names in the argument string
+ # When not operating in 3-way mode, an empty string is returned for parent2
+ replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b, child=dir2)
+ def quote(match):
+ key = match.group()[1:]
+ if not do3way and key == 'parent2':
+ return ''
+ return util.shellquote(replace[key])
+
+ # Match parent2 first, so 'parent1?' will match both parent1 and parent
+ regex = '\$(parent2|parent1?|child)'
+ if not do3way and not re.search(regex, args):
+ args += ' $parent1 $child'
+ args = re.sub(regex, quote, args)
+ cmdline = util.shellquote(diffcmd) + ' ' + args
+
ui.debug('running %r in %s\n' % (cmdline, tmproot))
util.system(cmdline, cwd=tmproot)
@@ -173,11 +216,11 @@
that revision is compared to the working directory, and, when no
revisions are specified, the working directory files are compared
to its parent.'''
- program = opts['program'] or 'diff'
- if opts['program']:
- option = opts['option']
- else:
- option = opts['option'] or ['-Npru']
+ program = opts.get('program')
+ option = opts.get('option')
+ if not program:
+ program = 'diff'
+ option = option or ['-Npru']
return dodiff(ui, repo, program, option, pats, opts)
cmdtable = {
--- a/hgext/inotify/__init__.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/inotify/__init__.py Sat Oct 03 23:38:10 2009 +0200
@@ -17,28 +17,7 @@
def serve(ui, repo, **opts):
'''start an inotify server for this repository'''
- timeout = opts.get('timeout')
- if timeout:
- timeout = float(timeout) * 1e3
-
- class service(object):
- def init(self):
- try:
- self.master = server.master(ui, repo.dirstate,
- repo.root, timeout)
- except server.AlreadyStartedException, inst:
- raise util.Abort(str(inst))
-
- def run(self):
- try:
- self.master.run()
- finally:
- self.master.shutdown()
-
- service = service()
- logfile = ui.config('inotify', 'log')
- cmdutil.service(opts, initfn=service.init, runfn=service.run,
- logfile=logfile)
+ server.start(ui, repo.dirstate, repo.root, opts)
def debuginotify(ui, repo, **opts):
'''debugging information for inotify extension
--- a/hgext/inotify/client.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/inotify/client.py Sat Oct 03 23:38:10 2009 +0200
@@ -34,7 +34,8 @@
self.ui.debug('(starting inotify server)\n')
try:
try:
- server.start(self.ui, self.dirstate, self.root)
+ server.start(self.ui, self.dirstate, self.root,
+ dict(daemon=True, daemon_pipefds=''))
except server.AlreadyStartedException, inst:
# another process may have started its own
# inotify server while this one was starting.
--- a/hgext/inotify/server.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/inotify/server.py Sat Oct 03 23:38:10 2009 +0200
@@ -7,7 +7,7 @@
# GNU General Public License version 2, incorporated herein by reference.
from mercurial.i18n import _
-from mercurial import osutil, util
+from mercurial import cmdutil, osutil, util
import common
import errno, os, select, socket, stat, struct, sys, tempfile, time
@@ -823,52 +823,29 @@
sys.exit(0)
pollable.run()
-def start(ui, dirstate, root):
- def closefds(ignore):
- # (from python bug #1177468)
- # close all inherited file descriptors
- # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG
- # a file descriptor is kept internally as os._urandomfd (created on demand
- # the first time os.urandom() is called), and should not be closed
- try:
- os.urandom(4)
- urandom_fd = getattr(os, '_urandomfd', None)
- except AttributeError:
- urandom_fd = None
- ignore.append(urandom_fd)
- for fd in range(3, 256):
- if fd in ignore:
- continue
+def start(ui, dirstate, root, opts):
+ timeout = opts.get('timeout')
+ if timeout:
+ timeout = float(timeout) * 1e3
+
+ class service(object):
+ def init(self):
try:
- os.close(fd)
- except OSError:
- pass
-
- m = master(ui, dirstate, root)
- sys.stdout.flush()
- sys.stderr.flush()
+ self.master = master(ui, dirstate, root, timeout)
+ except AlreadyStartedException, inst:
+ raise util.Abort(str(inst))
- pid = os.fork()
- if pid:
- return pid
-
- closefds(pollable.instances.keys())
- os.setsid()
-
- fd = os.open('/dev/null', os.O_RDONLY)
- os.dup2(fd, 0)
- if fd > 0:
- os.close(fd)
+ def run(self):
+ try:
+ self.master.run()
+ finally:
+ self.master.shutdown()
- fd = os.open(ui.config('inotify', 'log', '/dev/null'),
- os.O_RDWR | os.O_CREAT | os.O_TRUNC)
- os.dup2(fd, 1)
- os.dup2(fd, 2)
- if fd > 2:
- os.close(fd)
+ runargs = None
+ if 'inserve' not in sys.argv:
+ runargs = [sys.argv[0], 'inserve', '-R', root]
- try:
- m.run()
- finally:
- m.shutdown()
- os._exit(0)
+ service = service()
+ logfile = ui.config('inotify', 'log')
+ cmdutil.service(opts, initfn=service.init, runfn=service.run,
+ logfile=logfile, runargs=runargs)
--- a/hgext/keyword.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/keyword.py Sat Oct 03 23:38:10 2009 +0200
@@ -244,12 +244,14 @@
return t2 != text
return revlog.revlog.cmp(self, node, text)
-def _status(ui, repo, kwt, unknown, *pats, **opts):
+def _status(ui, repo, kwt, *pats, **opts):
'''Bails out if [keyword] configuration is not active.
Returns status of working directory.'''
if kwt:
- match = cmdutil.match(repo, pats, opts)
- return repo.status(match=match, unknown=unknown, clean=True)
+ unknown = (opts.get('unknown') or opts.get('all')
+ or opts.get('untracked'))
+ return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
+ unknown=unknown)
if ui.configitems('keyword'):
raise util.Abort(_('[keyword] patterns cannot match'))
raise util.Abort(_('no [keyword] patterns configured'))
@@ -259,7 +261,7 @@
if repo.dirstate.parents()[1] != nullid:
raise util.Abort(_('outstanding uncommitted merge'))
kwt = kwtools['templater']
- status = _status(ui, repo, kwt, False, *pats, **opts)
+ status = _status(ui, repo, kwt, *pats, **opts)
modified, added, removed, deleted = status[:4]
if modified or added or removed or deleted:
raise util.Abort(_('outstanding uncommitted changes'))
@@ -380,30 +382,32 @@
See "hg help keyword" on how to construct patterns both for
inclusion and exclusion of files.
- Use -u/--untracked to list untracked files as well.
-
- With -a/--all and -v/--verbose the codes used to show the status
+ With -A/--all and -v/--verbose the codes used to show the status
of files are::
K = keyword expansion candidate
- k = keyword expansion candidate (untracked)
+ k = keyword expansion candidate (not tracked)
I = ignored
- i = ignored (untracked)
+ i = ignored (not tracked)
'''
kwt = kwtools['templater']
- status = _status(ui, repo, kwt, opts.get('untracked'), *pats, **opts)
+ status = _status(ui, repo, kwt, *pats, **opts)
+ cwd = pats and repo.getcwd() or ''
modified, added, removed, deleted, unknown, ignored, clean = status
- files = sorted(modified + added + clean)
+ files = []
+ if not (opts.get('unknown') or opts.get('untracked')) or opts.get('all'):
+ files = sorted(modified + added + clean)
wctx = repo[None]
kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
- kwuntracked = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
- cwd = pats and repo.getcwd() or ''
- kwfstats = (not opts.get('ignore') and
- (('K', kwfiles), ('k', kwuntracked),) or ())
+ kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
+ if not opts.get('ignore') or opts.get('all'):
+ showfiles = kwfiles, kwunknown
+ else:
+ showfiles = [], []
if opts.get('all') or opts.get('ignore'):
- kwfstats += (('I', [f for f in files if f not in kwfiles]),
- ('i', [f for f in unknown if f not in kwuntracked]),)
- for char, filenames in kwfstats:
+ showfiles += ([f for f in files if f not in kwfiles],
+ [f for f in unknown if f not in kwunknown])
+ for char, filenames in zip('KkIi', showfiles):
fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
for f in filenames:
ui.write(fmt % repo.pathto(f, cwd))
@@ -545,9 +549,12 @@
_('hg kwexpand [OPTION]... [FILE]...')),
'kwfiles':
(files,
- [('a', 'all', None, _('show keyword status flags of all files')),
+ [('A', 'all', None, _('show keyword status flags of all files')),
('i', 'ignore', None, _('show files excluded from expansion')),
- ('u', 'untracked', None, _('additionally show untracked files')),
+ ('u', 'unknown', None, _('only show unknown (not tracked) files')),
+ ('a', 'all', None,
+ _('show keyword status flags of all files (DEPRECATED)')),
+ ('u', 'untracked', None, _('only show untracked files (DEPRECATED)')),
] + commands.walkopts,
_('hg kwfiles [OPTION]... [FILE]...')),
'kwshrink': (shrink, commands.walkopts,
--- a/hgext/notify.py Sat Oct 03 23:36:08 2009 +0200
+++ b/hgext/notify.py Sat Oct 03 23:38:10 2009 +0200
@@ -43,6 +43,7 @@
diffstat = True # add a diffstat before the diff content
sources = serve # notify if source of incoming changes in this list
# (serve == ssh or http, push, pull, bundle)
+ merge = False # send notification for merges (default True)
[email]
from = user@host.com # email address to send as if none given
[web]
@@ -111,6 +112,7 @@
self.test = self.ui.configbool('notify', 'test', True)
self.charsets = mail._charsets(self.ui)
self.subs = self.subscribers()
+ self.merge = self.ui.configbool('notify', 'merge', True)
mapfile = self.ui.config('notify', 'style')
template = (self.ui.config('notify', hooktype) or
@@ -166,10 +168,13 @@
return self.ui.config('web', 'baseurl') + (path or self.root)
def node(self, ctx, **props):
- '''format one changeset.'''
+ '''format one changeset, unless it is a suppressed merge.'''
+ if not self.merge and len(ctx.parents()) > 1:
+ return False
self.t.show(ctx, changes=ctx.changeset(),
baseurl=self.ui.config('web', 'baseurl'),
root=self.repo.root, webroot=self.root, **props)
+ return True
def skipsource(self, source):
'''true if incoming changes from this source should be skipped.'''
@@ -283,16 +288,29 @@
return
ui.pushbuffer()
+ data = ''
+ count = 0
if hooktype == 'changegroup':
start, end = ctx.rev(), len(repo)
- count = end - start
for rev in xrange(start, end):
- n.node(repo[rev])
- n.diff(ctx, repo['tip'])
+ if n.node(repo[rev]):
+ count += 1
+ else:
+ data += ui.popbuffer()
+ ui.note(_('notify: suppressing notification for merge %d:%s\n') %
+ (rev, repo[rev].hex()[:12]))
+ ui.pushbuffer()
+ if count:
+ n.diff(ctx, repo['tip'])
else:
- count = 1
- n.node(ctx)
+ if not n.node(ctx):
+ ui.popbuffer()
+ ui.note(_('notify: suppressing notification for merge %d:%s\n') %
+ (ctx.rev(), ctx.hex()[:12]))
+ return
+ count += 1
n.diff(ctx)
- data = ui.popbuffer()
- n.send(ctx, count, data)
+ data += ui.popbuffer()
+ if count:
+ n.send(ctx, count, data)
--- a/i18n/da.po Sat Oct 03 23:36:08 2009 +0200
+++ b/i18n/da.po Sat Oct 03 23:38:10 2009 +0200
@@ -17,8 +17,8 @@
msgstr ""
"Project-Id-Version: Mercurial\n"
"Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2009-07-20 23:05+0200\n"
-"PO-Revision-Date: 2009-07-21 00:18+0200\n"
+"POT-Creation-Date: 2009-09-29 00:26+0200\n"
+"PO-Revision-Date: 2009-09-29 00:41+0200\n"
"Last-Translator: <mg@lazybytes.net>\n"
"Language-Team: Danish\n"
"MIME-Version: 1.0\n"
@@ -1007,7 +1007,8 @@
#, python-format
msgid ""
"unexpected response from CVS server (expected \"Valid-requests\", but got %r)"
-msgstr "uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)"
+msgstr ""
+"uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)"
#, python-format
msgid "%d bytes missing from remote file"
@@ -1086,6 +1087,10 @@
msgid "%d changeset entries\n"
msgstr "%d ændringer\n"
+#, python-format
+msgid "darcs version 2.1 or newer needed (found %r)"
+msgstr ""
+
msgid "Python ElementTree module is not available"
msgstr "Python ElementTree modulet er ikke tilstede"
@@ -1492,10 +1497,6 @@
msgstr "sammenføjer med %d:%s\n"
#, python-format
-msgid "Automated merge with %s"
-msgstr "Automatisk sammenføjning med %s"
-
-#, python-format
msgid "new changeset %d:%s merges remote changes with local\n"
msgstr "ny ændring %d:%s fletter fjernændringer sammen med lokale\n"
@@ -1576,10 +1577,6 @@
"arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller "
"brug --force)"
-#, python-format
-msgid "Added signature for changeset %s"
-msgstr "Tilføjede underskrift af ændring %s"
-
msgid "unknown signature version"
msgstr "ukendt underskrift-version"
@@ -2133,7 +2130,9 @@
msgid ""
"\n"
"%s keywords written to %s:\n"
-msgstr "\n%s nøgleord skrevet til %s:\n"
+msgstr ""
+"\n"
+"%s nøgleord skrevet til %s:\n"
msgid "unhooked all commit hooks\n"
msgstr ""
@@ -3789,22 +3788,22 @@
msgstr ""
msgid "cannot use both abort and continue"
-msgstr ""
+msgstr "abort og continue kan ikke angives samtidig"
msgid "cannot use collapse with continue or abort"
-msgstr ""
+msgstr "continue eller abort kan ikke angives samtidig med collapse"
msgid "abort and continue do not allow specifying revisions"
-msgstr ""
+msgstr "abort og continue tillader ikke at der angives revisioner"
msgid "cannot specify both a revision and a base"
-msgstr ""
+msgstr "man kan ikke angive både en revision og en basis"
msgid "nothing to rebase\n"
msgstr ""
msgid "cannot use both keepbranches and extrafn"
-msgstr ""
+msgstr "man kan ikke bruge både keepbranches og extrafn"
msgid "rebase merging completed\n"
msgstr ""
@@ -3817,7 +3816,7 @@
#, python-format
msgid "%d revisions have been skipped\n"
-msgstr ""
+msgstr "sprang %d revisioner over\n"
msgid " set parents\n"
msgstr ""
@@ -4275,7 +4274,7 @@
msgstr ""
#, python-format
-msgid "[win32mbcs] filename conversion fail with %s encoding\n"
+msgid "[win32mbcs] filename conversion failed with %s encoding\n"
msgstr ""
msgid "[win32mbcs] cannot activate on this platform.\n"
@@ -4668,12 +4667,27 @@
" be expensive.\n"
" "
msgstr ""
+"tilføj alle nye filer, fjern alle manglende filer\n"
+"\n"
+" Tilføj alle nye filer og fjern alle manglende filer fra depotet.\n"
+"\n"
+" Nye filer bliver ignoreret hvis de matcher et af mønstrene i\n"
+" .hgignore. Som ved add, så træder disse ændringer først i kræft\n"
+" ved næste commit.\n"
+"\n"
+" Brug -s/--similarity tilvalget for at opdage omdøbte filer. Med en\n"
+" parameter større end 0 bliver hver fjernet fil sammenlignet med\n"
+" enhver tilføjet fil og filer der er tilstrækkelig ens bliver\n"
+" opført som omdøbte. Dette tilvalg tager et procenttal mellem 0\n"
+" (slået fra) og 100 (filer skal være identiske) som parameter. At\n"
+" opdage omdøbninger på denne måde kan være dyrt.\n"
+" "
msgid "similarity must be a number"
-msgstr ""
+msgstr "lighedsgrad skal være et tal"
msgid "similarity must be between 0 and 100"
-msgstr ""
+msgstr "lighedsgrad skal være mellem 0 og 100"
msgid ""
"show changeset information by line for each file\n"
@@ -4705,10 +4719,10 @@
" "
msgid "at least one filename or pattern is required"
-msgstr ""
+msgstr "kræver mindst et filnavn eller mønster"
msgid "at least one of -n/-c is required for -l"
-msgstr ""
+msgstr "brug af -l kræver mindst en af -n/-c"
#, python-format
msgid "%s: binary file\n"
@@ -4744,10 +4758,10 @@
msgstr "intet arbejdskatalog: angive venligst en revision"
msgid "repository root cannot be destination"
-msgstr ""
+msgstr "depotets rod kan ikke bruges som destination"
msgid "cannot archive plain files to stdout"
-msgstr ""
+msgstr "flade filer kan ikke arkiveres til standarduddata"
msgid ""
"reverse effect of earlier changeset\n"
@@ -4806,11 +4820,7 @@
msgstr "%s er ikke forælder til %s"
msgid "cannot use --parent on non-merge changeset"
-msgstr ""
-
-#, python-format
-msgid "Backed out changeset %s"
-msgstr ""
+msgstr "kan ikke bruge --parent på en ændringer som ikke er en sammenføjning"
#, python-format
msgid "changeset %s backs out changeset %s\n"
@@ -4824,7 +4834,7 @@
msgstr ""
msgid "(use \"backout --merge\" if you want to auto-merge)\n"
-msgstr ""
+msgstr "(brug \"backout --merge\" hvis du vil sammenføje automatisk)\n"
msgid ""
"subdivision search of changesets\n"
@@ -4872,7 +4882,7 @@
msgstr ""
msgid "(use of 'hg bisect <cmd>' is deprecated)\n"
-msgstr ""
+msgstr "(formen 'hg bisect <kommando>' er forældet)\n"
msgid "incompatible arguments"
msgstr "inkompatible argumenter"
@@ -4883,7 +4893,7 @@
#, python-format
msgid "failed to execute %s"
-msgstr ""
+msgstr "kunne ikke køre %s"
#, python-format
msgid "%s killed"
@@ -4917,10 +4927,27 @@
" 'hg commit --close-branch' to mark this branch as closed.\n"
" "
msgstr ""
+"angiv eller vis navnet på den aktuelle gren\n"
+"\n"
+" Uden noget argument vises navnet på den nuværende gren. Med et\n"
+" argument angives arbejdskatalogets grennavn (grenen eksisterer\n"
+" ikke i depotet før næste deponering). Det anbefales at den primære\n"
+" udvikling foretages på 'default' grenen.\n"
+"\n"
+" Med mindre -f/--force bruges, så vil branch ikke lade dig bruge et\n"
+" grennavn som allerede eksisterer, selv hvis det er inaktivt.\n"
+"\n"
+" Brug -C/--clean for at nulstille arbejdskatalogs gren til samme\n"
+" gren dets forældre-ændring og derved negere end tidligere ændring.\n"
+"\n"
+" Brug kommandoen 'hg update' for at skifte til en eksisterende\n"
+" gren. Brug 'hg commit --close-branch' for at markere denne gren\n"
+" som lukket.\n"
+" "
#, python-format
msgid "reset working directory to branch %s\n"
-msgstr ""
+msgstr "nulstil arbejdskataloget til gren %s\n"
msgid "a branch of the same name already exists (use --force to override)"
msgstr ""
@@ -5003,6 +5030,22 @@
" %p root-relative path name of file being printed\n"
" "
msgstr ""
+"udskriv den aktuelle eller en given revision af filer\n"
+"\n"
+" Udskriver de angivne filer som de så ud ved den givne revision.\n"
+" Hvis der ikke angves en revision, så bruges forældre-revisionen\n"
+" til arbejdskataloget, eller spidsen hvis der ikke er hentet noget\n"
+" arbejdskatalog.\n"
+"\n"
+" Output kan gemmes i en fil hvis navn angives med et formatstreng.\n"
+" Reglerne for formatteringen er de samme som for export-kommandoen\n"
+" med følgende tilføjelser:\n"
+"\n"
+" %s grundnavn for filen som udskrives\n"
+" %d katalognavn for filen som blvier udskrevet\n"
+" eller '.' hvis filen er i katalogets rod\n"
+" %p rod-relativ sti for filen som bliver udkrevet\n"
+" "
msgid ""
"make a copy of an existing repository\n"
@@ -5525,24 +5568,29 @@
"\n"
" With no arguments, show all repository head changesets.\n"
"\n"
-" Repository \"heads\" are changesets that don't have child\n"
-" changesets. They are where development generally takes place and\n"
-" are the usual targets for update and merge operations.\n"
+" Repository \"heads\" are changesets with no child changesets. They are\n"
+" where development generally takes place and are the usual targets\n"
+" for update and merge operations.\n"
"\n"
" If one or more REV is given, the \"branch heads\" will be shown for\n"
-" the named branch associated with that revision. The name of the\n"
-" branch is called the revision's branch tag.\n"
-"\n"
-" Branch heads are revisions on a given named branch that do not have\n"
-" any descendants on the same branch. A branch head could be a true head\n"
-" or it could be the last changeset on a branch before a new branch\n"
-" was created. If none of the branch heads are true heads, the branch\n"
-" is considered inactive. If -c/--closed is specified, also show branch\n"
-" heads marked closed (see hg commit --close-branch).\n"
-"\n"
-" If STARTREV is specified only those heads (or branch heads) that\n"
-" are descendants of STARTREV will be displayed.\n"
-" "
+" the named branch associated with the specified changeset(s).\n"
+"\n"
+" Branch heads are changesets on a named branch with no descendants on\n"
+" the same branch. A branch head could be a \"true\" (repository) head,\n"
+" or it could be the last changeset on that branch before it was\n"
+" merged into another branch, or it could be the last changeset on the\n"
+" branch before a new branch was created. If none of the branch heads\n"
+" are true heads, the branch is considered inactive.\n"
+"\n"
+" If -c/--closed is specified, also show branch heads marked closed\n"
+" (see hg commit --close-branch).\n"
+"\n"
+" If STARTREV is specified, only those heads that are descendants of\n"
+" STARTREV will be displayed.\n"
+" "
+msgstr ""
+
+msgid "you must specify a branch to use --closed"
msgstr ""
#, python-format
@@ -6403,17 +6451,9 @@
msgstr "mærkaten '%s' er ikke en lokal mærkat"
#, python-format
-msgid "Removed tag %s"
-msgstr "Mærke %s er fjernet"
-
-#, python-format
msgid "tag '%s' already exists (use -f to force)"
msgstr "mærkaten '%s' eksisterer allerede (brug -f for at gennemtvinge)"
-#, python-format
-msgid "Added tag %s for changeset %s"
-msgstr "Tilføjede mærkat %s til ændring %s"
-
msgid ""
"list repository tags\n"
"\n"
@@ -6511,6 +6551,9 @@
" Se 'hg help dates' for en liste af gyldige formater til -d/--date.\n"
" "
+msgid "cannot specify both -c/--check and -C/--clean"
+msgstr "man kan ikke angive både -c/--check og -C/--clean"
+
msgid "uncommitted local changes"
msgstr "udeponerede lokale ændringer"
@@ -6525,6 +6568,14 @@
" integrity of their crosslinks and indices.\n"
" "
msgstr ""
+"verificer depotets integritet\n"
+"\n"
+" Verificer integreteten af det aktuelle depot.\n"
+"\n"
+" Dette vil lave en udførlig kontrol af depotets integritet.\n"
+" Hashværdier og tjeksummer valideres for hver indgang i\n"
+" historikfilen, manifæstet og fulgte filer. Desuden valideres\n"
+" integriteten af deres krydslinks og indekser."
msgid "output version and copyright information"
msgstr "udskriv version- og copyrightinformation"
@@ -6539,6 +6590,11 @@
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
msgstr ""
+"\n"
+"Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> og andre\n"
+"Dette er frit programmel; se kildekoden for kopieringsbetingelser. Der\n"
+"gives INGEN GARANTI; ikke engang for SALGBARHED eller EGNETHED FOR\n"
+"NOGET BESTEMT FORMÅL.\n"
msgid "repository root directory or symbolic path name"
msgstr "depotrodfolder eller symbolsk stinavn"
@@ -6721,10 +6777,10 @@
msgstr "[-gbsr] [-c KOMMANDO] [REV]"
msgid "set branch name even if it shadows an existing branch"
-msgstr ""
+msgstr "sæt grennavnet selv hvis det overskygger en eksisterende gren"
msgid "reset branch name to parent branch name"
-msgstr ""
+msgstr "nulstil grennavnet til forældre-grennavnet"
msgid "[-fC] [NAME]"
msgstr "[-fC] [NAVN]"
@@ -6732,8 +6788,8 @@
msgid "show only branches that have unmerged heads"
msgstr "vil kun grene som har usammenføjne hoveder"
-msgid "show normal and closed heads"
-msgstr "vis normale og lukkede hoveder"
+msgid "show normal and closed branches"
+msgstr "vis normale og lukkede grene"
msgid "[-a]"
msgstr "[-a]"
@@ -6847,7 +6903,7 @@
msgstr "[TILVALG]... [-r REV1 [-r REV2]] [FIL]..."
msgid "diff against the second parent"
-msgstr ""
+msgstr "find forskelle i forhold til den anden forældre"
msgid "[OPTION]... [-o OUTFILESPEC] REV..."
msgstr "[TILVALG]... [-o UDFILSPECIFIKATION] REV..."
@@ -6879,8 +6935,11 @@
msgid "show only heads which are descendants of REV"
msgstr "vis kun hoveder som er efterkommere af REV"
-msgid "show only the active heads from open branches"
-msgstr "vis kun aktive hoveder fra åbne grene"
+msgid "show only the active branch heads from open branches"
+msgstr "vis kun de aktive grenhoveder fra åbne grene"
+
+msgid "show normal and closed branch heads"
+msgstr "vis normale og lukkede grenhoveder"
msgid "[-r STARTREV] [REV]..."
msgstr "[-r STARTREV] [REV]..."
@@ -7766,22 +7825,21 @@
" Mercurial supports several ways to specify individual revisions.\n"
"\n"
" A plain integer is treated as a revision number. Negative integers\n"
-" are treated as topological offsets from the tip, with -1 denoting\n"
-" the tip. As such, negative numbers are only useful if you've\n"
-" memorized your local tree numbers and want to save typing a single\n"
-" digit. This editor suggests copy and paste.\n"
+" are treated as sequential offsets from the tip, with -1 denoting\n"
+" the tip, -2 denoting the revision prior to the tip, and so forth.\n"
"\n"
" A 40-digit hexadecimal string is treated as a unique revision\n"
" identifier.\n"
"\n"
" A hexadecimal string less than 40 characters long is treated as a\n"
-" unique revision identifier, and referred to as a short-form\n"
+" unique revision identifier and is referred to as a short-form\n"
" identifier. A short-form identifier is only valid if it is the\n"
" prefix of exactly one full-length identifier.\n"
"\n"
-" Any other string is treated as a tag name, which is a symbolic\n"
-" name associated with a revision identifier. Tag names may not\n"
-" contain the \":\" character.\n"
+" Any other string is treated as a tag or branch name. A tag name is\n"
+" a symbolic name associated with a revision identifier. A branch\n"
+" name denotes the tipmost revision of that branch. Tag and branch\n"
+" names must not contain the \":\" character.\n"
"\n"
" The reserved name \"tip\" is a special tag that always identifies\n"
" the most recent revision.\n"
@@ -7943,13 +8001,19 @@
" - nonempty: Any text. Returns '(none)' if the string is empty.\n"
" - hgdate: Date. Returns the date as a pair of numbers:\n"
" \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
-" - isodate: Date. Returns the date in ISO 8601 format.\n"
+" - isodate: Date. Returns the date in ISO 8601 format: \"2009-08-18\n"
+" 13:00 +0200\".\n"
+" - isodatesec: Date. Returns the date in ISO 8601 format, including\n"
+" seconds: \"2009-08-18 13:00:13 +0200\". See also the\n"
+" rfc3339date filter.\n"
" - localdate: Date. Converts a date to local date.\n"
" - obfuscate: Any text. Returns the input text rendered as a\n"
" sequence of XML entities.\n"
" - person: Any text. Returns the text before an email address.\n"
" - rfc822date: Date. Returns a date using the same format used\n"
-" in email headers.\n"
+" in email headers: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
+" - rfc3339date: Date. Returns a date using the Internet date format\n"
+" specified in RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
" - short: Changeset hash. Returns the short form of a changeset\n"
" hash, i.e. a 12-byte hexadecimal string.\n"
" - shortdate: Date. Returns a date like \"2006-09-18\".\n"
--- a/i18n/pt_BR.po Sat Oct 03 23:36:08 2009 +0200
+++ b/i18n/pt_BR.po Sat Oct 03 23:38:10 2009 +0200
@@ -9812,22 +9812,21 @@
" Mercurial supports several ways to specify individual revisions.\n"
"\n"
" A plain integer is treated as a revision number. Negative integers\n"
-" are treated as topological offsets from the tip, with -1 denoting\n"
-" the tip. As such, negative numbers are only useful if you've\n"
-" memorized your local tree numbers and want to save typing a single\n"
-" digit. This editor suggests copy and paste.\n"
+" are treated as sequential offsets from the tip, with -1 denoting\n"
+" the tip, -2 denoting the revision prior to the tip, and so forth.\n"
"\n"
" A 40-digit hexadecimal string is treated as a unique revision\n"
" identifier.\n"
"\n"
" A hexadecimal string less than 40 characters long is treated as a\n"
-" unique revision identifier, and referred to as a short-form\n"
+" unique revision identifier and is referred to as a short-form\n"
" identifier. A short-form identifier is only valid if it is the\n"
" prefix of exactly one full-length identifier.\n"
"\n"
-" Any other string is treated as a tag name, which is a symbolic\n"
-" name associated with a revision identifier. Tag names may not\n"
-" contain the \":\" character.\n"
+" Any other string is treated as a tag or branch name. A tag name is\n"
+" a symbolic name associated with a revision identifier. A branch\n"
+" name denotes the tipmost revision of that branch. Tag and branch\n"
+" names must not contain the \":\" character.\n"
"\n"
" The reserved name \"tip\" is a special tag that always identifies\n"
" the most recent revision.\n"
@@ -9846,23 +9845,22 @@
" individuais.\n"
"\n"
" Um simples inteiro é tratado como um número de revisão. Inteiros\n"
-" negativos são tratados como contados topologicamente a partir da\n"
-" tip, com -1 denotando a tip. Assim, números negativos são úteis\n"
-" apenas se você memorizou os números de sua árvore local e quiser\n"
-" evitar digitar um único caractere. Este editor sugere copiar e\n"
-" colar.\n"
+" negativos são contados a partir da tip, com -1 denotando a tip,\n"
+" -2 denotando a revisão anterior à tip, e assim por diante.\n"
"\n"
" Uma string hexadecimal de 40 dígitos é tratada como um\n"
" identificador único de revisão.\n"
"\n"
" Uma string hexadecimal de menos de 40 caracteres é tratada como\n"
-" um identificador único de revisão, e referida como um\n"
-" identificador curto. Um identificador curto é válido apenas se\n"
-" for o prefixo de um identificador completo.\n"
-"\n"
-" Qualquer outra string é tratada como um nome de etiqueta, que é\n"
-" um nome simbólico associado a um identificador de revisão. Nomes\n"
-" de etiqueta não podem conter o caractere \":\".\n"
+" um identificador único de revisão, chamado de identificador\n"
+" curto. Um identificador curto é válido apenas se for o prefixo\n"
+" de um identificador completo.\n"
+"\n"
+" Qualquer outra string é tratada como um nome de etiqueta ou\n"
+" ramo. Um nome de etiqueta é um nome simbólico associado a um\n"
+" identificador de revisão. Um nome de ramo denota a revisão mais\n"
+" recente de tal ramo. Nomes de etiqueta ou de ramo não podem\n"
+" conter o caractere \":\".\n"
"\n"
" O nome reservado \"tip\" é uma etiqueta especial que sempre\n"
" identifica a revisão mais recente.\n"
@@ -10076,13 +10074,19 @@
" - nonempty: Any text. Returns '(none)' if the string is empty.\n"
" - hgdate: Date. Returns the date as a pair of numbers:\n"
" \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
-" - isodate: Date. Returns the date in ISO 8601 format.\n"
+" - isodate: Date. Returns the date in ISO 8601 format: \"2009-08-18\n"
+" 13:00 +0200\".\n"
+" - isodatesec: Date. Returns the date in ISO 8601 format, including\n"
+" seconds: \"2009-08-18 13:00:13 +0200\". See also the\n"
+" rfc3339date filter.\n"
" - localdate: Date. Converts a date to local date.\n"
" - obfuscate: Any text. Returns the input text rendered as a\n"
" sequence of XML entities.\n"
" - person: Any text. Returns the text before an email address.\n"
" - rfc822date: Date. Returns a date using the same format used\n"
-" in email headers.\n"
+" in email headers: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
+" - rfc3339date: Date. Returns a date using the Internet date format\n"
+" specified in RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
" - short: Changeset hash. Returns the short form of a changeset\n"
" hash, i.e. a 12-byte hexadecimal string.\n"
" - shortdate: Date. Returns a date like \"2006-09-18\".\n"
@@ -10186,14 +10190,17 @@
" - nonempty: Qualquer texto. Devolve (none) se o texto for vazio.\n"
" - hgdate: Data. Devolve a data como um par de números:\n"
" \"1157407993 25200\" (timestamp Unix, defasagem de fuso)\n"
-" - isodate: Data. Devolve a data em formato ISO 8601.\n"
+" - isodate: Data. Devolve a data em formato ISO 8601: \"2009-08-18\n"
+" 13:00 +0200\".\n"
" - localdate: Data. Converte para data local.\n"
" - obfuscate: Qualquer texto. Devolve o texto de entrada\n"
" renderizado como uma seqüência de entidades XML.\n"
" - person: Qualquer texto. Devolve o texto antes de um endereço\n"
" de e-mail.\n"
-" - rfc822date: Data. Devolve uma data usando o mesmo formato\n"
-" utilizado em cabeçalhos de e-mail.\n"
+" - rfc822date: Data. Devolve uma data usando o mesmo formato utilizado\n"
+" em cabeçalhos de e-mail: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
+" - rfc3339date: Data. Devolve uma data usando o formato de data da\n"
+" Internet especificado na RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
" - short: Hash do changeset. Devolve a forma curta do hash de\n"
" um changeset, ou seja, uma string hexadecimal de 12 bytes.\n"
" - shortdate: Data. Devolve uma data como \"2006-09-18\".\n"
--- a/mercurial/cmdutil.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/cmdutil.py Sat Oct 03 23:38:10 2009 +0200
@@ -546,24 +546,26 @@
return errors
-def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None):
+def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
+ runargs=None):
'''Run a command as a service.'''
if opts['daemon'] and not opts['daemon_pipefds']:
rfd, wfd = os.pipe()
- args = sys.argv[:]
- args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
+ if not runargs:
+ runargs = sys.argv[:]
+ runargs.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
# Don't pass --cwd to the child process, because we've already
# changed directory.
- for i in xrange(1,len(args)):
- if args[i].startswith('--cwd='):
- del args[i]
+ for i in xrange(1,len(runargs)):
+ if runargs[i].startswith('--cwd='):
+ del runargs[i]
break
- elif args[i].startswith('--cwd'):
- del args[i:i+2]
+ elif runargs[i].startswith('--cwd'):
+ del runargs[i:i+2]
break
pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
- args[0], args)
+ runargs[0], runargs)
os.close(wfd)
os.read(rfd, 1)
if parentfn:
--- a/mercurial/commands.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/commands.py Sat Oct 03 23:38:10 2009 +0200
@@ -1356,23 +1356,25 @@
With no arguments, show all repository head changesets.
- Repository "heads" are changesets that don't have child
- changesets. They are where development generally takes place and
- are the usual targets for update and merge operations.
+ Repository "heads" are changesets with no child changesets. They are
+ where development generally takes place and are the usual targets
+ for update and merge operations.
If one or more REV is given, the "branch heads" will be shown for
- the named branch associated with that revision. The name of the
- branch is called the revision's branch tag.
-
- Branch heads are revisions on a given named branch that do not have
- any descendants on the same branch. A branch head could be a true head
- or it could be the last changeset on a branch before a new branch
- was created. If none of the branch heads are true heads, the branch
- is considered inactive. If -c/--closed is specified, also show branch
- heads marked closed (see hg commit --close-branch).
-
- If STARTREV is specified only those heads (or branch heads) that
- are descendants of STARTREV will be displayed.
+ the named branch associated with the specified changeset(s).
+
+ Branch heads are changesets on a named branch with no descendants on
+ the same branch. A branch head could be a "true" (repository) head,
+ or it could be the last changeset on that branch before it was
+ merged into another branch, or it could be the last changeset on the
+ branch before a new branch was created. If none of the branch heads
+ are true heads, the branch is considered inactive.
+
+ If -c/--closed is specified, also show branch heads marked closed
+ (see hg commit --close-branch).
+
+ If STARTREV is specified, only those heads that are descendants of
+ STARTREV will be displayed.
"""
if opts.get('rev'):
start = repo.lookup(opts['rev'])
--- a/mercurial/dirstate.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/dirstate.py Sat Oct 03 23:38:10 2009 +0200
@@ -38,6 +38,9 @@
class dirstate(object):
def __init__(self, opener, ui, root):
+ '''Create a new dirstate object. opener is an open()-like callable
+ that can be used to open the dirstate file; root is the root of the
+ directory tracked by the dirstate.'''
self._opener = opener
self._root = root
self._rootdir = os.path.join(root, '')
@@ -47,6 +50,8 @@
@propertycache
def _map(self):
+ '''Return the dirstate contents as a map from filename to
+ (state, mode, size, time).'''
self._read()
return self._map
@@ -169,12 +174,14 @@
return path
def __getitem__(self, key):
- ''' current states:
- n normal
- m needs merging
- r marked for removal
- a marked for addition
- ? not tracked'''
+ '''Return the current state of key (a filename) in the dirstate.
+ States are:
+ n normal
+ m needs merging
+ r marked for removal
+ a marked for addition
+ ? not tracked
+ '''
return self._map.get(key, ("?",))[0]
def __contains__(self, key):
@@ -373,13 +380,9 @@
return
st = self._opener("dirstate", "w", atomictemp=True)
- try:
- gran = int(self._ui.config('dirstate', 'granularity', 1))
- except ValueError:
- gran = 1
- if gran > 0:
- hlimit = util.fstat(st).st_mtime
- llimit = hlimit - gran
+ # use the modification time of the newly created temporary file as the
+ # filesystem's notion of 'now'
+ now = int(util.fstat(st).st_mtime)
cs = cStringIO.StringIO()
copymap = self._copymap
@@ -389,9 +392,19 @@
for f, e in self._map.iteritems():
if f in copymap:
f = "%s\0%s" % (f, copymap[f])
- if gran > 0 and e[0] == 'n' and llimit < e[3] <= hlimit:
- # file was updated too recently, ignore stat data
- e = (e[0], 0, -1, -1)
+
+ if e[0] == 'n' and e[3] == now:
+ # The file was last modified "simultaneously" with the current
+ # write to dirstate (i.e. within the same second for file-
+ # systems with a granularity of 1 sec). This commonly happens
+ # for at least a couple of files on 'update'.
+ # The user could change the file without changing its size
+ # within the same second. Invalidate the file's stat data in
+ # dirstate, forcing future 'status' calls to compare the
+ # contents of the file. This prevents mistakenly treating such
+ # files as clean.
+ e = (e[0], 0, -1, -1) # mark entry as 'unset'
+
e = pack(_format, e[0], e[1], e[2], e[3], len(f))
write(e)
write(f)
@@ -411,11 +424,11 @@
def walk(self, match, unknown, ignored):
'''
- walk recursively through the directory tree, finding all files
- matched by the match function
+ Walk recursively through the directory tree, finding all files
+ matched by match.
- results are yielded in a tuple (filename, stat), where stat
- and st is the stat result if the file was found in the directory.
+ Return a dict mapping filename to stat-like object (either
+ mercurial.osutil.stat instance or return value of os.stat()).
'''
def fwarn(f, msg):
@@ -553,12 +566,38 @@
return results
def status(self, match, ignored, clean, unknown):
+ '''Determine the status of the working copy relative to the
+ dirstate and return a tuple of lists (unsure, modified, added,
+ removed, deleted, unknown, ignored, clean), where:
+
+ unsure:
+ files that might have been modified since the dirstate was
+ written, but need to be read to be sure (size is the same
+ but mtime differs)
+ modified:
+ files that have definitely been modified since the dirstate
+ was written (different size or mode)
+ added:
+ files that have been explicitly added with hg add
+ removed:
+ files that have been explicitly removed with hg remove
+ deleted:
+ files that have been deleted through other means ("missing")
+ unknown:
+ files not in the dirstate that are not ignored
+ ignored:
+ files not in the dirstate that are ignored
+ (by _dirignore())
+ clean:
+ files that have definitely not been modified since the
+ dirstate was written
+ '''
listignored, listclean, listunknown = ignored, clean, unknown
lookup, modified, added, unknown, ignored = [], [], [], [], []
removed, deleted, clean = [], [], []
dmap = self._map
- ladd = lookup.append
+ ladd = lookup.append # aka "unsure"
madd = modified.append
aadd = added.append
uadd = unknown.append
--- a/mercurial/posix.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/posix.py Sat Oct 03 23:38:10 2009 +0200
@@ -165,17 +165,11 @@
return inst.errno != errno.ESRCH
def explain_exit(code):
- """return a 2-tuple (desc, code) describing a process's status"""
- if os.WIFEXITED(code):
- val = os.WEXITSTATUS(code)
- return _("exited with status %d") % val, val
- elif os.WIFSIGNALED(code):
- val = os.WTERMSIG(code)
- return _("killed by signal %d") % val, val
- elif os.WIFSTOPPED(code):
- val = os.WSTOPSIG(code)
- return _("stopped by signal %d") % val, val
- raise ValueError(_("invalid exit code"))
+ """return a 2-tuple (desc, code) describing a subprocess status
+ (codes from kill are negative - not os.system/wait encoding)"""
+ if code >= 0:
+ return _("exited with status %d") % code, code
+ return _("killed by signal %d") % -code, -code
def isowner(st):
"""Return True if the stat object st is from the current user."""
--- a/mercurial/streamclone.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/streamclone.py Sat Oct 03 23:38:10 2009 +0200
@@ -48,8 +48,7 @@
try:
repo.ui.debug('scanning\n')
for name, ename, size in repo.store.walk():
- # for backwards compat, name was partially encoded
- entries.append((store.encodedir(name), size))
+ entries.append((name, size))
total_bytes += size
finally:
lock.release()
@@ -62,6 +61,7 @@
yield '%d %d\n' % (len(entries), total_bytes)
for name, size in entries:
repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
- yield '%s\0%d\n' % (name, size)
+ # partially encode name over the wire for backwards compat
+ yield '%s\0%d\n' % (store.encodedir(name), size)
for chunk in util.filechunkiter(repo.sopener(name), limit=size):
yield chunk
--- a/mercurial/subrepo.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/subrepo.py Sat Oct 03 23:38:10 2009 +0200
@@ -167,7 +167,7 @@
self._repo.ui.note(_('removing subrepo %s\n') % self._path)
hg.clean(self._repo, node.nullid, False)
- def get(self, state):
+ def _get(self, state):
source, revision = state
try:
self._repo.lookup(revision)
@@ -178,9 +178,13 @@
other = hg.repository(self._repo.ui, srcurl)
self._repo.pull(other)
+ def get(self, state):
+ self._get(state)
+ source, revision = state
hg.clean(self._repo, revision, False)
def merge(self, state):
+ self._get(state)
hg.merge(self._repo, state[1], remind=False)
def push(self, force):
--- a/mercurial/util.py Sat Oct 03 23:36:08 2009 +0200
+++ b/mercurial/util.py Sat Oct 03 23:38:10 2009 +0200
@@ -357,41 +357,26 @@
if val is True:
return '1'
return str(val)
- oldenv = {}
- for k in environ:
- oldenv[k] = os.environ.get(k)
- if cwd is not None:
- oldcwd = os.getcwd()
origcmd = cmd
if os.name == 'nt':
cmd = '"%s"' % cmd
- try:
- for k, v in environ.iteritems():
- os.environ[k] = py2shell(v)
- os.environ['HG'] = hgexecutable()
- if cwd is not None and oldcwd != cwd:
- os.chdir(cwd)
- rc = os.system(cmd)
- if sys.platform == 'OpenVMS' and rc & 1:
- rc = 0
- if rc and onerr:
- errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
- explain_exit(rc)[0])
- if errprefix:
- errmsg = '%s: %s' % (errprefix, errmsg)
- try:
- onerr.warn(errmsg + '\n')
- except AttributeError:
- raise onerr(errmsg)
- return rc
- finally:
- for k, v in oldenv.iteritems():
- if v is None:
- del os.environ[k]
- else:
- os.environ[k] = v
- if cwd is not None and oldcwd != cwd:
- os.chdir(oldcwd)
+ env = dict(os.environ)
+ env.update((k, py2shell(v)) for k, v in environ.iteritems())
+ env['HG'] = hgexecutable()
+ rc = subprocess.call(cmd, shell=True, close_fds=closefds,
+ env=env, cwd=cwd)
+ if sys.platform == 'OpenVMS' and rc & 1:
+ rc = 0
+ if rc and onerr:
+ errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
+ explain_exit(rc)[0])
+ if errprefix:
+ errmsg = '%s: %s' % (errprefix, errmsg)
+ try:
+ onerr.warn(errmsg + '\n')
+ except AttributeError:
+ raise onerr(errmsg)
+ return rc
def checksignature(func):
'''wrap a function with code to check for calling errors'''
@@ -1280,9 +1265,12 @@
padding = '\n' + ' ' * hangindent
# To avoid corrupting multi-byte characters in line, we must wrap
# a Unicode string instead of a bytestring.
- u = line.decode(encoding.encoding)
- w = padding.join(textwrap.wrap(u, width=width - hangindent))
- return w.encode(encoding.encoding)
+ try:
+ u = line.decode(encoding.encoding)
+ w = padding.join(textwrap.wrap(u, width=width - hangindent))
+ return w.encode(encoding.encoding)
+ except UnicodeDecodeError:
+ return padding.join(textwrap.wrap(line, width=width - hangindent))
def iterlines(iterator):
for chunk in iterator:
--- a/tests/test-http Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-http Sat Oct 03 23:38:10 2009 +0200
@@ -5,6 +5,11 @@
hg init test
cd test
echo foo>foo
+mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
+echo foo>foo.d/foo
+echo bar>foo.d/bAr.hg.d/BaR
+echo bar>foo.d/baR.d.hg/bAR
+
hg commit -A -m 1
hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=../hg1.pid
hg serve -p $HGPORT1 -d --pid-file=../hg2.pid
--- a/tests/test-http.out Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-http.out Sat Oct 03 23:38:10 2009 +0200
@@ -1,4 +1,7 @@
adding foo
+adding foo.d/bAr.hg.d/BaR
+adding foo.d/baR.d.hg/bAR
+adding foo.d/foo
abort: cannot start server at ':20060':
% clone via stream
streaming all changes
@@ -10,31 +13,31 @@
checking manifests
crosschecking files in changesets and manifests
checking files
-1 files, 1 changesets, 1 total revisions
+4 files, 1 changesets, 4 total revisions
% try to clone via stream, should use pull instead
requesting all changes
adding changesets
adding manifests
adding file changes
-added 1 changesets with 1 changes to 1 files
+added 1 changesets with 4 changes to 4 files
updating working directory
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+4 files updated, 0 files merged, 0 files removed, 0 files unresolved
% clone via pull
requesting all changes
adding changesets
adding manifests
adding file changes
-added 1 changesets with 1 changes to 1 files
+added 1 changesets with 4 changes to 4 files
updating working directory
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+4 files updated, 0 files merged, 0 files removed, 0 files unresolved
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
-1 files, 1 changesets, 1 total revisions
+4 files, 1 changesets, 4 total revisions
adding bar
% pull
-changegroup hook: HG_NODE=cfbd11a1fa315300a080c3de8fe36b0fc5820acf HG_SOURCE=pull HG_URL=http://localhost/
+changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=http://localhost/
pulling from http://localhost/
searching for changes
adding changesets
--- a/tests/test-inotify-issue1208.out Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-inotify-issue1208.out Sat Oct 03 23:38:10 2009 +0200
@@ -1,5 +1,5 @@
% fail
-could not talk to new inotify server: No such file or directory
+abort: could not start server: File exists
abort: could not start server: File exists
% inserve
% status
--- a/tests/test-keyword Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-keyword Sat Oct 03 23:38:10 2009 +0200
@@ -48,6 +48,11 @@
echo % cat
cat a b
+echo % no kwfiles
+hg kwfiles
+echo % untracked candidates
+hg -v kwfiles --unknown
+
echo % addremove
hg addremove
echo % status
@@ -162,6 +167,10 @@
echo % kwfiles
hg kwfiles
+echo % ignored files
+hg -v kwfiles --ignore
+echo % all files
+hg kwfiles --all
echo % diff --rev
hg diff --rev 1 | grep -v 'b/c'
--- a/tests/test-keyword.out Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-keyword.out Sat Oct 03 23:38:10 2009 +0200
@@ -42,6 +42,9 @@
do not process $Id:
xxx $
ignore $Id$
+% no kwfiles
+% untracked candidates
+k a
% addremove
adding a
adding b
@@ -181,6 +184,14 @@
% kwfiles
a
c
+% ignored files
+I b
+I sym
+% all files
+K a
+K c
+I b
+I sym
% diff --rev
diff -r ef63ca68695b c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
--- a/tests/test-notify.out Sat Oct 03 23:36:08 2009 +0200
+++ b/tests/test-notify.out Sat Oct 03 23:38:10 2009 +0200
@@ -35,6 +35,7 @@
diffstat = True # add a diffstat before the diff content
sources = serve # notify if source of incoming changes in this list
# (serve == ssh or http, push, pull, bundle)
+ merge = False # send notification for merges (default True)
[email]
from = user@host.com # email address to send as if none given
[web]