Mercurial > hg
changeset 3667:d5032b951c5c
merge with upstream
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Mon, 13 Nov 2006 21:50:09 +0100 |
parents | adbf440a81e0 (current diff) b984dcb1df71 (diff) |
children | 6f6696962986 |
files | |
diffstat | 12 files changed, 511 insertions(+), 568 deletions(-) [+] |
line wrap: on
line diff
--- 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