--- a/hgext/bugzilla.py Thu Nov 09 14:44:17 2006 -0800
+++ b/hgext/bugzilla.py Mon Nov 13 21:50:09 2006 +0100
@@ -55,7 +55,7 @@
from mercurial.demandload import *
from mercurial.i18n import gettext as _
from mercurial.node import *
-demandload(globals(), 'mercurial:templater,util os re time')
+demandload(globals(), 'mercurial:cmdutil,templater,util os re time')
MySQLdb = None
@@ -267,8 +267,8 @@
mapfile = self.ui.config('bugzilla', 'style')
tmpl = self.ui.config('bugzilla', 'template')
- sio = templater.stringio()
- t = templater.changeset_templater(self.ui, self.repo, mapfile, sio)
+ sio = cmdutil.stringio()
+ t = cmdutil.changeset_templater(self.ui, self.repo, mapfile, sio)
if not mapfile and not tmpl:
tmpl = _('changeset {node|short} in repo {root} refers '
'to bug {bug}.\ndetails:\n\t{desc|tabindent}')
--- a/hgext/hbisect.py Thu Nov 09 14:44:17 2006 -0800
+++ b/hgext/hbisect.py Mon Nov 13 21:50:09 2006 +0100
@@ -8,7 +8,7 @@
from mercurial.i18n import gettext as _
from mercurial.demandload import demandload
-demandload(globals(), "os sys sets mercurial:hg,util,commands")
+demandload(globals(), "os sys sets mercurial:hg,util,commands,cmdutil")
versionstr = "0.0.3"
@@ -169,7 +169,7 @@
if ancestors.pop() != self.badrev:
raise util.Abort(_("Could not find the first bad revision"))
self.ui.write(_("The first bad revision is:\n"))
- displayer = commands.show_changeset(self.ui, self.repo, {})
+ displayer = cmdutil.show_changeset(self.ui, self.repo, {})
displayer.show(changenode=self.badrev)
return None
best_rev = None
--- a/hgext/notify.py Thu Nov 09 14:44:17 2006 -0800
+++ b/hgext/notify.py Mon Nov 13 21:50:09 2006 +0100
@@ -68,7 +68,7 @@
from mercurial.demandload import *
from mercurial.i18n import gettext as _
from mercurial.node import *
-demandload(globals(), 'mercurial:commands,patch,templater,util,mail')
+demandload(globals(), 'mercurial:commands,patch,cmdutil,templater,util,mail')
demandload(globals(), 'email.Parser fnmatch socket time')
# template for single changeset can include email headers.
@@ -107,13 +107,13 @@
self.stripcount = int(self.ui.config('notify', 'strip', 0))
self.root = self.strip(self.repo.root)
self.domain = self.ui.config('notify', 'domain')
- self.sio = templater.stringio()
+ self.sio = cmdutil.stringio()
self.subs = self.subscribers()
mapfile = self.ui.config('notify', 'style')
template = (self.ui.config('notify', hooktype) or
self.ui.config('notify', 'template'))
- self.t = templater.changeset_templater(self.ui, self.repo, mapfile,
+ self.t = cmdutil.changeset_templater(self.ui, self.repo, mapfile,
self.sio)
if not mapfile and not template:
template = deftemplates.get(hooktype) or single_template
@@ -237,7 +237,7 @@
maxdiff = int(self.ui.config('notify', 'maxdiff', 300))
if maxdiff == 0:
return
- fp = templater.stringio()
+ fp = cmdutil.stringio()
prev = self.repo.changelog.parents(node)[0]
patch.diff(self.repo, prev, ref, fp=fp)
difflines = fp.getvalue().splitlines(1)
--- a/mercurial/cmdutil.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/cmdutil.py Mon Nov 13 21:50:09 2006 +0100
@@ -8,8 +8,8 @@
from demandload import demandload
from node import *
from i18n import gettext as _
-demandload(globals(), 'mdiff util')
demandload(globals(), 'os sys')
+demandload(globals(), 'mdiff util templater cStringIO patch')
revrangesep = ':'
@@ -195,3 +195,391 @@
(oldrel, newrel, score * 100))
if not dry_run:
repo.copy(old, new, wlock=wlock)
+
+class uibuffer(object):
+ # Implement and delegate some ui protocol. Save hunks of
+ # output for later display in the desired order.
+ def __init__(self, ui):
+ self.ui = ui
+ self.hunk = {}
+ self.header = {}
+ self.quiet = ui.quiet
+ self.verbose = ui.verbose
+ self.debugflag = ui.debugflag
+ self.lastheader = None
+ def note(self, *args):
+ if self.verbose:
+ self.write(*args)
+ def status(self, *args):
+ if not self.quiet:
+ self.write(*args)
+ def debug(self, *args):
+ if self.debugflag:
+ self.write(*args)
+ def write(self, *args):
+ self.hunk.setdefault(self.rev, []).extend(args)
+ def write_header(self, *args):
+ self.header.setdefault(self.rev, []).extend(args)
+ def mark(self, rev):
+ self.rev = rev
+ def flush(self, rev):
+ if rev in self.header:
+ h = "".join(self.header[rev])
+ if h != self.lastheader:
+ self.lastheader = h
+ self.ui.write(h)
+ del self.header[rev]
+ if rev in self.hunk:
+ self.ui.write("".join(self.hunk[rev]))
+ del self.hunk[rev]
+ return 1
+ return 0
+
+class changeset_printer(object):
+ '''show changeset information when templating not requested.'''
+
+ def __init__(self, ui, repo, patch, buffered):
+ self.ui = ui
+ self.repo = repo
+ self.buffered = buffered
+ self.patch = patch
+ if buffered:
+ self.ui = uibuffer(ui)
+
+ def flush(self, rev):
+ return self.ui.flush(rev)
+
+ def show(self, rev=0, changenode=None, brinfo=None, copies=None):
+ '''show a single changeset or file revision'''
+ if self.buffered:
+ self.ui.mark(rev)
+ log = self.repo.changelog
+ if changenode is None:
+ changenode = log.node(rev)
+ elif not rev:
+ rev = log.rev(changenode)
+
+ if self.ui.quiet:
+ self.ui.write("%d:%s\n" % (rev, short(changenode)))
+ return
+
+ changes = log.read(changenode)
+ date = util.datestr(changes[2])
+ extra = changes[5]
+ branch = extra.get("branch")
+
+ hexfunc = self.ui.debugflag and hex or short
+
+ parents = log.parentrevs(rev)
+ if not self.ui.debugflag:
+ if parents[1] == nullrev:
+ if parents[0] >= rev - 1:
+ parents = []
+ else:
+ parents = [parents[0]]
+ parents = [(p, hexfunc(log.node(p))) for p in parents]
+
+ self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
+
+ if branch:
+ self.ui.write(_("branch: %s\n") % branch)
+ for tag in self.repo.nodetags(changenode):
+ self.ui.write(_("tag: %s\n") % tag)
+ for parent in parents:
+ self.ui.write(_("parent: %d:%s\n") % parent)
+
+ if brinfo and changenode in brinfo:
+ br = brinfo[changenode]
+ self.ui.write(_("branch: %s\n") % " ".join(br))
+
+ if self.ui.debugflag:
+ self.ui.write(_("manifest: %d:%s\n") %
+ (self.repo.manifest.rev(changes[0]), hex(changes[0])))
+ self.ui.write(_("user: %s\n") % changes[1])
+ self.ui.write(_("date: %s\n") % date)
+
+ if self.ui.debugflag:
+ files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
+ for key, value in zip([_("files:"), _("files+:"), _("files-:")],
+ files):
+ if value:
+ self.ui.write("%-12s %s\n" % (key, " ".join(value)))
+ elif changes[3] and self.ui.verbose:
+ self.ui.write(_("files: %s\n") % " ".join(changes[3]))
+ if copies and self.ui.verbose:
+ copies = ['%s (%s)' % c for c in copies]
+ self.ui.write(_("copies: %s\n") % ' '.join(copies))
+
+ if extra and self.ui.debugflag:
+ extraitems = extra.items()
+ extraitems.sort()
+ for key, value in extraitems:
+ self.ui.write(_("extra: %s=%s\n")
+ % (key, value.encode('string_escape')))
+
+ description = changes[4].strip()
+ if description:
+ if self.ui.verbose:
+ self.ui.write(_("description:\n"))
+ self.ui.write(description)
+ self.ui.write("\n\n")
+ else:
+ self.ui.write(_("summary: %s\n") %
+ description.splitlines()[0])
+ self.ui.write("\n")
+
+ self.showpatch(changenode)
+
+ def showpatch(self, node):
+ if self.patch:
+ prev = self.repo.changelog.parents(node)[0]
+ patch.diff(self.repo, prev, node, fp=self.ui)
+ self.ui.write("\n")
+
+class changeset_templater(changeset_printer):
+ '''format changeset information.'''
+
+ def __init__(self, ui, repo, patch, mapfile, buffered):
+ changeset_printer.__init__(self, ui, repo, patch, buffered)
+ self.t = templater.templater(mapfile, templater.common_filters,
+ cache={'parent': '{rev}:{node|short} ',
+ 'manifest': '{rev}:{node|short}',
+ 'filecopy': '{name} ({source})'})
+
+ def use_template(self, t):
+ '''set template string to use'''
+ self.t.cache['changeset'] = t
+
+ def show(self, rev=0, changenode=None, brinfo=None, copies=[], **props):
+ '''show a single changeset or file revision'''
+ if self.buffered:
+ self.ui.mark(rev)
+ log = self.repo.changelog
+ if changenode is None:
+ changenode = log.node(rev)
+ elif not rev:
+ rev = log.rev(changenode)
+
+ changes = log.read(changenode)
+
+ def showlist(name, values, plural=None, **args):
+ '''expand set of values.
+ name is name of key in template map.
+ values is list of strings or dicts.
+ plural is plural of name, if not simply name + 's'.
+
+ expansion works like this, given name 'foo'.
+
+ if values is empty, expand 'no_foos'.
+
+ if 'foo' not in template map, return values as a string,
+ joined by space.
+
+ expand 'start_foos'.
+
+ for each value, expand 'foo'. if 'last_foo' in template
+ map, expand it instead of 'foo' for last key.
+
+ expand 'end_foos'.
+ '''
+ if plural: names = plural
+ else: names = name + 's'
+ if not values:
+ noname = 'no_' + names
+ if noname in self.t:
+ yield self.t(noname, **args)
+ return
+ if name not in self.t:
+ if isinstance(values[0], str):
+ yield ' '.join(values)
+ else:
+ for v in values:
+ yield dict(v, **args)
+ return
+ startname = 'start_' + names
+ if startname in self.t:
+ yield self.t(startname, **args)
+ vargs = args.copy()
+ def one(v, tag=name):
+ try:
+ vargs.update(v)
+ except (AttributeError, ValueError):
+ try:
+ for a, b in v:
+ vargs[a] = b
+ except ValueError:
+ vargs[name] = v
+ return self.t(tag, **vargs)
+ lastname = 'last_' + name
+ if lastname in self.t:
+ last = values.pop()
+ else:
+ last = None
+ for v in values:
+ yield one(v)
+ if last is not None:
+ yield one(last, tag=lastname)
+ endname = 'end_' + names
+ if endname in self.t:
+ yield self.t(endname, **args)
+
+ def showbranches(**args):
+ branch = changes[5].get("branch")
+ if branch:
+ yield showlist('branch', [branch], plural='branches', **args)
+ # add old style branches if requested
+ if brinfo and changenode in brinfo:
+ yield showlist('branch', brinfo[changenode],
+ plural='branches', **args)
+
+ def showparents(**args):
+ parents = [[('rev', log.rev(p)), ('node', hex(p))]
+ for p in log.parents(changenode)
+ if self.ui.debugflag or p != nullid]
+ if (not self.ui.debugflag and len(parents) == 1 and
+ parents[0][0][1] == rev - 1):
+ return
+ return showlist('parent', parents, **args)
+
+ def showtags(**args):
+ return showlist('tag', self.repo.nodetags(changenode), **args)
+
+ def showextras(**args):
+ extras = changes[5].items()
+ extras.sort()
+ for key, value in extras:
+ args = args.copy()
+ args.update(dict(key=key, value=value))
+ yield self.t('extra', **args)
+
+ def showcopies(**args):
+ c = [{'name': x[0], 'source': x[1]} for x in copies]
+ return showlist('file_copy', c, plural='file_copies', **args)
+
+ if self.ui.debugflag:
+ files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
+ def showfiles(**args):
+ return showlist('file', files[0], **args)
+ def showadds(**args):
+ return showlist('file_add', files[1], **args)
+ def showdels(**args):
+ return showlist('file_del', files[2], **args)
+ def showmanifest(**args):
+ args = args.copy()
+ args.update(dict(rev=self.repo.manifest.rev(changes[0]),
+ node=hex(changes[0])))
+ return self.t('manifest', **args)
+ else:
+ def showfiles(**args):
+ yield showlist('file', changes[3], **args)
+ showadds = ''
+ showdels = ''
+ showmanifest = ''
+
+ defprops = {
+ 'author': changes[1],
+ 'branches': showbranches,
+ 'date': changes[2],
+ 'desc': changes[4],
+ 'file_adds': showadds,
+ 'file_dels': showdels,
+ 'files': showfiles,
+ 'file_copies': showcopies,
+ 'manifest': showmanifest,
+ 'node': hex(changenode),
+ 'parents': showparents,
+ 'rev': rev,
+ 'tags': showtags,
+ 'extras': showextras,
+ }
+ props = props.copy()
+ props.update(defprops)
+
+ try:
+ if self.ui.debugflag and 'header_debug' in self.t:
+ key = 'header_debug'
+ elif self.ui.quiet and 'header_quiet' in self.t:
+ key = 'header_quiet'
+ elif self.ui.verbose and 'header_verbose' in self.t:
+ key = 'header_verbose'
+ elif 'header' in self.t:
+ key = 'header'
+ else:
+ key = ''
+ if key:
+ h = templater.stringify(self.t(key, **props))
+ if self.buffered:
+ self.ui.write_header(h)
+ else:
+ self.ui.write(h)
+ if self.ui.debugflag and 'changeset_debug' in self.t:
+ key = 'changeset_debug'
+ elif self.ui.quiet and 'changeset_quiet' in self.t:
+ key = 'changeset_quiet'
+ elif self.ui.verbose and 'changeset_verbose' in self.t:
+ key = 'changeset_verbose'
+ else:
+ key = 'changeset'
+ self.ui.write(templater.stringify(self.t(key, **props)))
+ self.showpatch(changenode)
+ except KeyError, inst:
+ raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
+ inst.args[0]))
+ except SyntaxError, inst:
+ raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
+
+class stringio(object):
+ '''wrap cStringIO for use by changeset_templater.'''
+ def __init__(self):
+ self.fp = cStringIO.StringIO()
+
+ def write(self, *args):
+ for a in args:
+ self.fp.write(a)
+
+ write_header = write
+
+ def __getattr__(self, key):
+ return getattr(self.fp, key)
+
+def show_changeset(ui, repo, opts, buffered=False):
+ """show one changeset using template or regular display.
+
+ Display format will be the first non-empty hit of:
+ 1. option 'template'
+ 2. option 'style'
+ 3. [ui] setting 'logtemplate'
+ 4. [ui] setting 'style'
+ If all of these values are either the unset or the empty string,
+ regular display via changeset_printer() is done.
+ """
+ # options
+ patch = opts.get('patch')
+ tmpl = opts.get('template')
+ mapfile = None
+ if tmpl:
+ tmpl = templater.parsestring(tmpl, quoted=False)
+ else:
+ mapfile = opts.get('style')
+ # ui settings
+ if not mapfile:
+ tmpl = ui.config('ui', 'logtemplate')
+ if tmpl:
+ tmpl = templater.parsestring(tmpl)
+ else:
+ mapfile = ui.config('ui', 'style')
+
+ if tmpl or mapfile:
+ if mapfile:
+ if not os.path.split(mapfile)[0]:
+ mapname = (templater.templatepath('map-cmdline.' + mapfile)
+ or templater.templatepath(mapfile))
+ if mapname: mapfile = mapname
+ try:
+ t = changeset_templater(ui, repo, patch, mapfile, buffered)
+ except SyntaxError, inst:
+ raise util.Abort(inst.args[0])
+ if tmpl: t.use_template(tmpl)
+ return t
+ return changeset_printer(ui, repo, patch, buffered)
+
--- a/mercurial/commands.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/commands.py Mon Nov 13 21:50:09 2006 +0100
@@ -8,12 +8,11 @@
from demandload import demandload
from node import *
from i18n import gettext as _
-demandload(globals(), "os re sys signal shutil imp urllib pdb shlex")
-demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
-demandload(globals(), "fnmatch difflib patch random signal tempfile time")
-demandload(globals(), "traceback errno socket version struct atexit sets bz2")
-demandload(globals(), "archival cStringIO changegroup")
-demandload(globals(), "cmdutil hgweb.server sshserver")
+demandload(globals(), "os re sys signal imp urllib pdb shlex")
+demandload(globals(), "fancyopts ui hg util lock revlog bundlerepo")
+demandload(globals(), "difflib patch tempfile time")
+demandload(globals(), "traceback errno version atexit bz2")
+demandload(globals(), "archival changegroup cmdutil hgweb.server sshserver")
class UnknownCommand(Exception):
"""Exception raised if command is not in the command table."""
@@ -296,130 +295,6 @@
if cleanup is not None:
os.unlink(cleanup)
-class changeset_printer(object):
- '''show changeset information when templating not requested.'''
-
- def __init__(self, ui, repo):
- self.ui = ui
- self.repo = repo
-
- def show(self, rev=0, changenode=None, brinfo=None, copies=None):
- '''show a single changeset or file revision'''
- log = self.repo.changelog
- if changenode is None:
- changenode = log.node(rev)
- elif not rev:
- rev = log.rev(changenode)
-
- if self.ui.quiet:
- self.ui.write("%d:%s\n" % (rev, short(changenode)))
- return
-
- changes = log.read(changenode)
- date = util.datestr(changes[2])
- extra = changes[5]
- branch = extra.get("branch")
-
- hexfunc = self.ui.debugflag and hex or short
-
- parents = log.parentrevs(rev)
- if not self.ui.debugflag:
- if parents[1] == nullrev:
- if parents[0] >= rev - 1:
- parents = []
- else:
- parents = [parents[0]]
- parents = [(p, hexfunc(log.node(p))) for p in parents]
-
- self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)))
-
- if branch:
- self.ui.write(_("branch: %s\n") % branch)
- for tag in self.repo.nodetags(changenode):
- self.ui.write(_("tag: %s\n") % tag)
- for parent in parents:
- self.ui.write(_("parent: %d:%s\n") % parent)
-
- if brinfo and changenode in brinfo:
- br = brinfo[changenode]
- self.ui.write(_("branch: %s\n") % " ".join(br))
-
- if self.ui.debugflag:
- self.ui.write(_("manifest: %d:%s\n") %
- (self.repo.manifest.rev(changes[0]), hex(changes[0])))
- self.ui.write(_("user: %s\n") % changes[1])
- self.ui.write(_("date: %s\n") % date)
-
- if self.ui.debugflag:
- files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
- for key, value in zip([_("files:"), _("files+:"), _("files-:")],
- files):
- if value:
- self.ui.write("%-12s %s\n" % (key, " ".join(value)))
- elif changes[3] and self.ui.verbose:
- self.ui.write(_("files: %s\n") % " ".join(changes[3]))
- if copies and self.ui.verbose:
- copies = ['%s (%s)' % c for c in copies]
- self.ui.write(_("copies: %s\n") % ' '.join(copies))
-
- if extra and self.ui.debugflag:
- extraitems = extra.items()
- extraitems.sort()
- for key, value in extraitems:
- self.ui.write(_("extra: %s=%s\n")
- % (key, value.encode('string_escape')))
-
- description = changes[4].strip()
- if description:
- if self.ui.verbose:
- self.ui.write(_("description:\n"))
- self.ui.write(description)
- self.ui.write("\n\n")
- else:
- self.ui.write(_("summary: %s\n") %
- description.splitlines()[0])
- self.ui.write("\n")
-
-def show_changeset(ui, repo, opts):
- """show one changeset using template or regular display.
-
- Display format will be the first non-empty hit of:
- 1. option 'template'
- 2. option 'style'
- 3. [ui] setting 'logtemplate'
- 4. [ui] setting 'style'
- If all of these values are either the unset or the empty string,
- regular display via changeset_printer() is done.
- """
- # options
- tmpl = opts.get('template')
- mapfile = None
- if tmpl:
- tmpl = templater.parsestring(tmpl, quoted=False)
- else:
- mapfile = opts.get('style')
- # ui settings
- if not mapfile:
- tmpl = ui.config('ui', 'logtemplate')
- if tmpl:
- tmpl = templater.parsestring(tmpl)
- else:
- mapfile = ui.config('ui', 'style')
-
- if tmpl or mapfile:
- if mapfile:
- if not os.path.split(mapfile)[0]:
- mapname = (templater.templatepath('map-cmdline.' + mapfile)
- or templater.templatepath(mapfile))
- if mapname: mapfile = mapname
- try:
- t = templater.changeset_templater(ui, repo, mapfile)
- except SyntaxError, inst:
- raise util.Abort(inst.args[0])
- if tmpl: t.use_template(tmpl)
- return t
- return changeset_printer(ui, repo)
-
def setremoteconfig(ui, opts):
"copy remote options to ui tree"
if opts.get('ssh'):
@@ -828,24 +703,23 @@
# create the right base
# XXX: nodesbetween / changegroup* should be "fixed" instead
o = []
- has_set = sets.Set(base)
+ has = {nullid: None}
for n in base:
- has_set.update(repo.changelog.reachable(n))
+ has.update(repo.changelog.reachable(n))
if revs:
visit = list(revs)
else:
visit = repo.changelog.heads()
- seen = sets.Set(visit)
+ seen = {}
while visit:
n = visit.pop(0)
- parents = [p for p in repo.changelog.parents(n)
- if p != nullid and p not in has_set]
+ parents = [p for p in repo.changelog.parents(n) if p not in has]
if len(parents) == 0:
o.insert(0, n)
else:
for p in parents:
if p not in seen:
- seen.add(p)
+ seen[p] = 1
visit.append(p)
else:
setremoteconfig(ui, opts)
@@ -1005,14 +879,11 @@
repo.undelete([abstarget], wlock)
try:
if not opts.get('dry_run'):
- shutil.copyfile(relsrc, reltarget)
- shutil.copymode(relsrc, reltarget)
+ util.copyfile(relsrc, reltarget)
restore = False
finally:
if restore:
repo.remove([abstarget], wlock)
- except shutil.Error, inst:
- raise util.Abort(str(inst))
except IOError, inst:
if inst.errno == errno.ENOENT:
ui.warn(_('%s: deleted in working copy\n') % relsrc)
@@ -1568,7 +1439,7 @@
ui.warn(_("the --branches option is deprecated, "
"please use 'hg branches' instead\n"))
br = repo.branchlookup(heads)
- displayer = show_changeset(ui, repo, opts)
+ displayer = cmdutil.show_changeset(ui, repo, opts)
for n in heads:
displayer.show(changenode=n, brinfo=br)
@@ -1715,16 +1586,12 @@
o = other.changelog.nodesbetween(incoming, revs)[0]
if opts['newest_first']:
o.reverse()
- displayer = show_changeset(ui, other, opts)
+ displayer = cmdutil.show_changeset(ui, other, opts)
for n in o:
parents = [p for p in other.changelog.parents(n) if p != nullid]
if opts['no_merges'] and len(parents) == 2:
continue
displayer.show(changenode=n)
- if opts['patch']:
- prev = (parents and parents[0]) or nullid
- patch.diff(other, prev, n, fp=repo.ui)
- ui.write("\n")
finally:
if hasattr(other, 'close'):
other.close()
@@ -1801,35 +1668,6 @@
commit. When the -v/--verbose switch is used, the list of changed
files and full commit message is shown.
"""
- class dui(object):
- # Implement and delegate some ui protocol. Save hunks of
- # output for later display in the desired order.
- def __init__(self, ui):
- self.ui = ui
- self.hunk = {}
- self.header = {}
- self.quiet = ui.quiet
- self.verbose = ui.verbose
- self.debugflag = ui.debugflag
- def bump(self, rev):
- self.rev = rev
- self.hunk[rev] = []
- self.header[rev] = []
- def note(self, *args):
- if self.verbose:
- self.write(*args)
- def status(self, *args):
- if not self.quiet:
- self.write(*args)
- def write(self, *args):
- self.hunk[self.rev].extend(args)
- def write_header(self, *args):
- self.header[self.rev].extend(args)
- def debug(self, *args):
- if self.debugflag:
- self.write(*args)
- def __getattr__(self, key):
- return getattr(self.ui, key)
getchange = util.cachefunc(lambda r:repo.changectx(r).changeset())
changeiter, matchfn = walkchangerevs(ui, repo, pats, getchange, opts)
@@ -1884,13 +1722,9 @@
return ncache[fn].get(dcache[1][fn])
return None
- displayer = show_changeset(ui, repo, opts)
+ displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
for st, rev, fns in changeiter:
- if st == 'window':
- du = dui(ui)
- displayer.ui = du
- elif st == 'add':
- du.bump(rev)
+ if st == 'add':
changenode = repo.changelog.node(rev)
parents = [p for p in repo.changelog.parentrevs(rev)
if p != nullrev]
@@ -1923,21 +1757,10 @@
if rename:
copies.append((fn, rename[0]))
displayer.show(rev, changenode, brinfo=br, copies=copies)
- if opts['patch']:
- if parents:
- prev = parents[0]
- else:
- prev = nullrev
- prev = repo.changelog.node(prev)
- patch.diff(repo, prev, changenode, match=matchfn, fp=du)
- du.write("\n\n")
elif st == 'iter':
if count == limit: break
- if du.header[rev]:
- ui.write_header(*du.header[rev])
- if du.hunk[rev]:
+ if displayer.flush(rev):
count += 1
- ui.write(*du.hunk[rev])
def manifest(ui, repo, rev=None):
"""output the latest or given revision of the project manifest
@@ -2020,16 +1843,12 @@
o = repo.changelog.nodesbetween(o, revs)[0]
if opts['newest_first']:
o.reverse()
- displayer = show_changeset(ui, repo, opts)
+ displayer = cmdutil.show_changeset(ui, repo, opts)
for n in o:
parents = [p for p in repo.changelog.parents(n) if p != nullid]
if opts['no_merges'] and len(parents) == 2:
continue
displayer.show(changenode=n)
- if opts['patch']:
- prev = (parents and parents[0]) or nullid
- patch.diff(repo, prev, n)
- ui.write("\n")
def parents(ui, repo, file_=None, rev=None, branches=None, **opts):
"""show the parents of the working dir or revision
@@ -2061,7 +1880,7 @@
ui.warn(_("the --branches option is deprecated, "
"please use 'hg branches' instead\n"))
br = repo.branchlookup(p)
- displayer = show_changeset(ui, repo, opts)
+ displayer = cmdutil.show_changeset(ui, repo, opts)
for n in p:
if n != nullid:
displayer.show(changenode=n, brinfo=br)
@@ -2420,8 +2239,7 @@
ui.note(_('saving current version of %s as %s\n') %
(rel, bakname))
if not opts.get('dry_run'):
- shutil.copyfile(rel, bakname)
- shutil.copymode(rel, bakname)
+ util.copyfile(rel, bakname)
if ui.verbose or not exact:
ui.status(xlist[1] % rel)
for table, hitlist, misslist, backuphit, backupmiss in disptable:
@@ -2532,24 +2350,14 @@
os.read(rfd, 1)
os._exit(0)
- try:
- httpd = hgweb.server.create_server(ui, repo)
- except socket.error, inst:
- raise util.Abort(_('cannot start server: %s') % inst.args[1])
+ httpd = hgweb.server.create_server(ui, repo)
if ui.verbose:
- addr, port = httpd.socket.getsockname()
- if addr == '0.0.0.0':
- addr = socket.gethostname()
+ if httpd.port != 80:
+ ui.status(_('listening at http://%s:%d/\n') %
+ (httpd.addr, httpd.port))
else:
- try:
- addr = socket.gethostbyaddr(addr)[0]
- except socket.error:
- pass
- if port != 80:
- ui.status(_('listening at http://%s:%d/\n') % (addr, port))
- else:
- ui.status(_('listening at http://%s/\n') % addr)
+ ui.status(_('listening at http://%s/\n') % httpd.addr)
if opts['pid_file']:
fp = open(opts['pid_file'], 'w')
@@ -2699,9 +2507,7 @@
ui.warn(_("the --branches option is deprecated, "
"please use 'hg branches' instead\n"))
br = repo.branchlookup([n])
- show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
- if opts['patch']:
- patch.diff(repo, repo.changelog.parents(n)[0], n)
+ cmdutil.show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
def unbundle(ui, repo, fname, **opts):
"""apply a changegroup file
@@ -2768,7 +2574,8 @@
if len(found) > 1:
repo.ui.warn(_("Found multiple heads for %s\n") % branch)
for x in found:
- show_changeset(ui, repo, {}).show(changenode=x, brinfo=br)
+ cmdutil.show_changeset(ui, repo, {}).show(
+ changenode=x, brinfo=br)
raise util.Abort("")
if len(found) == 1:
node = found[0]
--- a/mercurial/hgweb/server.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/hgweb/server.py Mon Nov 13 21:50:09 2006 +0100
@@ -200,6 +200,16 @@
self.reqmaker = wsgiapplication(self.make_handler)
self.daemon_threads = True
+ addr, port = self.socket.getsockname()
+ if addr == '0.0.0.0':
+ addr = socket.gethostname()
+ else:
+ try:
+ addr = socket.gethostbyaddr(addr)[0]
+ except socket.error:
+ pass
+ self.addr, self.port = addr, port
+
def make_handler(self):
if self.webdir_conf:
hgwebobj = self.webdirmaker(self.webdir_conf)
@@ -219,7 +229,10 @@
raise hg.RepoError(_('IPv6 not available on this system'))
super(IPv6HTTPServer, self).__init__(*args, **kwargs)
- if use_ipv6:
- return IPv6HTTPServer((address, port), _hgwebhandler)
- else:
- return MercurialHTTPServer((address, port), _hgwebhandler)
+ try:
+ if use_ipv6:
+ return IPv6HTTPServer((address, port), _hgwebhandler)
+ else:
+ return MercurialHTTPServer((address, port), _hgwebhandler)
+ except socket.error, inst:
+ raise util.Abort(_('cannot start server: %s') % inst.args[1])
--- a/mercurial/patch.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/patch.py Mon Nov 13 21:50:09 2006 +0100
@@ -26,11 +26,8 @@
targetdir = os.path.dirname(absdst)
if not os.path.isdir(targetdir):
os.makedirs(targetdir)
- try:
- shutil.copyfile(abssrc, absdst)
- shutil.copymode(abssrc, absdst)
- except shutil.Error, inst:
- raise util.Abort(str(inst))
+
+ util.copyfile(abssrc, absdst)
# public functions
--- a/mercurial/revlog.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/revlog.py Mon Nov 13 21:50:09 2006 +0100
@@ -542,10 +542,10 @@
else:
return self.index[rev][-5]
- def reachable(self, rev, stop=None):
+ def reachable(self, node, stop=None):
reachable = {}
- visit = [rev]
- reachable[rev] = 1
+ visit = [node]
+ reachable[node] = 1
if stop:
stopn = self.rev(stop)
else:
--- a/mercurial/templater.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/templater.py Mon Nov 13 21:50:09 2006 +0100
@@ -8,36 +8,17 @@
from demandload import demandload
from i18n import gettext as _
from node import *
-demandload(globals(), "cStringIO cgi re sys os time urllib util textwrap")
-
-esctable = {
- '\\': '\\',
- 'r': '\r',
- 't': '\t',
- 'n': '\n',
- 'v': '\v',
- }
+demandload(globals(), "cgi re sys os time urllib util textwrap")
def parsestring(s, quoted=True):
'''parse a string using simple c-like syntax.
string must be in quotes if quoted is True.'''
- fp = cStringIO.StringIO()
if quoted:
- first = s[0]
- if len(s) < 2: raise SyntaxError(_('string too short'))
- if first not in "'\"": raise SyntaxError(_('invalid quote'))
- if s[-1] != first: raise SyntaxError(_('unmatched quotes'))
- s = s[1:-1]
- escape = False
- for c in s:
- if escape:
- fp.write(esctable.get(c, c))
- escape = False
- elif c == '\\': escape = True
- elif quoted and c == first: raise SyntaxError(_('string ends early'))
- else: fp.write(c)
- if escape: raise SyntaxError(_('unterminated escape'))
- return fp.getvalue()
+ if len(s) < 2 or s[0] != s[-1]:
+ raise SyntaxError(_('unmatched quotes'))
+ return s[1:-1].decode('string_escape')
+
+ return s.decode('string_escape')
class templater(object):
'''template expansion engine.
@@ -59,6 +40,9 @@
filter uses function to transform value. syntax is
{key|filter1|filter2|...}.'''
+ template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
+ r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
+
def __init__(self, mapfile, filters={}, defaults={}, cache={}):
'''set up template engine.
mapfile is name of file to read map definitions from.
@@ -93,69 +77,53 @@
raise SyntaxError(_("%s:%s: parse error") % (mapfile, i))
def __contains__(self, key):
- return key in self.cache
+ return key in self.cache or key in self.map
def __call__(self, t, **map):
'''perform expansion.
t is name of map element to expand.
map is added elements to use during expansion.'''
- m = self.defaults.copy()
- m.update(map)
- try:
- tmpl = self.cache[t]
- except KeyError:
+ if not self.cache.has_key(t):
try:
- tmpl = self.cache[t] = file(self.map[t]).read()
+ self.cache[t] = file(self.map[t]).read()
except IOError, inst:
raise IOError(inst.args[0], _('template file %s: %s') %
(self.map[t], inst.args[1]))
- return self.template(tmpl, self.filters, **m)
+ tmpl = self.cache[t]
- template_re = re.compile(r"[#{]([a-zA-Z_][a-zA-Z0-9_]*)"
- r"((%[a-zA-Z_][a-zA-Z0-9_]*)*)"
- r"((\|[a-zA-Z_][a-zA-Z0-9_]*)*)[#}]")
-
- def template(self, tmpl, filters={}, **map):
- lm = map.copy()
while tmpl:
m = self.template_re.search(tmpl)
- if m:
- start, end = m.span(0)
- s, e = tmpl[start], tmpl[end - 1]
- key = m.group(1)
- if ((s == '#' and e != '#') or (s == '{' and e != '}')):
- raise SyntaxError(_("'%s'/'%s' mismatch expanding '%s'") %
- (s, e, key))
- if start:
- yield tmpl[:start]
- v = map.get(key, "")
- v = callable(v) and v(**map) or v
-
- format = m.group(2)
- fl = m.group(4)
-
- if format:
- try:
- q = v.__iter__
- except AttributeError:
- raise SyntaxError(_("Error expanding '%s%s'")
- % (key, format))
- for i in q():
- lm.update(i)
- yield self(format[1:], **lm)
-
- v = ""
-
- elif fl:
- for f in fl.split("|")[1:]:
- v = filters[f](v)
-
- yield v
- tmpl = tmpl[end:]
- else:
+ if not m:
yield tmpl
break
+ start, end = m.span(0)
+ key, format, fl = m.groups()
+
+ if start:
+ yield tmpl[:start]
+ tmpl = tmpl[end:]
+
+ if key in map:
+ v = map[key]
+ else:
+ v = self.defaults.get(key, "")
+ if callable(v):
+ v = v(**map)
+ if format:
+ if not hasattr(v, '__iter__'):
+ raise SyntaxError(_("Error expanding '%s%s'")
+ % (key, format))
+ lm = map.copy()
+ for i in v:
+ lm.update(i)
+ yield self(format, **lm)
+ else:
+ if fl:
+ for f in fl.split("|")[1:]:
+ v = self.filters[f](v)
+ yield v
+
agescales = [("second", 1),
("minute", 60),
("hour", 3600),
@@ -187,15 +155,10 @@
def stringify(thing):
'''turn nested template iterator into string.'''
- cs = cStringIO.StringIO()
- def walk(things):
- for t in things:
- if hasattr(t, '__iter__'):
- walk(t)
- else:
- cs.write(t)
- walk(thing)
- return cs.getvalue()
+ if hasattr(thing, '__iter__'):
+ return "".join([stringify(t) for t in thing])
+ if thing is None: return ""
+ return str(thing)
para_re = None
space_re = None
@@ -219,11 +182,8 @@
yield text[start:m.start(0)], m.group(1)
start = m.end(1)
- fp = cStringIO.StringIO()
- for para, rest in findparas():
- fp.write(space_re.sub(' ', textwrap.fill(para, width)))
- fp.write(rest)
- return fp.getvalue()
+ return "".join([space_re.sub(' ', textwrap.fill(para, width)) + rest
+ for para, rest in findparas()])
def firstline(text):
'''return the first line of text'''
@@ -275,16 +235,17 @@
def indent(text, prefix):
'''indent each non-empty line of text after first with prefix.'''
- fp = cStringIO.StringIO()
lines = text.splitlines()
num_lines = len(lines)
- for i in xrange(num_lines):
- l = lines[i]
- if i and l.strip(): fp.write(prefix)
- fp.write(l)
- if i < num_lines - 1 or text.endswith('\n'):
- fp.write('\n')
- return fp.getvalue()
+ def indenter():
+ for i in xrange(num_lines):
+ l = lines[i]
+ if i and l.strip():
+ yield prefix
+ yield l
+ if i < num_lines - 1 or text.endswith('\n'):
+ yield '\n'
+ return "".join(indenter())
common_filters = {
"addbreaks": nl2br,
@@ -329,228 +290,3 @@
if (name and os.path.exists(p)) or os.path.isdir(p):
return os.path.normpath(p)
-class changeset_templater(object):
- '''format changeset information.'''
-
- def __init__(self, ui, repo, mapfile, dest=None):
- self.t = templater(mapfile, common_filters,
- cache={'parent': '{rev}:{node|short} ',
- 'manifest': '{rev}:{node|short}',
- 'filecopy': '{name} ({source})'})
- self.ui = ui
- self.dest = dest
- self.repo = repo
-
- def use_template(self, t):
- '''set template string to use'''
- self.t.cache['changeset'] = t
-
- def write(self, thing, header=False):
- '''write expanded template.
- uses in-order recursive traverse of iterators.'''
- dest = self.dest or self.ui
- for t in thing:
- if hasattr(t, '__iter__'):
- self.write(t, header=header)
- elif header:
- dest.write_header(t)
- else:
- dest.write(t)
-
- def write_header(self, thing):
- self.write(thing, header=True)
-
- def show(self, rev=0, changenode=None, brinfo=None, changes=None,
- copies=[], **props):
- '''show a single changeset or file revision'''
- log = self.repo.changelog
- if changenode is None:
- changenode = log.node(rev)
- elif not rev:
- rev = log.rev(changenode)
- if changes is None:
- changes = log.read(changenode)
-
- def showlist(name, values, plural=None, **args):
- '''expand set of values.
- name is name of key in template map.
- values is list of strings or dicts.
- plural is plural of name, if not simply name + 's'.
-
- expansion works like this, given name 'foo'.
-
- if values is empty, expand 'no_foos'.
-
- if 'foo' not in template map, return values as a string,
- joined by space.
-
- expand 'start_foos'.
-
- for each value, expand 'foo'. if 'last_foo' in template
- map, expand it instead of 'foo' for last key.
-
- expand 'end_foos'.
- '''
- if plural: names = plural
- else: names = name + 's'
- if not values:
- noname = 'no_' + names
- if noname in self.t:
- yield self.t(noname, **args)
- return
- if name not in self.t:
- if isinstance(values[0], str):
- yield ' '.join(values)
- else:
- for v in values:
- yield dict(v, **args)
- return
- startname = 'start_' + names
- if startname in self.t:
- yield self.t(startname, **args)
- vargs = args.copy()
- def one(v, tag=name):
- try:
- vargs.update(v)
- except (AttributeError, ValueError):
- try:
- for a, b in v:
- vargs[a] = b
- except ValueError:
- vargs[name] = v
- return self.t(tag, **vargs)
- lastname = 'last_' + name
- if lastname in self.t:
- last = values.pop()
- else:
- last = None
- for v in values:
- yield one(v)
- if last is not None:
- yield one(last, tag=lastname)
- endname = 'end_' + names
- if endname in self.t:
- yield self.t(endname, **args)
-
- def showbranches(**args):
- branch = changes[5].get("branch")
- if branch:
- yield showlist('branch', [branch], plural='branches', **args)
- # add old style branches if requested
- if brinfo and changenode in brinfo:
- for x in showlist('branch', brinfo[changenode],
- plural='branches', **args):
- yield x
-
- if self.ui.debugflag:
- def showmanifest(**args):
- args = args.copy()
- args.update(dict(rev=self.repo.manifest.rev(changes[0]),
- node=hex(changes[0])))
- yield self.t('manifest', **args)
- else:
- showmanifest = ''
-
- def showparents(**args):
- parents = [[('rev', log.rev(p)), ('node', hex(p))]
- for p in log.parents(changenode)
- if self.ui.debugflag or p != nullid]
- if (not self.ui.debugflag and len(parents) == 1 and
- parents[0][0][1] == rev - 1):
- return
- for x in showlist('parent', parents, **args):
- yield x
-
- def showtags(**args):
- for x in showlist('tag', self.repo.nodetags(changenode), **args):
- yield x
-
- def showextras(**args):
- extras = changes[5].items()
- extras.sort()
- for key, value in extras:
- args = args.copy()
- args.update(dict(key=key, value=value))
- yield self.t('extra', **args)
-
- if self.ui.debugflag:
- files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
- def showfiles(**args):
- for x in showlist('file', files[0], **args): yield x
- def showadds(**args):
- for x in showlist('file_add', files[1], **args): yield x
- def showdels(**args):
- for x in showlist('file_del', files[2], **args): yield x
- else:
- def showfiles(**args):
- for x in showlist('file', changes[3], **args): yield x
- showadds = ''
- showdels = ''
-
- copies = [{'name': x[0], 'source': x[1]}
- for x in copies]
- def showcopies(**args):
- for x in showlist('file_copy', copies, plural='file_copies',
- **args):
- yield x
-
- defprops = {
- 'author': changes[1],
- 'branches': showbranches,
- 'date': changes[2],
- 'desc': changes[4],
- 'file_adds': showadds,
- 'file_dels': showdels,
- 'files': showfiles,
- 'file_copies': showcopies,
- 'manifest': showmanifest,
- 'node': hex(changenode),
- 'parents': showparents,
- 'rev': rev,
- 'tags': showtags,
- 'extras': showextras,
- }
- props = props.copy()
- props.update(defprops)
-
- try:
- if self.ui.debugflag and 'header_debug' in self.t:
- key = 'header_debug'
- elif self.ui.quiet and 'header_quiet' in self.t:
- key = 'header_quiet'
- elif self.ui.verbose and 'header_verbose' in self.t:
- key = 'header_verbose'
- elif 'header' in self.t:
- key = 'header'
- else:
- key = ''
- if key:
- self.write_header(self.t(key, **props))
- if self.ui.debugflag and 'changeset_debug' in self.t:
- key = 'changeset_debug'
- elif self.ui.quiet and 'changeset_quiet' in self.t:
- key = 'changeset_quiet'
- elif self.ui.verbose and 'changeset_verbose' in self.t:
- key = 'changeset_verbose'
- else:
- key = 'changeset'
- self.write(self.t(key, **props))
- except KeyError, inst:
- raise util.Abort(_("%s: no key named '%s'") % (self.t.mapfile,
- inst.args[0]))
- except SyntaxError, inst:
- raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
-
-class stringio(object):
- '''wrap cStringIO for use by changeset_templater.'''
- def __init__(self):
- self.fp = cStringIO.StringIO()
-
- def write(self, *args):
- for a in args:
- self.fp.write(a)
-
- write_header = write
-
- def __getattr__(self, key):
- return getattr(self.fp, key)
--- a/mercurial/ui.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/ui.py Mon Nov 13 21:50:09 2006 +0100
@@ -370,10 +370,6 @@
for a in args:
sys.stdout.write(str(a))
- def write_header(self, *args):
- for a in args:
- self.header.append(str(a))
-
def write_err(self, *args):
try:
if not sys.stdout.closed: sys.stdout.flush()
--- a/mercurial/util.py Thu Nov 09 14:44:17 2006 -0800
+++ b/mercurial/util.py Mon Nov 13 21:50:09 2006 +0100
@@ -460,6 +460,14 @@
except OSError:
pass
+def copyfile(src, dest):
+ "copy a file, preserving mode"
+ try:
+ shutil.copyfile(src, dest)
+ shutil.copymode(src, dest)
+ except shutil.Error, inst:
+ raise util.Abort(str(inst))
+
def copyfiles(src, dst, hardlink=None):
"""Copy a directory tree using hardlinks if possible"""
--- a/tests/test-remove.out Thu Nov 09 14:44:17 2006 -0800
+++ b/tests/test-remove.out Mon Nov 13 21:50:09 2006 +0100
@@ -37,7 +37,6 @@
@@ -0,0 +1,1 @@
+a
-
changeset: 1:a1fce69c50d9
tag: tip
user: test
@@ -50,7 +49,6 @@
@@ -1,1 +0,0 @@
-a
-
not removing a: file has been marked for add (use -f to force removal)
adding a
adding b