Mercurial > hg
changeset 9562:812aaef40757
Merge with main
author | Martin Geisler <mg@lazybytes.net> |
---|---|
date | Wed, 16 Sep 2009 23:46:06 +0200 |
parents | 2388ba07449b (current diff) 61e30f257c15 (diff) |
children | 5ac7121e31b6 |
files | doc/hgrc.5.txt hgext/churn.py |
diffstat | 73 files changed, 2264 insertions(+), 711 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/Makefile Wed Sep 16 16:11:44 2009 +0200 +++ b/doc/Makefile Wed Sep 16 23:46:06 2009 +0200 @@ -5,8 +5,7 @@ MANDIR=$(PREFIX)/share/man INSTALL=install -c -m 644 PYTHON=python -RST2HTML=rst2html -RST2MAN=rst2man +RST2HTML=$(shell which rst2html 2> /dev/null || which rst2html.py) all: man html @@ -18,20 +17,18 @@ touch hg.1.txt hg.1.gendoc.txt: gendoc.py ../mercurial/commands.py ../mercurial/help.py - ${PYTHON} gendoc.py > $@ + ${PYTHON} gendoc.py > $@.tmp + mv $@.tmp $@ %: %.txt common.txt - # add newline after all literal blocks and fix backslash escape - $(RST2MAN) $*.txt \ - | sed -e 's/^\.fi$$/.fi\n/' \ - | sed -e 's/\\fB\\\\fP/\\fB\\e\\fP/' \ - > $* + $(PYTHON) rst2man.py --halt warning \ + --strip-elements-with-class htmlonly $*.txt $* %.html: %.txt common.txt - $(RST2HTML) $*.txt > $*.html + $(RST2HTML) --halt warning $*.txt $*.html MANIFEST: man html - # tracked files are already in the main MANIFEST +# tracked files are already in the main MANIFEST $(RM) $@ for i in $(MAN) $(HTML) hg.1.gendoc.txt; do \ echo "doc/$$i" >> $@ ; \
--- a/doc/README Wed Sep 16 16:11:44 2009 +0200 +++ b/doc/README Wed Sep 16 23:46:06 2009 +0200 @@ -4,14 +4,8 @@ http://docutils.sourceforge.net/rst.html It's also convertible to a variety of other formats including standard -UNIX man page format and HTML. - -To do this, you'll need to install the rst2html and rst2man tools, -which are part of Docutils: +UNIX man page format and HTML. You'll need to install Docutils: http://docutils.sourceforge.net/ -The rst2man tool is still in their so-called "sandbox". The above page -has links to tarballs of both Docutils and their sandbox. - Use the Makefile in this directory to generate the man and HTML pages.
--- a/doc/hg.1.txt Wed Sep 16 16:11:44 2009 +0200 +++ b/doc/hg.1.txt Wed Sep 16 23:46:06 2009 +0200 @@ -11,6 +11,10 @@ :Manual section: 1 :Manual group: Mercurial Manual +.. contents:: + :backlinks: top + :class: htmlonly + SYNOPSIS --------
--- a/doc/hgrc.5.txt Wed Sep 16 16:11:44 2009 +0200 +++ b/doc/hgrc.5.txt Wed Sep 16 23:46:06 2009 +0200 @@ -11,6 +11,10 @@ :Manual section: 5 :Manual group: Mercurial Manual +.. contents:: + :backlinks: top + :class: htmlonly + SYNOPSIS -------- @@ -100,12 +104,12 @@ Lines beginning with "``#``" or "``;``" are ignored and may be used to provide comments. -A line of the form "`%include file`" will include `file` into the +A line of the form "``%include file``" will include ``file`` into the current configuration file. The inclusion is recursive, which means that included files can include other files. Filenames are relative to -the configuration file in which the `%include` directive is found. +the configuration file in which the ``%include`` directive is found. -A line with "`%unset name`" will remove `name` from the current +A line with "``%unset name``" will remove ``name`` from the current section, if it has been set previously. @@ -882,6 +886,10 @@ the list of repositories. The contents of the deny_read list have priority over (are examined before) the contents of the allow_read list. +``descend`` + hgwebdir indexes will not descend into subdirectories. Only repositories + directly in the current path will be shown (other repositories are still + available from the index corresponding to their containing path). ``description`` Textual description of the repository's purpose or contents. Default is "unknown".
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/rst2man.py Wed Sep 16 23:46:06 2009 +0200 @@ -0,0 +1,1112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# $Id: manpage.py 6110 2009-08-31 14:40:33Z grubert $ +# Author: Engelbert Gruber <grubert@users.sourceforge.net> +# Copyright: This module is put into the public domain. + +""" +Simple man page writer for reStructuredText. + +Man pages (short for "manual pages") contain system documentation on unix-like +systems. The pages are grouped in numbered sections: + + 1 executable programs and shell commands + 2 system calls + 3 library functions + 4 special files + 5 file formats + 6 games + 7 miscellaneous + 8 system administration + +Man pages are written *troff*, a text file formatting system. + +See http://www.tldp.org/HOWTO/Man-Page for a start. + +Man pages have no subsection only parts. +Standard parts + + NAME , + SYNOPSIS , + DESCRIPTION , + OPTIONS , + FILES , + SEE ALSO , + BUGS , + +and + + AUTHOR . + +A unix-like system keeps an index of the DESCRIPTIONs, which is accesable +by the command whatis or apropos. + +""" + +__docformat__ = 'reStructuredText' + +import sys +import os +import time +import re +from types import ListType + +import docutils +from docutils import nodes, utils, writers, languages +import roman + +FIELD_LIST_INDENT = 7 +DEFINITION_LIST_INDENT = 7 +OPTION_LIST_INDENT = 7 +BLOCKQOUTE_INDENT = 3.5 + +# Define two macros so man/roff can calculate the +# indent/unindent margins by itself +MACRO_DEF = (r""". +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +""") + +class Writer(writers.Writer): + + supported = ('manpage') + """Formats this writer supports.""" + + output = None + """Final translated form of `document`.""" + + def __init__(self): + writers.Writer.__init__(self) + self.translator_class = Translator + + def translate(self): + visitor = self.translator_class(self.document) + self.document.walkabout(visitor) + self.output = visitor.astext() + + +class Table: + def __init__(self): + self._rows = [] + self._options = ['center', ] + self._tab_char = '\t' + self._coldefs = [] + def new_row(self): + self._rows.append([]) + def append_separator(self, separator): + """Append the separator for table head.""" + self._rows.append([separator]) + def append_cell(self, cell_lines): + """cell_lines is an array of lines""" + start = 0 + if len(cell_lines)>0 and cell_lines[0] == '.sp\n': + start = 1 + self._rows[-1].append(cell_lines[start:]) + if len(self._coldefs) < len(self._rows[-1]): + self._coldefs.append('l') + def _minimize_cell(self, cell_lines): + """Remove leading and trailing blank and ``.sp`` lines""" + while (cell_lines and cell_lines[0] in ('\n', '.sp\n')): + del cell_lines[0] + while (cell_lines and cell_lines[-1] in ('\n', '.sp\n')): + del cell_lines[-1] + def as_list(self): + text = ['.TS\n'] + text.append(' '.join(self._options) + ';\n') + text.append('|%s|.\n' % ('|'.join(self._coldefs))) + for row in self._rows: + # row = array of cells. cell = array of lines. + text.append('_\n') # line above + text.append('T{\n') + for i in range(len(row)): + cell = row[i] + self._minimize_cell(cell) + text.extend(cell) + if not text[-1].endswith('\n'): + text[-1] += '\n' + if i < len(row)-1: + text.append('T}'+self._tab_char+'T{\n') + else: + text.append('T}\n') + text.append('_\n') + text.append('.TE\n') + return text + +class Translator(nodes.NodeVisitor): + """""" + + words_and_spaces = re.compile(r'\S+| +|\n') + document_start = """Man page generated from reStructeredText.""" + + def __init__(self, document): + nodes.NodeVisitor.__init__(self, document) + self.settings = settings = document.settings + lcode = settings.language_code + self.language = languages.get_language(lcode) + self.head = [] + self.body = [] + self.foot = [] + self.section_level = 0 + self.context = [] + self.topic_class = '' + self.colspecs = [] + self.compact_p = 1 + self.compact_simple = None + # the list style "*" bullet or "#" numbered + self._list_char = [] + # writing the header .TH and .SH NAME is postboned after + # docinfo. + self._docinfo = { + "title" : "", "title_upper": "", + "subtitle" : "", + "manual_section" : "", "manual_group" : "", + "author" : [], + "date" : "", + "copyright" : "", + "version" : "", + } + self._docinfo_keys = [] # a list to keep the sequence as in source. + self._docinfo_names = {} # to get name from text not normalized. + self._in_docinfo = None + self._active_table = None + self._in_literal = False + self.header_written = 0 + self._line_block = 0 + self.authors = [] + self.section_level = 0 + self._indent = [0] + # central definition of simple processing rules + # what to output on : visit, depart + # Do not use paragraph requests ``.PP`` because these set indentation. + # use ``.sp``. Remove superfluous ``.sp`` in ``astext``. + # + # Fonts are put on a stack, the top one is used. + # ``.ft P`` or ``\\fP`` pop from stack. + # ``B`` bold, ``I`` italic, ``R`` roman should be available. + # Hopefully ``C`` courier too. + self.defs = { + 'indent' : ('.INDENT %.1f\n', '.UNINDENT\n'), + 'definition_list_item' : ('.TP', ''), + 'field_name' : ('.TP\n.B ', '\n'), + 'literal' : ('\\fC', '\\fP'), + 'literal_block' : ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'), + + 'option_list_item' : ('.TP\n', ''), + + 'reference' : (r'\fI\%', r'\fP'), + 'emphasis': ('\\fI', '\\fP'), + 'strong' : ('\\fB', '\\fP'), + 'term' : ('\n.B ', '\n'), + 'title_reference' : ('\\fI', '\\fP'), + + 'topic-title' : ('.SS ', ), + 'sidebar-title' : ('.SS ', ), + + 'problematic' : ('\n.nf\n', '\n.fi\n'), + } + # NOTE dont specify the newline before a dot-command, but ensure + # it is there. + + def comment_begin(self, text): + """Return commented version of the passed text WITHOUT end of + line/comment.""" + prefix = '.\\" ' + out_text = ''.join( + [(prefix + in_line + '\n') + for in_line in text.split('\n')]) + return out_text + + def comment(self, text): + """Return commented version of the passed text.""" + return self.comment_begin(text)+'.\n' + + def ensure_eol(self): + """Ensure the last line in body is terminated by new line.""" + if self.body[-1][-1] != '\n': + self.body.append('\n') + + def astext(self): + """Return the final formatted document as a string.""" + if not self.header_written: + # ensure we get a ".TH" as viewers require it. + self.head.append(self.header()) + # filter body + for i in xrange(len(self.body)-1,0,-1): + # remove superfluous vertical gaps. + if self.body[i] == '.sp\n': + if self.body[i-1][:4] in ('.BI ','.IP '): + self.body[i] = '.\n' + elif (self.body[i-1][:3] == '.B ' and + self.body[i-2][:4] == '.TP\n'): + self.body[i] = '.\n' + elif (self.body[i-1] == '\n' and + self.body[i-2][0] != '.' and + (self.body[i-3][:7] == '.TP\n.B ' + or self.body[i-3][:4] == '\n.B ') + ): + self.body[i] = '.\n' + return ''.join(self.head + self.body + self.foot) + + def deunicode(self, text): + text = text.replace(u'\xa0', '\\ ') + text = text.replace(u'\u2020', '\\(dg') + return text + + def visit_Text(self, node): + text = node.astext() + text = text.replace('\\','\\e') + replace_pairs = [ + (u'-', ur'\-'), + (u'\'', ur'\(aq'), + (u'´', ur'\''), + (u'`', ur'\(ga'), + ] + for (in_char, out_markup) in replace_pairs: + text = text.replace(in_char, out_markup) + # unicode + text = self.deunicode(text) + if self._in_literal: + # prevent interpretation of "." at line start + if text[0] == '.': + text = '\\&' + text + text = text.replace('\n.', '\n\\&.') + self.body.append(text) + + def depart_Text(self, node): + pass + + def list_start(self, node): + class enum_char: + enum_style = { + 'bullet' : '\\(bu', + 'emdash' : '\\(em', + } + + def __init__(self, style): + self._style = style + if node.has_key('start'): + self._cnt = node['start'] - 1 + else: + self._cnt = 0 + self._indent = 2 + if style == 'arabic': + # indentation depends on number of childrens + # and start value. + self._indent = len(str(len(node.children))) + self._indent += len(str(self._cnt)) + 1 + elif style == 'loweralpha': + self._cnt += ord('a') - 1 + self._indent = 3 + elif style == 'upperalpha': + self._cnt += ord('A') - 1 + self._indent = 3 + elif style.endswith('roman'): + self._indent = 5 + + def next(self): + if self._style == 'bullet': + return self.enum_style[self._style] + elif self._style == 'emdash': + return self.enum_style[self._style] + self._cnt += 1 + # TODO add prefix postfix + if self._style == 'arabic': + return "%d." % self._cnt + elif self._style in ('loweralpha', 'upperalpha'): + return "%c." % self._cnt + elif self._style.endswith('roman'): + res = roman.toRoman(self._cnt) + '.' + if self._style.startswith('upper'): + return res.upper() + return res.lower() + else: + return "%d." % self._cnt + def get_width(self): + return self._indent + def __repr__(self): + return 'enum_style-%s' % list(self._style) + + if node.has_key('enumtype'): + self._list_char.append(enum_char(node['enumtype'])) + else: + self._list_char.append(enum_char('bullet')) + if len(self._list_char) > 1: + # indent nested lists + self.indent(self._list_char[-2].get_width()) + else: + self.indent(self._list_char[-1].get_width()) + + def list_end(self): + self.dedent() + self._list_char.pop() + + def header(self): + tmpl = (".TH %(title_upper)s %(manual_section)s" + " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n" + ".SH NAME\n" + "%(title)s \- %(subtitle)s\n") + return tmpl % self._docinfo + + def append_header(self): + """append header with .TH and .SH NAME""" + # NOTE before everything + # .TH title_upper section date source manual + if self.header_written: + return + self.body.append(self.header()) + self.body.append(MACRO_DEF) + self.header_written = 1 + + def visit_address(self, node): + self.visit_docinfo_item(node, 'address') + + def depart_address(self, node): + pass + + def visit_admonition(self, node, name=None): + if name: + self.body.append('.IP %s\n' % + self.language.labels.get(name, name)) + + def depart_admonition(self, node): + self.body.append('.RE\n') + + def visit_attention(self, node): + self.visit_admonition(node, 'attention') + + depart_attention = depart_admonition + + def visit_docinfo_item(self, node, name): + if name == 'author': + self._docinfo[name].append(node.astext()) + else: + self._docinfo[name] = node.astext() + self._docinfo_keys.append(name) + raise nodes.SkipNode + + def depart_docinfo_item(self, node): + pass + + def visit_author(self, node): + self.visit_docinfo_item(node, 'author') + + depart_author = depart_docinfo_item + + def visit_authors(self, node): + # _author is called anyway. + pass + + def depart_authors(self, node): + pass + + def visit_block_quote(self, node): + # BUG/HACK: indent alway uses the _last_ indention, + # thus we need two of them. + self.indent(BLOCKQOUTE_INDENT) + self.indent(0) + + def depart_block_quote(self, node): + self.dedent() + self.dedent() + + def visit_bullet_list(self, node): + self.list_start(node) + + def depart_bullet_list(self, node): + self.list_end() + + def visit_caption(self, node): + pass + + def depart_caption(self, node): + pass + + def visit_caution(self, node): + self.visit_admonition(node, 'caution') + + depart_caution = depart_admonition + + def visit_citation(self, node): + num,text = node.astext().split(None,1) + num = num.strip() + self.body.append('.IP [%s] 5\n' % num) + + def depart_citation(self, node): + pass + + def visit_citation_reference(self, node): + self.body.append('['+node.astext()+']') + raise nodes.SkipNode + + def visit_classifier(self, node): + pass + + def depart_classifier(self, node): + pass + + def visit_colspec(self, node): + self.colspecs.append(node) + + def depart_colspec(self, node): + pass + + def write_colspecs(self): + self.body.append("%s.\n" % ('L '*len(self.colspecs))) + + def visit_comment(self, node, + sub=re.compile('-(?=-)').sub): + self.body.append(self.comment(node.astext())) + raise nodes.SkipNode + + def visit_contact(self, node): + self.visit_docinfo_item(node, 'contact') + + depart_contact = depart_docinfo_item + + def visit_container(self, node): + pass + + def depart_container(self, node): + pass + + def visit_compound(self, node): + pass + + def depart_compound(self, node): + pass + + def visit_copyright(self, node): + self.visit_docinfo_item(node, 'copyright') + + def visit_danger(self, node): + self.visit_admonition(node, 'danger') + + depart_danger = depart_admonition + + def visit_date(self, node): + self.visit_docinfo_item(node, 'date') + + def visit_decoration(self, node): + pass + + def depart_decoration(self, node): + pass + + def visit_definition(self, node): + pass + + def depart_definition(self, node): + pass + + def visit_definition_list(self, node): + self.indent(DEFINITION_LIST_INDENT) + + def depart_definition_list(self, node): + self.dedent() + + def visit_definition_list_item(self, node): + self.body.append(self.defs['definition_list_item'][0]) + + def depart_definition_list_item(self, node): + self.body.append(self.defs['definition_list_item'][1]) + + def visit_description(self, node): + pass + + def depart_description(self, node): + pass + + def visit_docinfo(self, node): + self._in_docinfo = 1 + + def depart_docinfo(self, node): + self._in_docinfo = None + # NOTE nothing should be written before this + self.append_header() + + def visit_doctest_block(self, node): + self.body.append(self.defs['literal_block'][0]) + self._in_literal = True + + def depart_doctest_block(self, node): + self._in_literal = False + self.body.append(self.defs['literal_block'][1]) + + def visit_document(self, node): + # no blank line between comment and header. + self.body.append(self.comment(self.document_start).rstrip()+'\n') + # writing header is postboned + self.header_written = 0 + + def depart_document(self, node): + if self._docinfo['author']: + self.body.append('.SH AUTHOR\n%s\n' + % ', '.join(self._docinfo['author'])) + skip = ('author', 'copyright', 'date', + 'manual_group', 'manual_section', + 'subtitle', + 'title', 'title_upper', 'version') + for name in self._docinfo_keys: + if name == 'address': + self.body.append("\n%s:\n%s%s.nf\n%s\n.fi\n%s%s" % ( + self.language.labels.get(name, name), + self.defs['indent'][0] % 0, + self.defs['indent'][0] % BLOCKQOUTE_INDENT, + self._docinfo[name], + self.defs['indent'][1], + self.defs['indent'][1], + ) ) + elif not name in skip: + if name in self._docinfo_names: + label = self._docinfo_names[name] + else: + label = self.language.labels.get(name, name) + self.body.append("\n%s: %s\n" % (label, self._docinfo[name]) ) + if self._docinfo['copyright']: + self.body.append('.SH COPYRIGHT\n%s\n' + % self._docinfo['copyright']) + self.body.append( self.comment( + 'Generated by docutils manpage writer.\n' ) ) + + def visit_emphasis(self, node): + self.body.append(self.defs['emphasis'][0]) + + def depart_emphasis(self, node): + self.body.append(self.defs['emphasis'][1]) + + def visit_entry(self, node): + # a cell in a table row + if 'morerows' in node: + self.document.reporter.warning('"table row spanning" not supported', + base_node=node) + if 'morecols' in node: + self.document.reporter.warning( + '"table cell spanning" not supported', base_node=node) + self.context.append(len(self.body)) + + def depart_entry(self, node): + start = self.context.pop() + self._active_table.append_cell(self.body[start:]) + del self.body[start:] + + def visit_enumerated_list(self, node): + self.list_start(node) + + def depart_enumerated_list(self, node): + self.list_end() + + def visit_error(self, node): + self.visit_admonition(node, 'error') + + depart_error = depart_admonition + + def visit_field(self, node): + pass + + def depart_field(self, node): + pass + + def visit_field_body(self, node): + if self._in_docinfo: + name_normalized = self._field_name.lower().replace(" ","_") + self._docinfo_names[name_normalized] = self._field_name + self.visit_docinfo_item(node, name_normalized) + raise nodes.SkipNode + + def depart_field_body(self, node): + pass + + def visit_field_list(self, node): + self.indent(FIELD_LIST_INDENT) + + def depart_field_list(self, node): + self.dedent() + + def visit_field_name(self, node): + if self._in_docinfo: + self._field_name = node.astext() + raise nodes.SkipNode + else: + self.body.append(self.defs['field_name'][0]) + + def depart_field_name(self, node): + self.body.append(self.defs['field_name'][1]) + + def visit_figure(self, node): + self.indent(2.5) + self.indent(0) + + def depart_figure(self, node): + self.dedent() + self.dedent() + + def visit_footer(self, node): + self.document.reporter.warning('"footer" not supported', + base_node=node) + + def depart_footer(self, node): + pass + + def visit_footnote(self, node): + num,text = node.astext().split(None,1) + num = num.strip() + self.body.append('.IP [%s] 5\n' % self.deunicode(num)) + + def depart_footnote(self, node): + pass + + def footnote_backrefs(self, node): + self.document.reporter.warning('"footnote_backrefs" not supported', + base_node=node) + + def visit_footnote_reference(self, node): + self.body.append('['+self.deunicode(node.astext())+']') + raise nodes.SkipNode + + def depart_footnote_reference(self, node): + pass + + def visit_generated(self, node): + pass + + def depart_generated(self, node): + pass + + def visit_header(self, node): + raise NotImplementedError, node.astext() + + def depart_header(self, node): + pass + + def visit_hint(self, node): + self.visit_admonition(node, 'hint') + + depart_hint = depart_admonition + + def visit_subscript(self, node): + self.body.append('\\s-2\\d') + + def depart_subscript(self, node): + self.body.append('\\u\\s0') + + def visit_superscript(self, node): + self.body.append('\\s-2\\u') + + def depart_superscript(self, node): + self.body.append('\\d\\s0') + + def visit_attribution(self, node): + self.body.append('\\(em ') + + def depart_attribution(self, node): + self.body.append('\n') + + def visit_image(self, node): + self.document.reporter.warning('"image" not supported', + base_node=node) + text = [] + if 'alt' in node.attributes: + text.append(node.attributes['alt']) + if 'uri' in node.attributes: + text.append(node.attributes['uri']) + self.body.append('[image: %s]\n' % ('/'.join(text))) + raise nodes.SkipNode + + def visit_important(self, node): + self.visit_admonition(node, 'important') + + depart_important = depart_admonition + + def visit_label(self, node): + # footnote and citation + if (isinstance(node.parent, nodes.footnote) + or isinstance(node.parent, nodes.citation)): + raise nodes.SkipNode + self.document.reporter.warning('"unsupported "label"', + base_node=node) + self.body.append('[') + + def depart_label(self, node): + self.body.append(']\n') + + def visit_legend(self, node): + pass + + def depart_legend(self, node): + pass + + # WHAT should we use .INDENT, .UNINDENT ? + def visit_line_block(self, node): + self._line_block += 1 + if self._line_block == 1: + self.body.append('.nf\n') + else: + self.body.append('.in +2\n') + + def depart_line_block(self, node): + self._line_block -= 1 + if self._line_block == 0: + self.body.append('.fi\n') + self.body.append('.sp\n') + else: + self.body.append('.in -2\n') + + def visit_line(self, node): + pass + + def depart_line(self, node): + self.body.append('\n') + + def visit_list_item(self, node): + # man 7 man argues to use ".IP" instead of ".TP" + self.body.append('.IP %s %d\n' % ( + self._list_char[-1].next(), + self._list_char[-1].get_width(),) ) + + def depart_list_item(self, node): + pass + + def visit_literal(self, node): + self.body.append(self.defs['literal'][0]) + + def depart_literal(self, node): + self.body.append(self.defs['literal'][1]) + + def visit_literal_block(self, node): + self.body.append(self.defs['literal_block'][0]) + self._in_literal = True + + def depart_literal_block(self, node): + self._in_literal = False + self.body.append(self.defs['literal_block'][1]) + + def visit_meta(self, node): + raise NotImplementedError, node.astext() + + def depart_meta(self, node): + pass + + def visit_note(self, node): + self.visit_admonition(node, 'note') + + depart_note = depart_admonition + + def indent(self, by=0.5): + # if we are in a section ".SH" there already is a .RS + step = self._indent[-1] + self._indent.append(by) + self.body.append(self.defs['indent'][0] % step) + + def dedent(self): + self._indent.pop() + self.body.append(self.defs['indent'][1]) + + def visit_option_list(self, node): + self.indent(OPTION_LIST_INDENT) + + def depart_option_list(self, node): + self.dedent() + + def visit_option_list_item(self, node): + # one item of the list + self.body.append(self.defs['option_list_item'][0]) + + def depart_option_list_item(self, node): + self.body.append(self.defs['option_list_item'][1]) + + def visit_option_group(self, node): + # as one option could have several forms it is a group + # options without parameter bold only, .B, -v + # options with parameter bold italic, .BI, -f file + # + # we do not know if .B or .BI + self.context.append('.B') # blind guess + self.context.append(len(self.body)) # to be able to insert later + self.context.append(0) # option counter + + def depart_option_group(self, node): + self.context.pop() # the counter + start_position = self.context.pop() + text = self.body[start_position:] + del self.body[start_position:] + self.body.append('%s%s\n' % (self.context.pop(), ''.join(text))) + + def visit_option(self, node): + # each form of the option will be presented separately + if self.context[-1]>0: + self.body.append(', ') + if self.context[-3] == '.BI': + self.body.append('\\') + self.body.append(' ') + + def depart_option(self, node): + self.context[-1] += 1 + + def visit_option_string(self, node): + # do not know if .B or .BI + pass + + def depart_option_string(self, node): + pass + + def visit_option_argument(self, node): + self.context[-3] = '.BI' # bold/italic alternate + if node['delimiter'] != ' ': + self.body.append('\\fB%s ' % node['delimiter'] ) + elif self.body[len(self.body)-1].endswith('='): + # a blank only means no blank in output, just changing font + self.body.append(' ') + else: + # blank backslash blank, switch font then a blank + self.body.append(' \\ ') + + def depart_option_argument(self, node): + pass + + def visit_organization(self, node): + self.visit_docinfo_item(node, 'organization') + + def depart_organization(self, node): + pass + + def visit_paragraph(self, node): + # ``.PP`` : Start standard indented paragraph. + # ``.LP`` : Start block paragraph, all except the first. + # ``.P [type]`` : Start paragraph type. + # NOTE dont use paragraph starts because they reset indentation. + # ``.sp`` is only vertical space + self.ensure_eol() + self.body.append('.sp\n') + + def depart_paragraph(self, node): + self.body.append('\n') + + def visit_problematic(self, node): + self.body.append(self.defs['problematic'][0]) + + def depart_problematic(self, node): + self.body.append(self.defs['problematic'][1]) + + def visit_raw(self, node): + if node.get('format') == 'manpage': + self.body.append(node.astext() + "\n") + # Keep non-manpage raw text out of output: + raise nodes.SkipNode + + def visit_reference(self, node): + """E.g. link or email address.""" + self.body.append(self.defs['reference'][0]) + + def depart_reference(self, node): + self.body.append(self.defs['reference'][1]) + + def visit_revision(self, node): + self.visit_docinfo_item(node, 'revision') + + depart_revision = depart_docinfo_item + + def visit_row(self, node): + self._active_table.new_row() + + def depart_row(self, node): + pass + + def visit_section(self, node): + self.section_level += 1 + + def depart_section(self, node): + self.section_level -= 1 + + def visit_status(self, node): + self.visit_docinfo_item(node, 'status') + + depart_status = depart_docinfo_item + + def visit_strong(self, node): + self.body.append(self.defs['strong'][0]) + + def depart_strong(self, node): + self.body.append(self.defs['strong'][1]) + + def visit_substitution_definition(self, node): + """Internal only.""" + raise nodes.SkipNode + + def visit_substitution_reference(self, node): + self.document.reporter.warning('"substitution_reference" not supported', + base_node=node) + + def visit_subtitle(self, node): + if isinstance(node.parent, nodes.sidebar): + self.body.append(self.defs['strong'][0]) + elif isinstance(node.parent, nodes.document): + self.visit_docinfo_item(node, 'subtitle') + elif isinstance(node.parent, nodes.section): + self.body.append(self.defs['strong'][0]) + + def depart_subtitle(self, node): + # document subtitle calls SkipNode + self.body.append(self.defs['strong'][1]+'\n.PP\n') + + def visit_system_message(self, node): + # TODO add report_level + #if node['level'] < self.document.reporter['writer'].report_level: + # Level is too low to display: + # raise nodes.SkipNode + attr = {} + backref_text = '' + if node.hasattr('id'): + attr['name'] = node['id'] + if node.hasattr('line'): + line = ', line %s' % node['line'] + else: + line = '' + self.body.append('.IP "System Message: %s/%s (%s:%s)"\n' + % (node['type'], node['level'], node['source'], line)) + + def depart_system_message(self, node): + pass + + def visit_table(self, node): + self._active_table = Table() + + def depart_table(self, node): + self.ensure_eol() + self.body.extend(self._active_table.as_list()) + self._active_table = None + + def visit_target(self, node): + # targets are in-document hyper targets, without any use for man-pages. + raise nodes.SkipNode + + def visit_tbody(self, node): + pass + + def depart_tbody(self, node): + pass + + def visit_term(self, node): + self.body.append(self.defs['term'][0]) + + def depart_term(self, node): + self.body.append(self.defs['term'][1]) + + def visit_tgroup(self, node): + pass + + def depart_tgroup(self, node): + pass + + def visit_thead(self, node): + # MAYBE double line '=' + pass + + def depart_thead(self, node): + # MAYBE double line '=' + pass + + def visit_tip(self, node): + self.visit_admonition(node, 'tip') + + depart_tip = depart_admonition + + def visit_title(self, node): + if isinstance(node.parent, nodes.topic): + self.body.append(self.defs['topic-title'][0]) + elif isinstance(node.parent, nodes.sidebar): + self.body.append(self.defs['sidebar-title'][0]) + elif isinstance(node.parent, nodes.admonition): + self.body.append('.IP "') + elif self.section_level == 0: + self._docinfo['title'] = node.astext() + # document title for .TH + self._docinfo['title_upper'] = node.astext().upper() + raise nodes.SkipNode + elif self.section_level == 1: + self.body.append('.SH ') + else: + self.body.append('.SS ') + + def depart_title(self, node): + if isinstance(node.parent, nodes.admonition): + self.body.append('"') + self.body.append('\n') + + def visit_title_reference(self, node): + """inline citation reference""" + self.body.append(self.defs['title_reference'][0]) + + def depart_title_reference(self, node): + self.body.append(self.defs['title_reference'][1]) + + def visit_topic(self, node): + pass + + def depart_topic(self, node): + pass + + def visit_sidebar(self, node): + pass + + def depart_sidebar(self, node): + pass + + def visit_rubric(self, node): + pass + + def depart_rubric(self, node): + pass + + def visit_transition(self, node): + # .PP Begin a new paragraph and reset prevailing indent. + # .sp N leaves N lines of blank space. + # .ce centers the next line + self.body.append('\n.sp\n.ce\n----\n') + + def depart_transition(self, node): + self.body.append('\n.ce 0\n.sp\n') + + def visit_version(self, node): + self.visit_docinfo_item(node, 'version') + + def visit_warning(self, node): + self.visit_admonition(node, 'warning') + + depart_warning = depart_admonition + + def unimplemented_visit(self, node): + raise NotImplementedError('visiting unimplemented node type: %s' + % node.__class__.__name__) + +# The following part is taken from the Docutils rst2man.py script: +if __name__ == "__main__": + from docutils.core import publish_cmdline, default_description + description = ("Generates plain unix manual documents. " + + default_description) + publish_cmdline(writer=Writer(), description=description) + +# vim: set fileencoding=utf-8 et ts=4 ai :
--- a/hgext/churn.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/churn.py Wed Sep 16 23:46:06 2009 +0200 @@ -53,15 +53,17 @@ if opts.get('date'): df = util.matchdate(opts['date']) - get = util.cachefunc(lambda r: repo[r].changeset()) + get = util.cachefunc(lambda r: repo[r]) changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) for st, rev, fns in changeiter: + if not st == 'add': continue - if df and not df(get(rev)[2][0]): # doesn't match date format + + ctx = get(rev) + if df and not df(ctx.date()[0]): # doesn't match date format continue - ctx = repo[rev] key = getkey(ctx) key = amap.get(key, key) # alias remap if opts.get('changesets'): @@ -147,8 +149,8 @@ rate.sort(key=sortkey) # Be careful not to have a zero maxcount (issue833) - maxcount = float(max([v for k, v in rate])) or 1.0 - maxname = max([len(k) for k, v in rate]) + maxcount = float(max(v for k, v in rate)) or 1.0 + maxname = max(len(k) for k, v in rate) ttywidth = util.termwidth() ui.debug(_("assuming %i character terminal\n") % ttywidth)
--- a/hgext/color.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/color.py Wed Sep 16 23:46:06 2009 +0200 @@ -59,7 +59,6 @@ ''' import os, sys -import itertools from mercurial import cmdutil, commands, extensions, error from mercurial.i18n import _ @@ -146,7 +145,7 @@ patchlines = ui.popbuffer().splitlines() patchnames = repo.mq.series - for patch, patchname in itertools.izip(patchlines, patchnames): + for patch, patchname in zip(patchlines, patchnames): if opts['missing']: effects = _patch_effects['missing'] # Determine if patch is applied. @@ -219,12 +218,8 @@ 'changed': ['white'], 'trailingwhitespace': ['bold', 'red_background']} -_ui = None - def uisetup(ui): '''Initialize the extension.''' - global _ui - _ui = ui _setupcmd(ui, 'diff', commands.table, colordiff, _diff_effects) _setupcmd(ui, 'incoming', commands.table, None, _diff_effects) _setupcmd(ui, 'log', commands.table, None, _diff_effects) @@ -232,17 +227,10 @@ _setupcmd(ui, 'tip', commands.table, None, _diff_effects) _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects) -def extsetup(): try: mq = extensions.find('mq') - try: - # If we are loaded after mq, we must wrap commands.table - _setupcmd(_ui, 'qdiff', commands.table, colordiff, _diff_effects) - _setupcmd(_ui, 'qseries', commands.table, colorqseries, _patch_effects) - except error.UnknownCommand: - # Otherwise we wrap mq.cmdtable - _setupcmd(_ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects) - _setupcmd(_ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects) + _setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects) + _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects) except KeyError: # The mq extension is not enabled pass
--- a/hgext/convert/common.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/convert/common.py Wed Sep 16 23:46:06 2009 +0200 @@ -203,6 +203,8 @@ """Put tags into sink. tags: {tagname: sink_rev_id, ...} where tagname is an UTF-8 string. + Return a pair (tag_revision, tag_parent_revision), or (None, None) + if nothing was changed. """ raise NotImplementedError()
--- a/hgext/convert/convcmd.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/convert/convcmd.py Wed Sep 16 23:46:06 2009 +0200 @@ -336,11 +336,14 @@ ctags[k] = self.map[v] if c and ctags: - nrev = self.dest.puttags(ctags) - # write another hash correspondence to override the previous - # one so we don't end up with extra tag heads - if nrev: - self.map[c] = nrev + nrev, tagsparent = self.dest.puttags(ctags) + if nrev and tagsparent: + # write another hash correspondence to override the previous + # one so we don't end up with extra tag heads + tagsparents = [e for e in self.map.iteritems() + if e[1] == tagsparent] + if tagsparents: + self.map[tagsparents[0][0]] = nrev self.writeauthormap() finally:
--- a/hgext/convert/gnuarch.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/convert/gnuarch.py Wed Sep 16 23:46:06 2009 +0200 @@ -284,7 +284,7 @@ self.changes[rev].summary = self.recode(self.changes[rev].summary) # Commit revision origin when dealing with a branch or tag - if catlog.has_key('Continuation-of'): + if 'Continuation-of' in catlog: self.changes[rev].continuationof = self.recode(catlog['Continuation-of']) except Exception: raise util.Abort(_('could not parse cat-log of %s') % rev)
--- a/hgext/convert/hg.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/convert/hg.py Wed Sep 16 23:46:06 2009 +0200 @@ -189,7 +189,7 @@ newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags]) if newlines == oldlines: - return None + return None, None data = "".join(newlines) def getfilectx(repo, memctx, f): return context.memfilectx(f, data, False, False, None) @@ -201,7 +201,7 @@ [".hgtags"], getfilectx, "convert-repo", date, extra) self.repo.commitctx(ctx) - return hex(self.repo.changelog.tip()) + return hex(self.repo.changelog.tip()), hex(tagparent) def setfilemapmode(self, active): self.filemapmode = active
--- a/hgext/graphlog.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/graphlog.py Wed Sep 16 23:46:06 2009 +0200 @@ -22,48 +22,31 @@ ASCIIDATA = 'ASC' -def asciiformat(ui, repo, revdag, opts, parentrepo=None): - """formats a changelog DAG walk for ASCII output""" - if parentrepo is None: - parentrepo = repo - showparents = [ctx.node() for ctx in parentrepo[None].parents()] - displayer = show_changeset(ui, repo, opts, buffered=True) - for (id, type, ctx, parentids) in revdag: - if type != graphmod.CHANGESET: - continue - displayer.show(ctx) - lines = displayer.hunk.pop(ctx.rev()).split('\n')[:-1] - char = ctx.node() in showparents and '@' or 'o' - yield (id, ASCIIDATA, (char, lines), parentids) - -def asciiedges(nodes): +def asciiedges(seen, rev, parents): """adds edge info to changelog DAG walk suitable for ascii()""" - seen = [] - for node, type, data, parents in nodes: - if node not in seen: - seen.append(node) - nodeidx = seen.index(node) + if rev not in seen: + seen.append(rev) + nodeidx = seen.index(rev) + + knownparents = [] + newparents = [] + for parent in parents: + if parent in seen: + knownparents.append(parent) + else: + newparents.append(parent) - knownparents = [] - newparents = [] - for parent in parents: - if parent in seen: - knownparents.append(parent) - else: - newparents.append(parent) + ncols = len(seen) + seen[nodeidx:nodeidx + 1] = newparents + edges = [(nodeidx, seen.index(p)) for p in knownparents] - ncols = len(seen) - nextseen = seen[:] - nextseen[nodeidx:nodeidx + 1] = newparents - edges = [(nodeidx, nextseen.index(p)) for p in knownparents] + if len(newparents) > 0: + edges.append((nodeidx, nodeidx)) + if len(newparents) > 1: + edges.append((nodeidx, nodeidx + 1)) - if len(newparents) > 0: - edges.append((nodeidx, nodeidx)) - if len(newparents) > 1: - edges.append((nodeidx, nodeidx + 1)) - nmorecols = len(nextseen) - ncols - seen = nextseen - yield (nodeidx, type, data, edges, ncols, nmorecols) + nmorecols = len(seen) - ncols + return nodeidx, edges, ncols, nmorecols def fix_long_right_edges(edges): for (i, (start, end)) in enumerate(edges): @@ -117,11 +100,13 @@ line.extend(["|", " "] * (n_columns - ni - 1)) return line -def ascii(ui, dag): +def ascii(ui, base, type, char, text, coldata): """prints an ASCII graph of the DAG - dag is a generator that emits tuples with the following elements: + takes the following arguments (one call per node in the graph): + - ui to write to + - A list we can keep the needed state in - Column of the current node in the set of ongoing edges. - Type indicator of node data == ASCIIDATA. - Payload: (char, lines): @@ -135,91 +120,87 @@ in the current revision. That is: -1 means one column removed; 0 means no columns added or removed; 1 means one column added. """ - prev_n_columns_diff = 0 - prev_node_index = 0 - for (node_index, type, (node_ch, node_lines), edges, n_columns, n_columns_diff) in dag: - assert -2 < n_columns_diff < 2 - if n_columns_diff == -1: - # Transform - # - # | | | | | | - # o | | into o---+ - # |X / |/ / - # | | | | - fix_long_right_edges(edges) - - # add_padding_line says whether to rewrite + idx, edges, ncols, coldiff = coldata + assert -2 < coldiff < 2 + if coldiff == -1: + # Transform # - # | | | | | | | | - # | o---+ into | o---+ - # | / / | | | # <--- padding line - # o | | | / / - # o | | - add_padding_line = (len(node_lines) > 2 and - n_columns_diff == -1 and - [x for (x, y) in edges if x + 1 < y]) + # | | | | | | + # o | | into o---+ + # |X / |/ / + # | | | | + fix_long_right_edges(edges) + + # add_padding_line says whether to rewrite + # + # | | | | | | | | + # | o---+ into | o---+ + # | / / | | | # <--- padding line + # o | | | / / + # o | | + add_padding_line = (len(text) > 2 and coldiff == -1 and + [x for (x, y) in edges if x + 1 < y]) - # fix_nodeline_tail says whether to rewrite - # - # | | o | | | | o | | - # | | |/ / | | |/ / - # | o | | into | o / / # <--- fixed nodeline tail - # | |/ / | |/ / - # o | | o | | - fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line + # fix_nodeline_tail says whether to rewrite + # + # | | o | | | | o | | + # | | |/ / | | |/ / + # | o | | into | o / / # <--- fixed nodeline tail + # | |/ / | |/ / + # o | | o | | + fix_nodeline_tail = len(text) <= 2 and not add_padding_line - # nodeline is the line containing the node character (typically o) - nodeline = ["|", " "] * node_index - nodeline.extend([node_ch, " "]) + # nodeline is the line containing the node character (typically o) + nodeline = ["|", " "] * idx + nodeline.extend([char, " "]) - nodeline.extend( - get_nodeline_edges_tail( - node_index, prev_node_index, n_columns, n_columns_diff, - prev_n_columns_diff, fix_nodeline_tail)) + nodeline.extend( + get_nodeline_edges_tail(idx, base[1], ncols, coldiff, + base[0], fix_nodeline_tail)) - # shift_interline is the line containing the non-vertical - # edges between this entry and the next - shift_interline = ["|", " "] * node_index - if n_columns_diff == -1: - n_spaces = 1 - edge_ch = "/" - elif n_columns_diff == 0: - n_spaces = 2 - edge_ch = "|" - else: - n_spaces = 3 - edge_ch = "\\" - shift_interline.extend(n_spaces * [" "]) - shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1)) + # shift_interline is the line containing the non-vertical + # edges between this entry and the next + shift_interline = ["|", " "] * idx + if coldiff == -1: + n_spaces = 1 + edge_ch = "/" + elif coldiff == 0: + n_spaces = 2 + edge_ch = "|" + else: + n_spaces = 3 + edge_ch = "\\" + shift_interline.extend(n_spaces * [" "]) + shift_interline.extend([edge_ch, " "] * (ncols - idx - 1)) - # draw edges from the current node to its parents - draw_edges(edges, nodeline, shift_interline) + # draw edges from the current node to its parents + draw_edges(edges, nodeline, shift_interline) - # lines is the list of all graph lines to print - lines = [nodeline] - if add_padding_line: - lines.append(get_padding_line(node_index, n_columns, edges)) - lines.append(shift_interline) + # lines is the list of all graph lines to print + lines = [nodeline] + if add_padding_line: + lines.append(get_padding_line(idx, ncols, edges)) + lines.append(shift_interline) - # make sure that there are as many graph lines as there are - # log strings - while len(node_lines) < len(lines): - node_lines.append("") - if len(lines) < len(node_lines): - extra_interline = ["|", " "] * (n_columns + n_columns_diff) - while len(lines) < len(node_lines): - lines.append(extra_interline) + # make sure that there are as many graph lines as there are + # log strings + while len(text) < len(lines): + text.append("") + if len(lines) < len(text): + extra_interline = ["|", " "] * (ncols + coldiff) + while len(lines) < len(text): + lines.append(extra_interline) - # print lines - indentation_level = max(n_columns, n_columns + n_columns_diff) - for (line, logstr) in zip(lines, node_lines): - ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr) - ui.write(ln.rstrip() + '\n') + # print lines + indentation_level = max(ncols, ncols + coldiff) + for (line, logstr) in zip(lines, text): + ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr) + ui.write(ln.rstrip() + '\n') - # ... and start over - prev_node_index = node_index - prev_n_columns_diff = n_columns_diff + # ... and start over + base[0] = coldiff + base[1] = idx def get_revs(repo, rev_opt): if rev_opt: @@ -235,6 +216,14 @@ if op in opts and opts[op]: raise util.Abort(_("--graph option is incompatible with --%s") % op) +def generate(ui, dag, displayer, showparents, edgefn): + seen, base = [], [0, 0] + for rev, type, ctx, parents in dag: + char = ctx.node() in showparents and '@' or 'o' + displayer.show(ctx) + lines = displayer.hunk.pop(rev).split('\n')[:-1] + ascii(ui, base, type, char, lines, edgefn(seen, rev, parents)) + def graphlog(ui, repo, path=None, **opts): """show revision history alongside an ASCII revision graph @@ -259,8 +248,9 @@ else: revdag = graphmod.revisions(repo, start, stop) - fmtdag = asciiformat(ui, repo, revdag, opts) - ascii(ui, asciiedges(fmtdag)) + displayer = show_changeset(ui, repo, opts, buffered=True) + showparents = [ctx.node() for ctx in repo[None].parents()] + generate(ui, revdag, displayer, showparents, asciiedges) def graphrevs(repo, nodes, opts): limit = cmdutil.loglimit(opts) @@ -294,8 +284,9 @@ o = repo.changelog.nodesbetween(o, revs)[0] revdag = graphrevs(repo, o, opts) - fmtdag = asciiformat(ui, repo, revdag, opts) - ascii(ui, asciiedges(fmtdag)) + displayer = show_changeset(ui, repo, opts, buffered=True) + showparents = [ctx.node() for ctx in repo[None].parents()] + generate(ui, revdag, displayer, showparents, asciiedges) def gincoming(ui, repo, source="default", **opts): """show the incoming changesets alongside an ASCII revision graph @@ -343,8 +334,9 @@ chlist = other.changelog.nodesbetween(incoming, revs)[0] revdag = graphrevs(other, chlist, opts) - fmtdag = asciiformat(ui, other, revdag, opts, parentrepo=repo) - ascii(ui, asciiedges(fmtdag)) + displayer = show_changeset(ui, other, opts, buffered=True) + showparents = [ctx.node() for ctx in repo[None].parents()] + generate(ui, revdag, displayer, showparents, asciiedges) finally: if hasattr(other, 'close'):
--- a/hgext/highlight/__init__.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/highlight/__init__.py Wed Sep 16 23:46:06 2009 +0200 @@ -53,8 +53,9 @@ req.respond(common.HTTP_OK, 'text/css') return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')] -# monkeypatch in the new version -extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight) -extensions.wrapfunction(webcommands, 'annotate', annotate_highlight) -webcommands.highlightcss = generate_css -webcommands.__all__.append('highlightcss') +def extsetup(): + # monkeypatch in the new version + extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight) + extensions.wrapfunction(webcommands, 'annotate', annotate_highlight) + webcommands.highlightcss = generate_css + webcommands.__all__.append('highlightcss')
--- a/hgext/highlight/highlight.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/highlight/highlight.py Wed Sep 16 23:46:06 2009 +0200 @@ -32,26 +32,27 @@ if util.binary(text): return - # avoid UnicodeDecodeError in pygments - text = encoding.tolocal(text) + # Pygments is best used with Unicode strings: + # <http://pygments.org/docs/unicode/> + text = text.decode(encoding.encoding, 'replace') # To get multi-line strings right, we can't format line-by-line try: - lexer = guess_lexer_for_filename(fctx.path(), text[:1024], - encoding=encoding.encoding) + lexer = guess_lexer_for_filename(fctx.path(), text[:1024]) except (ClassNotFound, ValueError): try: - lexer = guess_lexer(text[:1024], encoding=encoding.encoding) + lexer = guess_lexer(text[:1024]) except (ClassNotFound, ValueError): - lexer = TextLexer(encoding=encoding.encoding) + lexer = TextLexer() - formatter = HtmlFormatter(style=style, encoding=encoding.encoding) + formatter = HtmlFormatter(style=style) colorized = highlight(text, lexer, formatter) # strip wrapping div colorized = colorized[:colorized.find('\n</pre>')] colorized = colorized[colorized.find('<pre>')+5:] - coloriter = iter(colorized.splitlines()) + coloriter = (s.encode(encoding.encoding, 'replace') + for s in colorized.splitlines()) tmpl.filters['colorize'] = lambda x: coloriter.next()
--- a/hgext/inotify/__init__.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/inotify/__init__.py Wed Sep 16 23:46:06 2009 +0200 @@ -13,7 +13,6 @@ from mercurial.i18n import _ from mercurial import cmdutil, util import server -from weakref import proxy from client import client, QueryFailed def serve(ui, repo, **opts): @@ -25,7 +24,8 @@ class service(object): def init(self): try: - self.master = server.master(ui, repo, timeout) + self.master = server.master(ui, repo.dirstate, + repo.root, timeout) except server.AlreadyStartedException, inst: raise util.Abort(str(inst)) @@ -56,9 +56,6 @@ if not hasattr(repo, 'dirstate'): return - # XXX: weakref until hg stops relying on __del__ - repo = proxy(repo) - class inotifydirstate(repo.dirstate.__class__): # We'll set this to false after an unsuccessful attempt so that
--- a/hgext/inotify/client.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/inotify/client.py Wed Sep 16 23:46:06 2009 +0200 @@ -29,12 +29,12 @@ if err[0] == errno.ECONNREFUSED: self.ui.warn(_('(found dead inotify server socket; ' 'removing it)\n')) - os.unlink(self.repo.join('inotify.sock')) + os.unlink(os.path.join(self.root, '.hg', 'inotify.sock')) if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart: self.ui.debug(_('(starting inotify server)\n')) try: try: - server.start(self.ui, self.repo) + server.start(self.ui, self.dirstate, self.root) except server.AlreadyStartedException, inst: # another process may have started its own # inotify server while this one was starting. @@ -64,11 +64,12 @@ class client(object): def __init__(self, ui, repo): self.ui = ui - self.repo = repo + self.dirstate = repo.dirstate + self.root = repo.root self.sock = socket.socket(socket.AF_UNIX) def _connect(self): - sockpath = self.repo.join('inotify.sock') + sockpath = os.path.join(self.root, '.hg', 'inotify.sock') try: self.sock.connect(sockpath) except socket.error, err:
--- a/hgext/inotify/linux/_inotify.c Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/inotify/linux/_inotify.c Wed Sep 16 23:46:06 2009 +0200 @@ -106,13 +106,12 @@ static PyObject *remove_watch(PyObject *self, PyObject *args) { - PyObject *ret = NULL; uint32_t wd; int fd; int r; if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd)) - goto bail; + return NULL; Py_BEGIN_ALLOW_THREADS r = inotify_rm_watch(fd, wd); @@ -120,18 +119,11 @@ if (r == -1) { PyErr_SetFromErrno(PyExc_OSError); - goto bail; + return NULL; } Py_INCREF(Py_None); - - goto done; - -bail: - Py_CLEAR(ret); - -done: - return ret; + return Py_None; } PyDoc_STRVAR(
--- a/hgext/inotify/server.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/inotify/server.py Wed Sep 16 23:46:06 2009 +0200 @@ -34,13 +34,11 @@ walk_ignored_errors = (errno.ENOENT, errno.ENAMETOOLONG) -def walkrepodirs(repo): +def walkrepodirs(dirstate, absroot): '''Iterate over all subdirectories of this repo. Exclude the .hg directory, any nested repos, and ignored dirs.''' - rootslash = repo.root + os.sep - def walkit(dirname, top): - fullpath = rootslash + dirname + fullpath = join(absroot, dirname) try: for name, kind in osutil.listdir(fullpath): if kind == stat.S_IFDIR: @@ -49,7 +47,7 @@ return else: d = join(dirname, name) - if repo.dirstate._ignore(d): + if dirstate._ignore(d): continue for subdir in walkit(d, False): yield subdir @@ -60,18 +58,16 @@ return walkit('', True) -def walk(repo, root): +def walk(dirstate, absroot, root): '''Like os.walk, but only yields regular files.''' # This function is critical to performance during startup. - rootslash = repo.root + os.sep - def walkit(root, reporoot): files, dirs = [], [] try: - fullpath = rootslash + root + fullpath = join(absroot, root) for name, kind in osutil.listdir(fullpath): if kind == stat.S_IFDIR: if name == '.hg': @@ -80,7 +76,7 @@ else: dirs.append(name) path = join(root, name) - if repo.dirstate._ignore(path): + if dirstate._ignore(path): continue for result in walkit(path, False): yield result @@ -98,7 +94,7 @@ return walkit(root, root == '') -def _explain_watch_limit(ui, repo): +def _explain_watch_limit(ui, dirstate, rootabs): path = '/proc/sys/fs/inotify/max_user_watches' try: limit = int(file(path).read()) @@ -112,7 +108,7 @@ ui.warn(_('*** this limit is too low to watch every ' 'directory in this repository\n')) ui.warn(_('*** counting directories: ')) - ndirs = len(list(walkrepodirs(repo))) + ndirs = len(list(walkrepodirs(dirstate, rootabs))) ui.warn(_('found %d\n') % ndirs) newlimit = min(limit, 1024) while newlimit < ((limit + ndirs) * 1.1): @@ -121,7 +117,7 @@ (limit, newlimit)) ui.warn(_('*** echo %d > %s\n') % (newlimit, path)) raise util.Abort(_('cannot watch %s until inotify watch limit is raised') - % repo.root) + % rootabs) class pollable(object): """ @@ -309,10 +305,12 @@ inotify.IN_UNMOUNT | 0) - def __init__(self, ui, repo): + def __init__(self, ui, dirstate, root): self.ui = ui - self.repo = repo - self.wprefix = self.repo.wjoin('') + self.dirstate = dirstate + + self.wprefix = join(root, '') + self.prefixlen = len(self.wprefix) try: self.watcher = watcher.watcher() except OSError, err: @@ -351,7 +349,7 @@ def dirstate_info(self): try: - st = os.lstat(self.repo.join('dirstate')) + st = os.lstat(self.wprefix + '.hg/dirstate') return st.st_mtime, st.st_ino except OSError, err: if err.errno != errno.ENOENT: @@ -363,7 +361,7 @@ return if self.watcher.path(path) is None: if self.ui.debugflag: - self.ui.note(_('watching %r\n') % path[len(self.wprefix):]) + self.ui.note(_('watching %r\n') % path[self.prefixlen:]) try: self.watcher.add(path, mask) except OSError, err: @@ -371,16 +369,16 @@ return if err.errno != errno.ENOSPC: raise - _explain_watch_limit(self.ui, self.repo) + _explain_watch_limit(self.ui, self.dirstate, self.wprefix) def setup(self): - self.ui.note(_('watching directories under %r\n') % self.repo.root) - self.add_watch(self.repo.path, inotify.IN_DELETE) + self.ui.note(_('watching directories under %r\n') % self.wprefix) + self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE) self.check_dirstate() def filestatus(self, fn, st): try: - type_, mode, size, time = self.repo.dirstate._map[fn][:4] + type_, mode, size, time = self.dirstate._map[fn][:4] except KeyError: type_ = '?' if type_ == 'n': @@ -392,7 +390,7 @@ if time != int(st_mtime): return 'l' return 'n' - if type_ == '?' and self.repo.dirstate._ignore(fn): + if type_ == '?' and self.dirstate._ignore(fn): return 'i' return type_ @@ -443,14 +441,13 @@ if oldstatus and oldstatus in self.statuskeys \ and oldstatus != newstatus: del self.statustrees[oldstatus].dir(root).files[fn] - if newstatus and newstatus != 'i': + + if newstatus in (None, 'i'): + d.files.pop(fn, None) + elif oldstatus != newstatus: d.files[fn] = newstatus - if newstatus in self.statuskeys: - dd = self.statustrees[newstatus].dir(root) - if oldstatus != newstatus or fn not in dd.files: - dd.files[fn] = newstatus - else: - d.files.pop(fn, None) + if newstatus != 'n': + self.statustrees[newstatus].dir(root).files[fn] = newstatus def check_deleted(self, key): @@ -458,7 +455,7 @@ # may have vanished from the dirstate; we must clean them up. nuke = [] for wfn, ignore in self.statustrees[key].walk(key): - if wfn not in self.repo.dirstate: + if wfn not in self.dirstate: nuke.append(wfn) for wfn in nuke: root, fn = split(wfn) @@ -466,12 +463,12 @@ del self.tree.dir(root).files[fn] def scan(self, topdir=''): - ds = self.repo.dirstate._map.copy() - self.add_watch(join(self.repo.root, topdir), self.mask) - for root, dirs, files in walk(self.repo, topdir): + ds = self.dirstate._map.copy() + self.add_watch(join(self.wprefix, topdir), self.mask) + for root, dirs, files in walk(self.dirstate, self.wprefix, topdir): for d in dirs: self.add_watch(join(root, d), self.mask) - wroot = root[len(self.wprefix):] + wroot = root[self.prefixlen:] for fn in files: wfn = join(wroot, fn) self.updatefile(wfn, self.getstat(wfn)) @@ -500,7 +497,7 @@ if not self.ui.debugflag: self.last_event = None self.ui.note(_('%s dirstate reload\n') % self.event_time()) - self.repo.dirstate.invalidate() + self.dirstate.invalidate() self.handle_timeout() self.scan() self.ui.note(_('%s end dirstate reload\n') % self.event_time()) @@ -516,8 +513,8 @@ # But it's easier to do nothing than to open that can of # worms. - if '_ignore' in self.repo.dirstate.__dict__: - delattr(self.repo.dirstate, '_ignore') + if '_ignore' in self.dirstate.__dict__: + delattr(self.dirstate, '_ignore') self.ui.note(_('rescanning due to .hgignore change\n')) self.handle_timeout() self.scan() @@ -560,7 +557,7 @@ try: st = self.stat(wpath) if stat.S_ISREG(st[0]): - if self.repo.dirstate[wpath] in 'lmn': + if self.dirstate[wpath] in 'lmn': self.updatefile(wpath, st) except OSError: pass @@ -574,7 +571,7 @@ self.check_dirstate() return - self.deletefile(wpath, self.repo.dirstate[wpath]) + self.deletefile(wpath, self.dirstate[wpath]) def process_create(self, wpath, evt): if self.ui.debugflag: @@ -634,7 +631,7 @@ (self.event_time(), len(events))) for evt in events: assert evt.fullpath.startswith(self.wprefix) - wpath = evt.fullpath[len(self.wprefix):] + wpath = evt.fullpath[self.prefixlen:] # paths have been normalized, wpath never ends with a '/' @@ -672,18 +669,17 @@ Returns a sorted list of relatives paths currently watched, for debugging purposes. """ - return sorted(tuple[0][len(self.wprefix):] for tuple in self.watcher) + return sorted(tuple[0][self.prefixlen:] for tuple in self.watcher) class server(pollable): """ Listens for client queries on unix socket inotify.sock """ - def __init__(self, ui, repo, repowatcher, timeout): + def __init__(self, ui, root, repowatcher, timeout): self.ui = ui - self.repo = repo self.repowatcher = repowatcher self.sock = socket.socket(socket.AF_UNIX) - self.sockpath = self.repo.join('inotify.sock') + self.sockpath = join(root, '.hg/inotify.sock') self.realsockpath = None try: self.sock.bind(self.sockpath) @@ -811,11 +807,10 @@ raise class master(object): - def __init__(self, ui, repo, timeout=None): + def __init__(self, ui, dirstate, root, timeout=None): self.ui = ui - self.repo = repo - self.repowatcher = repowatcher(ui, repo) - self.server = server(ui, repo, self.repowatcher, timeout) + self.repowatcher = repowatcher(ui, dirstate, root) + self.server = server(ui, root, self.repowatcher, timeout) def shutdown(self): for obj in pollable.instances.itervalues(): @@ -828,7 +823,7 @@ sys.exit(0) pollable.run() -def start(ui, repo): +def start(ui, dirstate, root): def closefds(ignore): # (from python bug #1177468) # close all inherited file descriptors @@ -849,7 +844,7 @@ except OSError: pass - m = master(ui, repo) + m = master(ui, dirstate, root) sys.stdout.flush() sys.stderr.flush()
--- a/hgext/mq.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/mq.py Wed Sep 16 23:46:06 2009 +0200 @@ -22,7 +22,6 @@ print patch series qseries print applied patches qapplied - print name of top applied patch qtop add known patch to applied stack qpush remove patch from applied stack qpop @@ -1682,17 +1681,35 @@ def applied(ui, repo, patch=None, **opts): """print the patches already applied""" + q = repo.mq + l = len(q.applied) + if patch: if patch not in q.series: raise util.Abort(_("patch %s is not in series file") % patch) end = q.series.index(patch) + 1 else: end = q.series_end(True) - return q.qseries(repo, length=end, status='A', summary=opts.get('summary')) + + if opts.get('last') and not end: + ui.write(_("no patches applied\n")) + return 1 + elif opts.get('last') and end == 1: + ui.write(_("only one patch applied\n")) + return 1 + elif opts.get('last'): + start = end - 2 + end = 1 + else: + start = 0 + + return q.qseries(repo, length=end, start=start, status='A', + summary=opts.get('summary')) def unapplied(ui, repo, patch=None, **opts): """print the patches not yet applied""" + q = repo.mq if patch: if patch not in q.series: @@ -1700,7 +1717,14 @@ start = q.series.index(patch) + 1 else: start = q.series_end(True) - q.qseries(repo, start=start, status='U', summary=opts.get('summary')) + + if start == len(q.series) and opts.get('first'): + ui.write(_("all patches applied\n")) + return 1 + + length = opts.get('first') and 1 or None + return q.qseries(repo, start=start, length=length, status='U', + summary=opts.get('summary')) def qimport(ui, repo, *filename, **opts): """import a patch @@ -2522,7 +2546,10 @@ seriesopts = [('s', 'summary', None, _('print first line of patch header'))] cmdtable = { - "qapplied": (applied, [] + seriesopts, _('hg qapplied [-s] [PATCH]')), + "qapplied": + (applied, + [('1', 'last', None, _('show only the last patch'))] + seriesopts, + _('hg qapplied [-1] [-s] [PATCH]')), "qclone": (clone, [('', 'pull', None, _('use pull protocol to copy metadata')), @@ -2645,7 +2672,10 @@ ('n', 'nobackup', None, _('no backups'))], _('hg strip [-f] [-b] [-n] REV')), "qtop": (top, [] + seriesopts, _('hg qtop [-s]')), - "qunapplied": (unapplied, [] + seriesopts, _('hg qunapplied [-s] [PATCH]')), + "qunapplied": + (unapplied, + [('1', 'first', None, _('show only the first patch'))] + seriesopts, + _('hg qunapplied [-1] [-s] [PATCH]')), "qfinish": (finish, [('a', 'applied', None, _('finish all applied changesets'))],
--- a/hgext/patchbomb.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/patchbomb.py Wed Sep 16 23:46:06 2009 +0200 @@ -162,12 +162,16 @@ body += '\n'.join(patch) msg = mail.mimetextpatch(body, display=opts.get('test')) + flag = ' '.join(opts.get('flag')) + if flag: + flag = ' ' + flag + subj = desc[0].strip().rstrip('. ') if total == 1 and not opts.get('intro'): - subj = '[PATCH] ' + (opts.get('subject') or subj) + subj = '[PATCH%s] %s' % (flag, opts.get('subject') or subj) else: tlen = len(str(total)) - subj = '[PATCH %0*d of %d] %s' % (tlen, idx, total, subj) + subj = '[PATCH %0*d of %d%s] %s' % (tlen, idx, total, flag, subj) msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test')) msg['X-Mercurial-Node'] = node return msg, subj @@ -322,11 +326,13 @@ if len(patches) > 1 or opts.get('intro'): tlen = len(str(len(patches))) - subj = '[PATCH %0*d of %d] %s' % ( - tlen, 0, len(patches), - opts.get('subject') or - prompt(ui, 'Subject:', - rest=' [PATCH %0*d of %d] ' % (tlen, 0, len(patches)))) + flag = ' '.join(opts.get('flag')) + if flag: + subj = '[PATCH %0*d of %d %s] ' % (tlen, 0, len(patches), flag) + else: + subj = '[PATCH %0*d of %d] ' % (tlen, 0, len(patches)) + subj += opts.get('subject') or prompt(ui, 'Subject:', rest=subj, + default='None') body = '' if opts.get('diffstat'): @@ -477,6 +483,7 @@ _('subject of first message (intro or single patch)')), ('', 'in-reply-to', '', _('message identifier to reply to')), + ('', 'flag', [], _('flags to add in subject prefixes')), ('t', 'to', [], _('email addresses of recipients')), ]
--- a/hgext/transplant.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/transplant.py Wed Sep 16 23:46:06 2009 +0200 @@ -182,7 +182,7 @@ fp.write("# HG changeset patch\n") fp.write("# User %s\n" % user) fp.write("# Date %d %d\n" % date) - fp.write(changelog[4]) + fp.write(msg + '\n') fp.close() try:
--- a/hgext/win32mbcs.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/win32mbcs.py Wed Sep 16 23:46:06 2009 +0200 @@ -101,7 +101,7 @@ if args: args = list(args) args[0] = appendsep(args[0]) - if kwds.has_key('path'): + if 'path' in kwds: kwds['path'] = appendsep(kwds['path']) return func(*args, **kwds) @@ -123,7 +123,7 @@ funcs = '''os.path.join os.path.split os.path.splitext os.path.splitunc os.path.normpath os.path.normcase os.makedirs mercurial.util.endswithsep mercurial.util.splitpath mercurial.util.checkcase - mercurial.util.fspath mercurial.windows.pconvert''' + mercurial.util.fspath mercurial.util.pconvert''' # codec and alias names of sjis and big5 to be faked. problematic_encodings = '''big5 big5-tw csbig5 big5hkscs big5-hkscs
--- a/hgext/zeroconf/__init__.py Wed Sep 16 16:11:44 2009 +0200 +++ b/hgext/zeroconf/__init__.py Wed Sep 16 23:46:06 2009 +0200 @@ -101,17 +101,20 @@ def __init__(self, repo, name=None): super(hgwebzc, self).__init__(repo, name) name = self.reponame or os.path.basename(repo.root) + path = self.repo.ui.config("web", "prefix", "").strip('/') desc = self.repo.ui.config("web", "description", name) - publish(name, desc, name, int(repo.ui.config("web", "port", 8000))) + publish(name, desc, path, int(repo.ui.config("web", "port", 8000))) class hgwebdirzc(hgwebdir_mod.hgwebdir): - def run(self): + def __init__(self, conf, baseui=None): + super(hgwebdirzc, self).__init__(conf, baseui) + prefix = self.ui.config("web", "prefix", "").strip('/') + '/' for r, p in self.repos: u = self.ui.copy() u.readconfig(os.path.join(p, '.hg', 'hgrc')) n = os.path.basename(r) - publish(n, "hgweb", p, int(u.config("web", "port", 8000))) - return super(hgwebdirzc, self).run() + path = (prefix + r).strip('/') + publish(n, "hgweb", path, int(u.config("web", "port", 8000))) # listen
--- a/mercurial/changegroup.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/changegroup.py Wed Sep 16 23:46:06 2009 +0200 @@ -10,7 +10,7 @@ import struct, os, bz2, zlib, tempfile def getchunk(source): - """get a chunk from a changegroup""" + """return the next chunk from changegroup 'source' as a string""" d = source.read(4) if not d: return "" @@ -25,7 +25,8 @@ return d def chunkiter(source): - """iterate through the chunks in source""" + """iterate through the chunks in source, yielding a sequence of chunks + (strings)""" while 1: c = getchunk(source) if not c: @@ -33,10 +34,11 @@ yield c def chunkheader(length): - """build a changegroup chunk header""" + """return a changegroup chunk header (string)""" return struct.pack(">l", length + 4) def closechunk(): + """return a changegroup chunk header (string) for a zero-length chunk""" return struct.pack(">l", 0) class nocompress(object):
--- a/mercurial/cmdutil.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/cmdutil.py Wed Sep 16 23:46:06 2009 +0200 @@ -987,12 +987,12 @@ def finddate(ui, repo, date): """Find the tipmost changeset that matches the given date spec""" df = util.matchdate(date) - get = util.cachefunc(lambda r: repo[r].changeset()) + get = util.cachefunc(lambda r: repo[r]) changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None}) results = {} for st, rev, fns in changeiter: if st == 'add': - d = get(rev)[2] + d = get(rev).date() if df(d[0]): results[rev] = d elif st == 'iter': @@ -1118,13 +1118,13 @@ def changerevgen(): for i, window in increasing_windows(len(repo) - 1, nullrev): for j in xrange(i - window, i + 1): - yield j, change(j)[3] + yield change(j) - for rev, changefiles in changerevgen(): - matches = filter(m, changefiles) + for ctx in changerevgen(): + matches = filter(m, ctx.files()) if matches: - fncache[rev] = matches - wanted.add(rev) + fncache[ctx.rev()] = matches + wanted.add(ctx.rev()) class followfilter(object): def __init__(self, onlyfirst=False): @@ -1189,7 +1189,7 @@ fns = fncache.get(rev) if not fns: def fns_generator(): - for f in change(rev)[3]: + for f in change(rev).files(): if m(f): yield f fns = fns_generator()
--- a/mercurial/commands.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/commands.py Wed Sep 16 23:46:06 2009 +0200 @@ -1275,9 +1275,9 @@ if opts.get('all'): cols.append(change) if opts.get('user'): - cols.append(ui.shortuser(get(r)[1])) + cols.append(ui.shortuser(get(r).user())) if opts.get('date'): - cols.append(datefunc(get(r)[2])) + cols.append(datefunc(get(r).date())) if opts.get('files_with_matches'): c = (fn, r) if c in filerevmatches: @@ -1291,7 +1291,7 @@ skip = {} revfiles = {} - get = util.cachefunc(lambda r: repo[r].changeset()) + get = util.cachefunc(lambda r: repo[r]) changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) found = False follow = opts.get('follow') @@ -1300,7 +1300,7 @@ matches.clear() revfiles.clear() elif st == 'add': - ctx = repo[rev] + ctx = get(rev) pctx = ctx.parents()[0] parent = pctx.rev() matches.setdefault(rev, {}) @@ -1323,18 +1323,18 @@ continue files.append(fn) - if not matches[rev].has_key(fn): + if fn not in matches[rev]: grepbody(fn, rev, flog.read(fnode)) pfn = copy or fn - if not matches[parent].has_key(pfn): + if pfn not in matches[parent]: try: fnode = pctx.filenode(pfn) grepbody(pfn, parent, flog.read(fnode)) except error.LookupError: pass elif st == 'iter': - parent = repo[rev].parents()[0].rev() + parent = get(rev).parents()[0].rev() for fn in sorted(revfiles.get(rev, [])): states = matches[rev][fn] copy = copies.get(rev, {}).get(fn) @@ -1982,7 +1982,7 @@ will appear in files:. """ - get = util.cachefunc(lambda r: repo[r].changeset()) + get = util.cachefunc(lambda r: repo[r]) changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) limit = cmdutil.loglimit(opts) @@ -2040,40 +2040,37 @@ if opts.get('only_merges') and len(parents) != 2: continue - if only_branches: - revbranch = get(rev)[5]['branch'] - if revbranch not in only_branches: - continue - - if df: - changes = get(rev) - if not df(changes[2][0]): - continue + ctx = get(rev) + if only_branches and ctx.branch() not in only_branches: + continue + + if df and not df(ctx.date()[0]): + continue if opts.get('keyword'): - changes = get(rev) miss = 0 for k in [kw.lower() for kw in opts['keyword']]: - if not (k in changes[1].lower() or - k in changes[4].lower() or - k in " ".join(changes[3]).lower()): + if not (k in ctx.user().lower() or + k in ctx.description().lower() or + k in " ".join(ctx.files()).lower()): miss = 1 break if miss: continue if opts['user']: - changes = get(rev) - if not [k for k in opts['user'] if k in changes[1]]: + if not [k for k in opts['user'] if k in ctx.user()]: continue copies = [] if opts.get('copies') and rev: - for fn in get(rev)[3]: + for fn in ctx.files(): rename = getrenamed(fn, rev) if rename: copies.append((fn, rename[0])) - displayer.show(context.changectx(repo, rev), copies=copies) + + displayer.show(ctx, copies=copies) + elif st == 'iter': if count == limit: break if displayer.flush(rev): @@ -2158,7 +2155,8 @@ roots, heads = [common.node()], [p2.node()] displayer = cmdutil.show_changeset(ui, repo, opts) for node in repo.changelog.nodesbetween(roots=roots, heads=heads)[0]: - displayer.show(repo[node]) + if node not in roots: + displayer.show(repo[node]) return 0 return hg.merge(repo, node, force=opts.get('force'))
--- a/mercurial/dispatch.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/dispatch.py Wed Sep 16 23:46:06 2009 +0200 @@ -335,7 +335,7 @@ path = _findrepo(os.getcwd()) or "" if not path: lui = ui - if path: + else: try: lui = ui.copy() lui.readconfig(os.path.join(path, ".hg", "hgrc")) @@ -349,19 +349,25 @@ lui = ui.copy() lui.readconfig(os.path.join(path, ".hg", "hgrc")) + # Configure extensions in phases: uisetup, extsetup, cmdtable, and + # reposetup. Programs like TortoiseHg will call _dispatch several + # times so we keep track of configured extensions in _loaded. extensions.loadall(lui) - for name, module in extensions.extensions(): - if name in _loaded: - continue + exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded] - # setup extensions - # TODO this should be generalized to scheme, where extensions can - # redepend on other extensions. then we should toposort them, and - # do initialization in correct order + # (uisetup is handled in extensions.loadall) + + for name, module in exts: extsetup = getattr(module, 'extsetup', None) if extsetup: - extsetup() + try: + extsetup(ui) + except TypeError: + if extsetup.func_code.co_argcount != 0: + raise + extsetup() # old extsetup with no ui argument + for name, module in exts: cmdtable = getattr(module, 'cmdtable', {}) overrides = [cmd for cmd in cmdtable if cmd in commands.table] if overrides: @@ -370,6 +376,8 @@ commands.table.update(cmdtable) _loaded.add(name) + # (reposetup is handled in hg.repository) + addaliases(lui, commands.table) # check for fallback encoding
--- a/mercurial/extensions.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/extensions.py Wed Sep 16 23:46:06 2009 +0200 @@ -40,6 +40,7 @@ return imp.load_source(module_name, path) def load(ui, name, path): + # unused ui argument kept for backwards compatibility if name.startswith('hgext.') or name.startswith('hgext/'): shortname = name[6:] else: @@ -66,12 +67,9 @@ _extensions[shortname] = mod _order.append(shortname) - uisetup = getattr(mod, 'uisetup', None) - if uisetup: - uisetup(ui) - def loadall(ui): result = ui.configitems("extensions") + newindex = len(_order) for (name, path) in result: if path: if path[0] == '!': @@ -90,6 +88,11 @@ if ui.traceback(): return 1 + for name in _order[newindex:]: + uisetup = getattr(_extensions[name], 'uisetup', None) + if uisetup: + uisetup(ui) + def wrapcommand(table, command, wrapper): aliases, entry = cmdutil.findcmd(command, table) for alias, e in table.iteritems():
--- a/mercurial/help.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/help.py Wed Sep 16 23:46:06 2009 +0200 @@ -405,59 +405,59 @@ List of filters: - :addbreaks: Any text. Add an XHTML "<br />" tag before the end of - every line except the last. - :age: Date. Returns a human-readable date/time difference - between the given date/time and the current - date/time. - :basename: Any text. Treats the text as a path, and returns the - last component of the path after splitting by the - path separator (ignoring trailing separators). For - example, "foo/bar/baz" becomes "baz" and "foo/bar//" - becomes "bar". - :stripdir: Treat the text as path and strip a directory level, - if possible. For example, "foo" and "foo/bar" becomes - "foo". - :date: Date. Returns a date in a Unix date format, including - the timezone: "Mon Sep 04 15:13:13 2006 0700". - :domain: Any text. Finds the first string that looks like an - email address, and extracts just the domain - component. Example: 'User <user@example.com>' becomes - 'example.com'. - :email: Any text. Extracts the first string that looks like - an email address. Example: 'User <user@example.com>' - becomes 'user@example.com'. - :escape: Any text. Replaces the special XML/XHTML characters - "&", "<" and ">" with XML entities. - :fill68: Any text. Wraps the text to fit in 68 columns. - :fill76: Any text. Wraps the text to fit in 76 columns. - :firstline: Any text. Returns the first line of text. - :nonempty: Any text. Returns '(none)' if the string is empty. - :hgdate: Date. Returns the date as a pair of numbers: - "1157407993 25200" (Unix timestamp, timezone offset). - :isodate: Date. Returns the date in ISO 8601 format: - "2009-08-18 13:00 +0200". - :isodatesec: Date. Returns the date in ISO 8601 format, including - seconds: "2009-08-18 13:00:13 +0200". See also the - rfc3339date filter. - :localdate: Date. Converts a date to local date. - :obfuscate: Any text. Returns the input text rendered as a - sequence of XML entities. - :person: Any text. Returns the text before an email address. - :rfc822date: Date. Returns a date using the same format used in - email headers: "Tue, 18 Aug 2009 13:00:13 +0200". + :addbreaks: Any text. Add an XHTML "<br />" tag before the end of + every line except the last. + :age: Date. Returns a human-readable date/time difference + between the given date/time and the current + date/time. + :basename: Any text. Treats the text as a path, and returns the + last component of the path after splitting by the + path separator (ignoring trailing separators). For + example, "foo/bar/baz" becomes "baz" and "foo/bar//" + becomes "bar". + :stripdir: Treat the text as path and strip a directory level, + if possible. For example, "foo" and "foo/bar" becomes + "foo". + :date: Date. Returns a date in a Unix date format, including + the timezone: "Mon Sep 04 15:13:13 2006 0700". + :domain: Any text. Finds the first string that looks like an + email address, and extracts just the domain + component. Example: 'User <user@example.com>' becomes + 'example.com'. + :email: Any text. Extracts the first string that looks like + an email address. Example: 'User <user@example.com>' + becomes 'user@example.com'. + :escape: Any text. Replaces the special XML/XHTML characters + "&", "<" and ">" with XML entities. + :fill68: Any text. Wraps the text to fit in 68 columns. + :fill76: Any text. Wraps the text to fit in 76 columns. + :firstline: Any text. Returns the first line of text. + :nonempty: Any text. Returns '(none)' if the string is empty. + :hgdate: Date. Returns the date as a pair of numbers: + "1157407993 25200" (Unix timestamp, timezone offset). + :isodate: Date. Returns the date in ISO 8601 format: + "2009-08-18 13:00 +0200". + :isodatesec: Date. Returns the date in ISO 8601 format, including + seconds: "2009-08-18 13:00:13 +0200". See also the + rfc3339date filter. + :localdate: Date. Converts a date to local date. + :obfuscate: Any text. Returns the input text rendered as a + sequence of XML entities. + :person: Any text. Returns the text before an email address. + :rfc822date: Date. Returns a date using the same format used in + email headers: "Tue, 18 Aug 2009 13:00:13 +0200". :rfc3339date: Date. Returns a date using the Internet date format specified in RFC 3339: "2009-08-18T13:00:13+02:00". - :short: Changeset hash. Returns the short form of a changeset - hash, i.e. a 12-byte hexadecimal string. - :shortdate: Date. Returns a date like "2006-09-18". - :strip: Any text. Strips all leading and trailing whitespace. - :tabindent: Any text. Returns the text, with every line except - the first starting with a tab character. - :urlescape: Any text. Escapes all "special" characters. For - example, "foo bar" becomes "foo%20bar". - :user: Any text. Returns the user portion of an email - address. + :short: Changeset hash. Returns the short form of a changeset + hash, i.e. a 12-byte hexadecimal string. + :shortdate: Date. Returns a date like "2006-09-18". + :strip: Any text. Strips all leading and trailing whitespace. + :tabindent: Any text. Returns the text, with every line except + the first starting with a tab character. + :urlescape: Any text. Escapes all "special" characters. For + example, "foo bar" becomes "foo%20bar". + :user: Any text. Returns the user portion of an email + address. ''')), (['urls'], _('URL Paths'),
--- a/mercurial/hgweb/hgwebdir_mod.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/hgweb/hgwebdir_mod.py Wed Sep 16 23:46:06 2009 +0200 @@ -198,12 +198,17 @@ sortdefault = 'name', False def entries(sortcolumn="", descending=False, subdir="", **map): + rows = [] parity = paritygen(self.stripecount) + descend = self.ui.configbool('web', 'descend', True) for name, path in self.repos: + if not name.startswith(subdir): continue name = name[len(subdir):] + if not descend and '/' in name: + continue u = self.ui.copy() try:
--- a/mercurial/localrepo.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/localrepo.py Wed Sep 16 23:46:06 2009 +0200 @@ -1457,6 +1457,12 @@ return self.push_addchangegroup(remote, force, revs) def prepush(self, remote, force, revs): + '''Analyze the local and remote repositories and determine which + changesets need to be pushed to the remote. Return a tuple + (changegroup, remoteheads). changegroup is a readable file-like + object whose read() returns successive changegroup chunks ready to + be sent over the wire. remoteheads is the list of remote heads. + ''' common = {} remote_heads = remote.heads() inc = self.findincoming(remote, common, remote_heads, force=force) @@ -1601,9 +1607,10 @@ self.ui.debug("%s\n" % hex(node)) def changegroupsubset(self, bases, heads, source, extranodes=None): - """This function generates a changegroup consisting of all the nodes - that are descendents of any of the bases, and ancestors of any of - the heads. + """Compute a changegroup consisting of all the nodes that are + descendents of any of the bases and ancestors of any of the heads. + Return a chunkbuffer object whose read() method will return + successive changegroup chunks. It is fairly complex as determining which filenodes and which manifest nodes need to be included for the changeset to be complete @@ -1902,8 +1909,9 @@ return self.changegroupsubset(basenodes, self.heads(), source) def _changegroup(self, common, source): - """Generate a changegroup of all nodes that we have that a recipient - doesn't. + """Compute the changegroup of all nodes that we have that a recipient + doesn't. Return a chunkbuffer object whose read() method will return + successive changegroup chunks. This is much easier than the previous function as we can assume that the recipient has any changenode we aren't sending them. @@ -1937,6 +1945,7 @@ return lookuprevlink def gengroup(): + '''yield a sequence of changegroup chunks (strings)''' # construct a list of all changed files changedfiles = set()
--- a/mercurial/manifest.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/manifest.py Wed Sep 16 23:46:06 2009 +0200 @@ -20,12 +20,11 @@ def set(self, f, flags): self._flags[f] = flags def copy(self): - return manifestdict(dict.copy(self), dict.copy(self._flags)) + return manifestdict(self, dict.copy(self._flags)) class manifest(revlog.revlog): def __init__(self, opener): - self.mapcache = None - self.listcache = None + self._mancache = None revlog.revlog.__init__(self, opener, "00manifest.i") def parse(self, lines): @@ -40,12 +39,12 @@ def read(self, node): if node == revlog.nullid: return manifestdict() # don't upset local cache - if self.mapcache and self.mapcache[0] == node: - return self.mapcache[1] + if self._mancache and self._mancache[0] == node: + return self._mancache[1] text = self.revision(node) - self.listcache = array.array('c', text) + arraytext = array.array('c', text) mapping = self.parse(text) - self.mapcache = (node, mapping) + self._mancache = (node, mapping, arraytext) return mapping def _search(self, m, s, lo=0, hi=None): @@ -93,8 +92,8 @@ def find(self, node, f): '''look up entry for a single file efficiently. return (node, flags) pair if found, (None, None) if not.''' - if self.mapcache and node == self.mapcache[0]: - return self.mapcache[1].get(f), self.mapcache[1].flags(f) + if self._mancache and self._mancache[0] == node: + return self._mancache[1].get(f), self._mancache[1].flags(f) text = self.revision(node) start, end = self._search(text, f) if start == end: @@ -110,17 +109,13 @@ def addlistdelta(addlist, x): # start from the bottom up # so changes to the offsets don't mess things up. - i = len(x) - while i > 0: - i -= 1 - start = x[i][0] - end = x[i][1] - if x[i][2]: - addlist[start:end] = array.array('c', x[i][2]) + for start, end, content in reversed(x): + if content: + addlist[start:end] = array.array('c', content) else: del addlist[start:end] - return "".join([struct.pack(">lll", d[0], d[1], len(d[2])) + d[2] - for d in x ]) + return "".join(struct.pack(">lll", start, end, len(content)) + content + for start, end, content in x) def checkforbidden(l): for f in l: @@ -128,26 +123,29 @@ raise error.RevlogError( _("'\\n' and '\\r' disallowed in filenames: %r") % f) - # if we're using the listcache, make sure it is valid and + # if we're using the cache, make sure it is valid and # parented by the same node we're diffing against - if not (changed and self.listcache and p1 and self.mapcache[0] == p1): + if not (changed and self._mancache and p1 and self._mancache[0] == p1): files = sorted(map) checkforbidden(files) # if this is changed to support newlines in filenames, # be sure to check the templates/ dir again (especially *-raw.tmpl) hex, flags = revlog.hex, map.flags - text = ["%s\000%s%s\n" % (f, hex(map[f]), flags(f)) - for f in files] - self.listcache = array.array('c', "".join(text)) + text = ''.join("%s\000%s%s\n" % (f, hex(map[f]), flags(f)) + for f in files) + arraytext = array.array('c', text) cachedelta = None else: - addlist = self.listcache + added, removed = changed + addlist = self._mancache[2] - checkforbidden(changed[0]) + checkforbidden(added) # combine the changed lists into one list for sorting - work = [[x, 0] for x in changed[0]] - work[len(work):] = [[x, 1] for x in changed[1]] + work = [(x, False) for x in added] + work.extend((x, True) for x in removed) + # this could use heapq.merge() (from python2.6+) or equivalent + # since the lists are already sorted work.sort() delta = [] @@ -160,18 +158,17 @@ # start with a readonly loop that finds the offset of # each line and creates the deltas - for w in work: - f = w[0] + for f, todelete in work: # bs will either be the index of the item or the insert point start, end = self._search(addbuf, f, start) - if w[1] == 0: + if not todelete: l = "%s\000%s%s\n" % (f, revlog.hex(map[f]), map.flags(f)) else: + if start == end: + # item we want to delete was not found, error out + raise AssertionError( + _("failed to remove %s from manifest") % f) l = "" - if start == end and w[1] == 1: - # item we want to delete was not found, error out - raise AssertionError( - _("failed to remove %s from manifest") % f) if dstart != None and dstart <= start and dend >= start: if dend < end: dend = end @@ -190,12 +187,12 @@ cachedelta = addlistdelta(addlist, delta) # the delta is only valid if we've been processing the tip revision - if self.mapcache[0] != self.tip(): + if p1 != self.tip(): cachedelta = None - self.listcache = addlist + arraytext = addlist + text = buffer(arraytext) - n = self.addrevision(buffer(self.listcache), transaction, link, - p1, p2, cachedelta) - self.mapcache = (n, map) + n = self.addrevision(text, transaction, link, p1, p2, cachedelta) + self._mancache = (n, map, arraytext) return n
--- a/mercurial/minirst.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/minirst.py Wed Sep 16 23:46:06 2009 +0200 @@ -279,6 +279,8 @@ def formatblock(block, width): """Format a block according to width.""" + if width <= 0: + width = 78 indent = ' ' * block['indent'] if block['type'] == 'margin': return ''
--- a/mercurial/parsers.c Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/parsers.c Wed Sep 16 23:46:06 2009 +0200 @@ -92,8 +92,6 @@ goto bail; if (nlen > 40) { - PyObject *flags; - flags = PyString_FromStringAndSize(zero + 41, nlen - 40); if (!flags)
--- a/mercurial/patch.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/patch.py Wed Sep 16 23:46:06 2009 +0200 @@ -188,7 +188,7 @@ if m: if gp: gitpatches.append(gp) - src, dst = m.group(1, 2) + dst = m.group(2) gp = patchmeta(dst) gp.lineno = lineno elif gp: @@ -378,15 +378,13 @@ self.write() self.write_rej() - def apply(self, h, reverse): + def apply(self, h): if not h.complete(): raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") % (h.number, h.desc, len(h.a), h.lena, len(h.b), h.lenb)) self.hunks += 1 - if reverse: - h.reverse() if self.missing: self.rej.append(h) @@ -600,31 +598,6 @@ self.startb, self.lenb) self.hunk[0] = self.desc - def reverse(self): - self.create, self.remove = self.remove, self.create - origlena = self.lena - origstarta = self.starta - self.lena = self.lenb - self.starta = self.startb - self.lenb = origlena - self.startb = origstarta - self.a = [] - self.b = [] - # self.hunk[0] is the @@ description - for x in xrange(1, len(self.hunk)): - o = self.hunk[x] - if o.startswith('-'): - n = '+' + o[1:] - self.b.append(o[1:]) - elif o.startswith('+'): - n = '-' + o[1:] - self.a.append(n) - else: - n = o - self.b.append(o[1:]) - self.a.append(o) - self.hunk[x] = o - def fix_newline(self): diffhelpers.fix_newline(self.hunk, self.a, self.b) @@ -762,7 +735,7 @@ return s return s[:i] -def selectfile(afile_orig, bfile_orig, hunk, strip, reverse): +def selectfile(afile_orig, bfile_orig, hunk, strip): def pathstrip(path, count=1): pathlen = len(path) i = 0 @@ -790,8 +763,6 @@ else: goodb = not nullb and os.path.exists(bfile) createfunc = hunk.createfile - if reverse: - createfunc = hunk.rmfile missing = not goodb and not gooda and not createfunc() # some diff programs apparently produce create patches where the @@ -977,8 +948,7 @@ if hunknum == 0 and dopatch and not gitworkdone: raise NoHunks -def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, - eol=None): +def applydiff(ui, fp, changed, strip=1, sourcefile=None, eol=None): """ Reads a patch from fp and tries to apply it. @@ -1008,7 +978,7 @@ if not current_file: continue current_hunk = values - ret = current_file.apply(current_hunk, reverse) + ret = current_file.apply(current_hunk) if ret >= 0: changed.setdefault(current_file.fname, None) if ret > 0: @@ -1021,7 +991,7 @@ current_file = patchfile(ui, sourcefile, opener, eol=eol) else: current_file, missing = selectfile(afile, bfile, first_hunk, - strip, reverse) + strip) current_file = patchfile(ui, current_file, opener, missing, eol) except PatchError, err: ui.warn(str(err) + '\n')
--- a/mercurial/repo.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/repo.py Wed Sep 16 23:46:06 2009 +0200 @@ -40,4 +40,5 @@ url = self.url() if url.endswith('/'): return url + path - return url + '/' + path + else: + return url + '/' + path
--- a/mercurial/revlog.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/revlog.py Wed Sep 16 23:46:06 2009 +0200 @@ -973,7 +973,7 @@ if node == nullid: return "" if self._cache and self._cache[0] == node: - return str(self._cache[2]) + return self._cache[2] # look up what we need to read text = None @@ -988,7 +988,7 @@ # do we have useful data cached? if self._cache and self._cache[1] >= base and self._cache[1] < rev: base = self._cache[1] - text = str(self._cache[2]) + text = self._cache[2] self._loadindex(base, rev + 1) self._chunkraw(base, rev) @@ -1111,7 +1111,8 @@ ifh.write(data[1]) self.checkinlinesize(transaction, ifh) - self._cache = (node, curr, text) + if type(text) == str: # only accept immutable objects + self._cache = (node, curr, text) return node def ancestor(self, a, b): @@ -1127,7 +1128,8 @@ return self.node(c) def group(self, nodelist, lookup, infocollect=None): - """calculate a delta group + """Calculate a delta group, yielding a sequence of changegroup chunks + (strings). Given a list of changeset revs, return a set of deltas and metadata corresponding to nodes. the first delta is
--- a/mercurial/tags.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/tags.py Wed Sep 16 23:46:06 2009 +0200 @@ -301,7 +301,10 @@ def _writetagcache(ui, repo, heads, tagfnode, cachetags): - cachefile = repo.opener('tags.cache', 'w', atomictemp=True) + try: + cachefile = repo.opener('tags.cache', 'w', atomictemp=True) + except (OSError, IOError): + return _debug(ui, 'writing cache file %s\n' % cachefile.name) realheads = repo.heads() # for sanity checks below
--- a/mercurial/templatefilters.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/templatefilters.py Wed Sep 16 23:46:06 2009 +0200 @@ -105,13 +105,14 @@ '''indent each non-empty line of text after first with prefix.''' lines = text.splitlines() num_lines = len(lines) + endswithnewline = text[-1:] == '\n' 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'): + if i < num_lines - 1 or endswithnewline: yield '\n' return "".join(indenter())
--- a/mercurial/templater.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/templater.py Wed Sep 16 23:46:06 2009 +0200 @@ -42,7 +42,7 @@ filter uses function to transform value. syntax is {key|filter1|filter2|...}.''' - template_re = re.compile(r'{([\w\|%]+)}|#([\w\|%]+)#') + template_re = re.compile(r'{([\w\|%]+)}') def __init__(self, loader, filters={}, defaults={}): self.loader = loader
--- a/mercurial/ui.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/ui.py Wed Sep 16 23:46:06 2009 +0200 @@ -199,7 +199,7 @@ def _path(self, loc): p = self.config('paths', loc) if p and '%%' in p: - self.warn('(deprecated \'%%\' in path %s=%s from %s)\n' % + self.warn("(deprecated '%%' in path %s=%s from %s)\n" % (loc, p, self.configsource('paths', loc))) p = p.replace('%%', '%') return p @@ -358,7 +358,7 @@ visible. 'topic' is the current operation, 'item' is a non-numeric marker of the current position (ie the currently in-process file), 'pos' is the current numeric position (ie - revision, bytes, etc.), units is a corresponding unit label, + revision, bytes, etc.), unit is a corresponding unit label, and total is the highest expected pos. Multiple nested topics may be active at a time. All topics @@ -368,14 +368,14 @@ if pos == None or not self.debugflag: return - if units: - units = ' ' + units + if unit: + unit = ' ' + unit if item: item = ' ' + item if total: pct = 100.0 * pos / total ui.debug('%s:%s %s/%s%s (%4.2g%%)\n' - % (topic, item, pos, total, units, pct)) + % (topic, item, pos, total, unit, pct)) else: - ui.debug('%s:%s %s%s\n' % (topic, item, pos, units)) + ui.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
--- a/mercurial/url.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/url.py Wed Sep 16 23:46:06 2009 +0200 @@ -487,6 +487,8 @@ authinfo = None return url, authinfo +handlerfuncs = [] + def opener(ui, authinfo=None): ''' construct an opener suitable for urllib2 @@ -507,6 +509,7 @@ handlers.extend((urllib2.HTTPBasicAuthHandler(passmgr), httpdigestauthhandler(passmgr))) + handlers.extend([h(ui, passmgr) for h in handlerfuncs]) opener = urllib2.build_opener(*handlers) # 1.0 here is the _protocol_ version
--- a/mercurial/util.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/util.py Wed Sep 16 23:46:06 2009 +0200 @@ -266,9 +266,7 @@ def canonpath(root, cwd, myname): """return the canonical path of myname, given cwd and root""" - if root == os.sep: - rootsep = os.sep - elif endswithsep(root): + if endswithsep(root): rootsep = root else: rootsep = root + os.sep @@ -663,8 +661,9 @@ contents = _fspathcache[dir] lpart = part.lower() + lenp = len(part) for n in contents: - if n.lower() == lpart: + if lenp == len(n) and n.lower() == lpart: result.append(n) break else: @@ -1275,6 +1274,9 @@ def wrap(line, hangindent, width=None): if width is None: width = termwidth() - 2 + if width <= hangindent: + # adjust for weird terminal size + width = max(78, hangindent + 1) padding = '\n' + ' ' * hangindent return padding.join(textwrap.wrap(line, width=width - hangindent))
--- a/mercurial/windows.py Wed Sep 16 16:11:44 2009 +0200 +++ b/mercurial/windows.py Wed Sep 16 23:46:06 2009 +0200 @@ -17,7 +17,7 @@ try: return osutil.posixfile(name, mode, buffering) except WindowsError, err: - raise IOError(err.errno, err.strerror) + raise IOError(err.errno, '%s: %s' % (name, err.strerror)) posixfile.__doc__ = osutil.posixfile.__doc__ class winstdout(object):
--- a/tests/hghave Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/hghave Wed Sep 16 23:46:06 2009 +0200 @@ -78,7 +78,7 @@ def has_icasefs(): # Stolen from mercurial.util - fd, path = tempfile.mkstemp(prefix=tempprefix) + fd, path = tempfile.mkstemp(prefix=tempprefix, dir='.') os.close(fd) try: s1 = os.stat(path) @@ -123,6 +123,10 @@ def has_git(): return matchoutput('git --version 2>&1', r'^git version') +def has_rst2html(): + return matchoutput('rst2html --version', r'^rst2html \(Docutils') or \ + matchoutput('rst2html.py --version', r'^rst2html.py \(Docutils') + def has_svn(): return matchoutput('svn --version 2>&1', r'^svn, version') and \ matchoutput('svnadmin --version 2>&1', r'^svnadmin, version') @@ -195,6 +199,7 @@ "outer-repo": (has_outer_repo, "outer repo"), "p4": (has_p4, "Perforce server and client"), "pygments": (has_pygments, "Pygments source highlighting library"), + "rst2html": (has_rst2html, "Docutils rst2html tool"), "svn": (has_svn, "subversion client and admin tools"), "svn-bindings": (has_svn_bindings, "subversion python bindings"), "symlink": (has_symlink, "symbolic links"),
--- a/tests/printenv.py Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/printenv.py Wed Sep 16 23:46:06 2009 +0200 @@ -46,12 +46,9 @@ elif url.startswith("remote:http"): os.environ["HG_URL"] = "remote:http" -if "HG_PENDING" in os.environ: - os.environ["HG_PENDING"] = os.environ["HG_PENDING"] and "true" - out.write("%s hook: " % name) for v in env: - out.write("%s=%s " % (v, os.environ[v])) + out.write("%s=%s " % (v, os.environ[v].replace(os.environ["HGTMP"], '$HGTMP'))) out.write("\n") out.close()
--- a/tests/run-tests.py Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/run-tests.py Wed Sep 16 23:46:06 2009 +0200 @@ -167,16 +167,22 @@ else: vlog = lambda *msg: None + if options.tmpdir: + options.tmpdir = os.path.expanduser(options.tmpdir) + try: + os.makedirs(options.tmpdir) + except OSError, err: + if err.errno != errno.EEXIST: + raise + if options.jobs < 1: - print >> sys.stderr, 'ERROR: -j/--jobs must be positive' - sys.exit(1) + parser.error('--jobs must be positive') if options.interactive and options.jobs > 1: print '(--interactive overrides --jobs)' options.jobs = 1 if options.py3k_warnings: if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0): - print 'ERROR: Py3k warnings switch can only be used on Python 2.6+' - sys.exit(1) + parser.error('--py3k-warnings can only be used on Python 2.6+') return (options, args)
--- a/tests/test-casefolding Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-casefolding Wed Sep 16 23:46:06 2009 +0200 @@ -31,6 +31,9 @@ hg rm a hg ci -Am removea echo A > A +# on linux hfs keeps the old case stored, force it +mv a aa +mv aa A hg ci -Am addA # Used to fail under case insensitive fs hg up -C 0
--- a/tests/test-convert-clonebranches.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-convert-clonebranches.out Wed Sep 16 23:46:06 2009 +0200 @@ -18,12 +18,12 @@ % incremental conversion 2 c1 pulling from branch0 into branch1 -2 changesets found +4 changesets found 1 c2 pulling from branch0 into branch2 -2 changesets found +4 changesets found 0 c3 pulling from branch2 into branch3 -3 changesets found +5 changesets found pulling from branch1 into branch3 1 changesets found
--- a/tests/test-convert-git Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-convert-git Wed Sep 16 23:46:06 2009 +0200 @@ -42,7 +42,7 @@ echo b >> a commit -a -m t4.1 -git checkout -b other HEAD^ >/dev/null 2>/dev/null +git checkout -b other HEAD~ >/dev/null 2>/dev/null echo c > a echo a >> a commit -a -m t4.2 @@ -68,7 +68,7 @@ echo >> foo commit -a -m 'change foo' -git checkout -b Bar HEAD^ >/dev/null 2>/dev/null +git checkout -b Bar HEAD~ >/dev/null 2>/dev/null echo quux >> quux git add quux commit -a -m 'add quux' @@ -77,7 +77,7 @@ git add bar commit -a -m 'add bar' -git checkout -b Baz HEAD^ >/dev/null 2>/dev/null +git checkout -b Baz HEAD~ >/dev/null 2>/dev/null echo baz > baz git add baz commit -a -m 'add baz' @@ -89,7 +89,7 @@ echo bar >> bar commit -a -m 'change bar' -git checkout -b Foo HEAD^ >/dev/null 2>/dev/null +git checkout -b Foo HEAD~ >/dev/null 2>/dev/null echo >> foo commit -a -m 'change foo'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-convert-tagsbranch-topology Wed Sep 16 23:46:06 2009 +0200 @@ -0,0 +1,64 @@ +#!/bin/sh + +"$TESTDIR/hghave" git || exit 80 + +echo "[extensions]" >> $HGRCPATH +echo "convert=" >> $HGRCPATH +echo 'hgext.graphlog =' >> $HGRCPATH +echo '[convert]' >> $HGRCPATH +echo 'hg.usebranchnames = True' >> $HGRCPATH +echo 'hg.tagsbranch = tags-update' >> $HGRCPATH + +GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME +GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL +GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE +GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME +GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL +GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE + +count=10 +action() +{ + GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000" + GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" + git "$@" >/dev/null 2>/dev/null || echo "git command error" + count=`expr $count + 1` +} + +glog() +{ + hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@" +} + +convertrepo() +{ + hg convert --datesort git-repo hg-repo +} + +# Build a GIT repo with at least 1 tag +mkdir git-repo +cd git-repo +git init >/dev/null 2>&1 +echo a > a +git add a +action commit -m "rev1" +action tag -m "tag1" tag1 +cd .. + +# Do a first conversion +convertrepo + +# Simulate upstream updates after first conversion +cd git-repo +echo b > a +git add a +action commit -m "rev2" +action tag -m "tag2" tag2 +cd .. + +# Perform an incremental conversion +convertrepo + +# Print the log +cd hg-repo +glog
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-convert-tagsbranch-topology.out Wed Sep 16 23:46:06 2009 +0200 @@ -0,0 +1,19 @@ +initializing destination hg-repo repository +scanning source... +sorting... +converting... +0 rev1 +updating tags +scanning source... +sorting... +converting... +0 rev2 +updating tags +o 3 "update tags" files: .hgtags +| +| o 2 "rev2" files: a +| | +o | 1 "update tags" files: .hgtags + / +o 0 "rev1" files: a +
--- a/tests/test-double-merge.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-double-merge.out Wed Sep 16 23:46:06 2009 +0200 @@ -1,9 +1,4 @@ created new head -changeset: 0:310fd17130da -user: test -date: Mon Jan 12 13:46:40 1970 +0000 -summary: add foo - changeset: 1:7731dad1c2b9 user: test date: Mon Jan 12 13:46:40 1970 +0000
--- a/tests/test-extension Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-extension Wed Sep 16 23:46:06 2009 +0200 @@ -55,6 +55,29 @@ hg foo echo 'barfoo = !' >> $HGRCPATH +# check that extensions are loaded in phases +cat > foo.py <<EOF +import os +name = os.path.basename(__file__).rsplit('.', 1)[0] +print "1) %s imported" % name +def uisetup(ui): + print "2) %s uisetup" % name +def extsetup(): + print "3) %s extsetup" % name +def reposetup(ui, repo): + print "4) %s reposetup" % name +EOF + +cp foo.py bar.py +echo 'foo = foo.py' >> $HGRCPATH +echo 'bar = bar.py' >> $HGRCPATH + +# command with no output, we just want to see the extensions loaded +hg paths + +echo 'foo = !' >> $HGRCPATH +echo 'bar = !' >> $HGRCPATH + cd .. cat > empty.py <<EOF '''empty cmdtable
--- a/tests/test-extension.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-extension.out Wed Sep 16 23:46:06 2009 +0200 @@ -16,6 +16,14 @@ reposetup called for a ui == repo.ui Foo +1) foo imported +1) bar imported +2) foo uisetup +2) bar uisetup +3) foo extsetup +3) bar extsetup +4) foo reposetup +4) bar reposetup empty extension - empty cmdtable no commands defined
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-gendoc Wed Sep 16 23:46:06 2009 +0200 @@ -0,0 +1,12 @@ +#!/bin/sh + +"$TESTDIR/hghave" rst2html || exit 80 +RST2HTML=$(which rst2html 2> /dev/null || which rst2html.py) + +echo "checking for syntax errors in gendoc.py" +python $TESTDIR/../doc/gendoc.py > gendoc.txt || exit + +# We run rst2html over the file without adding "--halt warning" to +# make it report all errors instead of stopping on the first one. +echo "checking for parse errors with rst2html" +$RST2HTML gendoc.txt /dev/null
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-gendoc.out Wed Sep 16 23:46:06 2009 +0200 @@ -0,0 +1,2 @@ +checking for syntax errors in gendoc.py +checking for parse errors with rst2html
--- a/tests/test-grep Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-grep Wed Sep 16 23:46:06 2009 +0200 @@ -22,14 +22,14 @@ echo % simple hg grep port port echo % all -hg grep --all -nu port port +hg grep --traceback --all -nu port port echo % other hg grep import port hg cp port port2 hg commit -m 4 -u spam -d '5 0' -echo '% follow' -hg grep -f 'import$' port2 +echo % follow +hg grep --traceback -f 'import$' port2 echo deport >> port2 hg commit -m 5 -u eggs -d '6 0' hg grep -f --all -nu port port2
--- a/tests/test-hgwebdir Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-hgwebdir Wed Sep 16 23:46:06 2009 +0200 @@ -29,6 +29,7 @@ root=`pwd` cd .. + cat > paths.conf <<EOF [paths] a=$root/a @@ -50,6 +51,7 @@ echo % should give a 404 - repo is not published "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/c/file/tip/c?style=raw' + cat > paths.conf <<EOF [paths] t/a/=$root/a @@ -83,6 +85,24 @@ "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/b/d/file/tip/d?style=raw' +"$TESTDIR/killdaemons.py" +cat > paths.conf <<EOF +[paths] +t/a = $root/a +t/b = $root/b +c = $root/c +[web] +descend=false +EOF + +hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \ + -A access-paths.log -E error-paths-3.log +cat hg.pid >> $DAEMON_PIDS +echo % test descend = False +"$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=raw' +"$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=raw' + + cat > collections.conf <<EOF [collections] $root=$root @@ -99,9 +119,12 @@ "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/b/file/tip/b?style=raw' "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/c/file/tip/c?style=raw' + echo % paths errors 1 cat error-paths-1.log echo % paths errors 2 cat error-paths-2.log +echo % paths errors 3 +cat error-paths-3.log echo % collections errors cat error-collections.log
--- a/tests/test-hgwebdir.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-hgwebdir.out Wed Sep 16 23:46:06 2009 +0200 @@ -307,6 +307,18 @@ 200 Script output follows d +% test descend = False +200 Script output follows + + +/c/ + +200 Script output follows + + +/t/a/ +/t/b/ + % collections: should succeed 200 Script output follows @@ -327,4 +339,5 @@ c % paths errors 1 % paths errors 2 +% paths errors 3 % collections errors
--- a/tests/test-highlight Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-highlight Wed Sep 16 23:46:06 2009 +0200 @@ -47,9 +47,6 @@ print "The first %d primes: %s" % (n, list(islice(p, n))) EOF -# check for UnicodeDecodeError with iso-8859-1 file contents -python -c 'fp = open("isolatin.txt", "w"); fp.write("h\xFCbsch\n"); fp.close();' - hg ci -Ama echo % hg serve @@ -60,10 +57,6 @@ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/primes.py') \ | sed "s/class=\"k\"/class=\"kn\"/g" | sed "s/class=\"mf\"/class=\"mi\"/g" -echo % hgweb filerevision, html -("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/isolatin.txt') \ - | sed "s/class=\"k\"/class=\"kn\"/g" - echo % hgweb fileannotate, html ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/annotate/tip/primes.py') \ | sed "s/class=\"k\"/class=\"kn\"/g" | sed "s/class=\"mi\"/class=\"mf\"/g" @@ -121,3 +114,28 @@ echo % errors encountered cat errors.log + +cd .. +hg init eucjp +cd eucjp + +printf '\265\376\n' >> eucjp.txt # Japanese kanji "Kyo" + +hg ci -Ama + +hgserveget () { + "$TESTDIR/killdaemons.py" + echo % HGENCODING="$1" hg serve + HGENCODING="$1" hg serve -p $HGPORT -d -n test --pid-file=hg.pid -E errors.log + cat hg.pid >> $DAEMON_PIDS + + echo % hgweb filerevision, html + "$TESTDIR/get-with-headers.py" localhost:$HGPORT "/file/tip/$2" \ + | grep '<div class="parity0 source">' | $TESTDIR/printrepr.py + echo % errors encountered + cat errors.log +} + +hgserveget euc-jp eucjp.txt +hgserveget utf-8 eucjp.txt +hgserveget us-ascii eucjp.txt
--- a/tests/test-highlight.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-highlight.out Wed Sep 16 23:46:06 2009 +0200 @@ -1,4 +1,3 @@ -adding isolatin.txt adding primes.py % hg serve % hgweb filerevision, html @@ -12,7 +11,7 @@ <link rel="stylesheet" href="/static/style-paper.css" type="text/css" /> <link rel="stylesheet" href="/highlightcss" type="text/css" /> -<title>test: 3e1445510fe7 primes.py</title> +<title>test: 853dcd4de2a6 primes.py</title> </head> <body> @@ -23,27 +22,27 @@ <img src="/static/hglogo.png" alt="mercurial" /></a> </div> <ul> -<li><a href="/shortlog/3e1445510fe7">log</a></li> -<li><a href="/graph/3e1445510fe7">graph</a></li> +<li><a href="/shortlog/853dcd4de2a6">log</a></li> +<li><a href="/graph/853dcd4de2a6">graph</a></li> <li><a href="/tags">tags</a></li> <li><a href="/branches">branches</a></li> </ul> <ul> -<li><a href="/rev/3e1445510fe7">changeset</a></li> -<li><a href="/file/3e1445510fe7/">browse</a></li> +<li><a href="/rev/853dcd4de2a6">changeset</a></li> +<li><a href="/file/853dcd4de2a6/">browse</a></li> </ul> <ul> <li class="active">file</li> -<li><a href="/diff/3e1445510fe7/primes.py">diff</a></li> -<li><a href="/annotate/3e1445510fe7/primes.py">annotate</a></li> -<li><a href="/log/3e1445510fe7/primes.py">file log</a></li> -<li><a href="/raw-file/3e1445510fe7/primes.py">raw</a></li> +<li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li> +<li><a href="/annotate/853dcd4de2a6/primes.py">annotate</a></li> +<li><a href="/log/853dcd4de2a6/primes.py">file log</a></li> +<li><a href="/raw-file/853dcd4de2a6/primes.py">raw</a></li> </ul> </div> <div class="main"> <h2><a href="/">test</a></h2> -<h3>view primes.py @ 0:3e1445510fe7</h3> +<h3>view primes.py @ 0:853dcd4de2a6</h3> <form class="search" action="/log"> @@ -119,93 +118,6 @@ </body> </html> -% hgweb filerevision, html -200 Script output follows - -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"> -<head> -<link rel="icon" href="/static/hgicon.png" type="image/png" /> -<meta name="robots" content="index, nofollow" /> -<link rel="stylesheet" href="/static/style-paper.css" type="text/css" /> - -<link rel="stylesheet" href="/highlightcss" type="text/css" /> -<title>test: 3e1445510fe7 isolatin.txt</title> -</head> -<body> - -<div class="container"> -<div class="menu"> -<div class="logo"> -<a href="http://mercurial.selenic.com/"> -<img src="/static/hglogo.png" alt="mercurial" /></a> -</div> -<ul> -<li><a href="/shortlog/3e1445510fe7">log</a></li> -<li><a href="/graph/3e1445510fe7">graph</a></li> -<li><a href="/tags">tags</a></li> -<li><a href="/branches">branches</a></li> -</ul> -<ul> -<li><a href="/rev/3e1445510fe7">changeset</a></li> -<li><a href="/file/3e1445510fe7/">browse</a></li> -</ul> -<ul> -<li class="active">file</li> -<li><a href="/diff/3e1445510fe7/isolatin.txt">diff</a></li> -<li><a href="/annotate/3e1445510fe7/isolatin.txt">annotate</a></li> -<li><a href="/log/3e1445510fe7/isolatin.txt">file log</a></li> -<li><a href="/raw-file/3e1445510fe7/isolatin.txt">raw</a></li> -</ul> -</div> - -<div class="main"> -<h2><a href="/">test</a></h2> -<h3>view isolatin.txt @ 0:3e1445510fe7</h3> - -<form class="search" action="/log"> - -<p><input name="rev" id="search1" type="text" size="30" /></p> -<div id="hint">find changesets by author, revision, -files, or words in the commit message</div> -</form> - -<div class="description">a</div> - -<table id="changesetEntry"> -<tr> - <th class="author">author</th> - <td class="author">test</td> -</tr> -<tr> - <th class="date">date</th> - <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td> -</tr> -<tr> - <th class="author">parents</th> - <td class="author"></td> -</tr> -<tr> - <th class="author">children</th> - <td class="author"></td> -</tr> - -</table> - -<div class="overflow"> -<div class="sourcefirst"> line source</div> - -<div class="parity0 source"><a href="#l1" id="l1"> 1</a> h?bsch</div> -<div class="sourcelast"></div> -</div> -</div> -</div> - - - -</body> -</html> - % hgweb fileannotate, html 200 Script output follows @@ -228,28 +140,28 @@ <img src="/static/hglogo.png" alt="mercurial" /></a> </div> <ul> -<li><a href="/shortlog/3e1445510fe7">log</a></li> -<li><a href="/graph/3e1445510fe7">graph</a></li> +<li><a href="/shortlog/853dcd4de2a6">log</a></li> +<li><a href="/graph/853dcd4de2a6">graph</a></li> <li><a href="/tags">tags</a></li> <li><a href="/branches">branches</a></li> </ul> <ul> -<li><a href="/rev/3e1445510fe7">changeset</a></li> -<li><a href="/file/3e1445510fe7/">browse</a></li> +<li><a href="/rev/853dcd4de2a6">changeset</a></li> +<li><a href="/file/853dcd4de2a6/">browse</a></li> </ul> <ul> -<li><a href="/file/3e1445510fe7/primes.py">file</a></li> -<li><a href="/diff/3e1445510fe7/primes.py">diff</a></li> +<li><a href="/file/853dcd4de2a6/primes.py">file</a></li> +<li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li> <li class="active">annotate</li> -<li><a href="/log/3e1445510fe7/primes.py">file log</a></li> -<li><a href="/raw-annotate/3e1445510fe7/primes.py">raw</a></li> +<li><a href="/log/853dcd4de2a6/primes.py">file log</a></li> +<li><a href="/raw-annotate/853dcd4de2a6/primes.py">raw</a></li> </ul> </div> <div class="main"> <h2><a href="/">test</a></h2> -<h3>annotate primes.py @ 0:3e1445510fe7</h3> +<h3>annotate primes.py @ 0:853dcd4de2a6</h3> <form class="search" action="/log"> @@ -289,225 +201,225 @@ <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#1" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#1" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l1" id="l1"> 1</a> <span class="c">#!/usr/bin/env python</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#2" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#2" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l2" id="l2"> 2</a> </td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#3" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#3" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l3" id="l3"> 3</a> <span class="sd">"""Fun with generators. Corresponding Haskell implementation:</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#4" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#4" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l4" id="l4"> 4</a> </td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#5" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#5" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l5" id="l5"> 5</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#6" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#6" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l6" id="l6"> 6</a> <span class="sd"> where sieve (p:ns) = p : sieve [n | n <- ns, mod n p /= 0]</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#7" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#7" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l7" id="l7"> 7</a> <span class="sd">"""</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#8" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#8" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l8" id="l8"> 8</a> </td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#9" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#9" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l9" id="l9"> 9</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#10" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#10" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l10" id="l10"> 10</a> </td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#11" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#11" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l11" id="l11"> 11</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#12" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#12" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l12" id="l12"> 12</a> <span class="sd">"""Generate all primes."""</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#13" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#13" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l13" id="l13"> 13</a> <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#14" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#14" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l14" id="l14"> 14</a> <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#15" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#15" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l15" id="l15"> 15</a> <span class="c"># It is important to yield *here* in order to stop the</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#16" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#16" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l16" id="l16"> 16</a> <span class="c"># infinite recursion.</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#17" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#17" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l17" id="l17"> 17</a> <span class="kn">yield</span> <span class="n">p</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#18" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#18" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l18" id="l18"> 18</a> <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#19" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#19" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l19" id="l19"> 19</a> <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#20" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#20" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l20" id="l20"> 20</a> <span class="kn">yield</span> <span class="n">n</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#21" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#21" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l21" id="l21"> 21</a> </td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#22" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#22" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l22" id="l22"> 22</a> <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mf">2</span> <span class="o">==</span> <span class="mf">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#23" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#23" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l23" id="l23"> 23</a> <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mf">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o"><</span> <span class="mf">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#24" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#24" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l24" id="l24"> 24</a> </td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#25" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#25" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l25" id="l25"> 25</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#26" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#26" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l26" id="l26"> 26</a> <span class="kn">import</span> <span class="nn">sys</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#27" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#27" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l27" id="l27"> 27</a> <span class="kn">try</span><span class="p">:</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#28" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#28" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l28" id="l28"> 28</a> <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#29" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#29" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l29" id="l29"> 29</a> <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#30" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#30" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l30" id="l30"> 30</a> <span class="n">n</span> <span class="o">=</span> <span class="mf">10</span></td> </tr> <tr class="parity0"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#31" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#31" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l31" id="l31"> 31</a> <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></td> </tr> <tr class="parity1"> <td class="annotate"> -<a href="/annotate/3e1445510fe7/primes.py#32" -title="3e1445510fe7: a">test@0</a> +<a href="/annotate/853dcd4de2a6/primes.py#32" +title="853dcd4de2a6: a">test@0</a> </td> <td class="source"><a href="#l32" id="l32"> 32</a> <span class="kn">print</span> <span class="s">"The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></td> </tr> @@ -538,3 +450,16 @@ /* pygments_style = fruity */ % errors encountered +adding eucjp.txt +% HGENCODING=euc-jp hg serve +% hgweb filerevision, html +<div class="parity0 source"><a href="#l1" id="l1"> 1</a> \xb5\xfe</div> +% errors encountered +% HGENCODING=utf-8 hg serve +% hgweb filerevision, html +<div class="parity0 source"><a href="#l1" id="l1"> 1</a> \xef\xbf\xbd\xef\xbf\xbd</div> +% errors encountered +% HGENCODING=us-ascii hg serve +% hgweb filerevision, html +<div class="parity0 source"><a href="#l1" id="l1"> 1</a> ??</div> +% errors encountered
--- a/tests/test-hook.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-hook.out Wed Sep 16 23:46:06 2009 +0200 @@ -1,18 +1,18 @@ precommit hook: HG_PARENT1=0000000000000000000000000000000000000000 -pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=true +pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$HGTMP/test-hook/a 0:29b62aeb769f commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 updating working directory 1 files updated, 0 files merged, 0 files removed, 0 files unresolved precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b -pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=true +pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a 1:b702efe96888 commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b 1 files updated, 0 files merged, 0 files removed, 0 files unresolved precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b -pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=true +pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a 2:1324a5531bac commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b @@ -20,7 +20,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 -pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=true +pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=$HGTMP/test-hook/a 3:4c52fb2e4022 commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 @@ -43,7 +43,7 @@ (run 'hg update' to get a working copy) pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 -pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=true +pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=$HGTMP/test-hook/a 4:8ea2ef7ad3e8 commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 @@ -58,10 +58,10 @@ abort: pretag.forbid hook exited with status 1 4:8ea2ef7ad3e8 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 -pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true +pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a 5:fad284daf8c0 5:fad284daf8c0 -pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true +pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a transaction abort! rollback completed abort: pretxncommit.forbid1 hook exited with status 1 @@ -81,7 +81,7 @@ searching for changes abort: prechangegroup.forbid hook exited with status 1 4:8ea2ef7ad3e8 -pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=true HG_SOURCE=pull HG_URL=file: +pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/b HG_SOURCE=pull HG_URL=file: pulling from ../a searching for changes adding changesets
--- a/tests/test-log Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-log Wed Sep 16 23:46:06 2009 +0200 @@ -104,6 +104,12 @@ echo '% log -r <some unknown node id>' hg log -r 1000000000000000000000000000000000000000 +echo '% log -k r1' +hg log -k r1 + +echo '% log -d -1' +hg log -d -1 + cd .. hg init usertest
--- a/tests/test-log.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-log.out Wed Sep 16 23:46:06 2009 +0200 @@ -239,6 +239,13 @@ abort: 00changelog.i@: ambiguous identifier! % log -r <some unknown node id> abort: unknown revision '1000000000000000000000000000000000000000'! +% log -k r1 +changeset: 1:3d5bf5654eda +user: test +date: Thu Jan 01 00:00:01 1970 +0000 +summary: r1 + +% log -d -1 adding a adding b changeset: 0:29a4c94f1924
--- a/tests/test-merge-default.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-merge-default.out Wed Sep 16 23:46:06 2009 +0200 @@ -13,11 +13,6 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) % should succeed - 2 heads -changeset: 1:ba677d0156c1 -user: test -date: Thu Jan 01 00:00:00 1970 +0000 -summary: b - changeset: 3:903c264cdf57 parent: 1:ba677d0156c1 user: test
--- a/tests/test-merge1.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-merge1.out Wed Sep 16 23:46:06 2009 +0200 @@ -1,11 +1,6 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved created new head %% no merges expected -changeset: 0:98e00378acd0 -user: test -date: Mon Jan 12 13:46:40 1970 +0000 -summary: commit #0 - changeset: 1:4ee19afe4659 user: test date: Mon Jan 12 13:46:40 1970 +0000
--- a/tests/test-mq Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-mq Wed Sep 16 23:46:06 2009 +0200 @@ -155,18 +155,13 @@ echo % qtop hg qtop -echo % qprev -hg qprev - -echo % qnext -hg qnext +echo % prev +hg qapp -1 -echo % pop, qnext, qprev, qapplied +echo % next +hg qunapp -1 + hg qpop -hg qnext -hg qprev -hg qapplied - echo % commit should fail hg commit @@ -197,6 +192,42 @@ hg qpop test2.patch-2 hg qpush test1b.patch+1 +echo % pop, qapplied, qunapplied +hg qseries -v +echo % qapplied -1 test.patch +hg qapplied -1 test.patch +echo % qapplied -1 test1b.patch +hg qapplied -1 test1b.patch +echo % qapplied -1 test2.patch +hg qapplied -1 test2.patch +echo % qapplied -1 +hg qapplied -1 +echo % qapplied +hg qapplied +echo % qapplied test1b.patch +hg qapplied test1b.patch +echo % qunapplied -1 +hg qunapplied -1 +echo % qunapplied +hg qunapplied +echo % popping +hg qpop +echo % qunapplied -1 +hg qunapplied -1 +echo % qunapplied +hg qunapplied +echo % qunapplied test2.patch +hg qunapplied test2.patch +echo % qunapplied -1 test2.patch +hg qunapplied -1 test2.patch +echo % popping -a +hg qpop -a +echo % qapplied +hg qapplied +echo % qapplied -1 +hg qapplied -1 +hg qpush + echo % push should succeed hg qpop -a hg push ../../k
--- a/tests/test-mq.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-mq.out Wed Sep 16 23:46:06 2009 +0200 @@ -16,7 +16,6 @@ print patch series qseries print applied patches qapplied - print name of top applied patch qtop add known patch to applied stack qpush remove patch from applied stack qpop @@ -146,16 +145,12 @@ test2.patch % qtop test2.patch -% qprev +% prev test.patch -% qnext +% next all patches applied -% pop, qnext, qprev, qapplied popping test2.patch now at: test.patch -test2.patch -only one patch applied -test.patch % commit should fail abort: cannot commit over an applied mq patch % push should fail @@ -182,11 +177,50 @@ applying test1b.patch applying test2.patch now at: test2.patch -% push should succeed +% pop, qapplied, qunapplied +0 A test.patch +1 A test1b.patch +2 A test2.patch +% qapplied -1 test.patch +only one patch applied +% qapplied -1 test1b.patch +test.patch +% qapplied -1 test2.patch +test1b.patch +% qapplied -1 +test1b.patch +% qapplied +test.patch +test1b.patch +test2.patch +% qapplied test1b.patch +test.patch +test1b.patch +% qunapplied -1 +all patches applied +% qunapplied +% popping popping test2.patch +now at: test1b.patch +% qunapplied -1 +test2.patch +% qunapplied +test2.patch +% qunapplied test2.patch +% qunapplied -1 test2.patch +all patches applied +% popping -a popping test1b.patch popping test.patch patch queue now empty +% qapplied +% qapplied -1 +no patches applied +applying test.patch +now at: test.patch +% push should succeed +popping test.patch +patch queue now empty pushing to ../../k searching for changes adding changesets
--- a/tests/test-patchbomb Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-patchbomb Wed Sep 16 23:46:06 2009 +0200 @@ -151,3 +151,19 @@ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar --in-reply-to baz \ -r 0:1 | fixheaders + +echo "% test single flag for single patch" +hg email --date '1970-1-1 0:1' -n --flag fooFlag -f quux -t foo -c bar -s test \ + -r 2 | fixheaders + +echo "% test single flag for multiple patches" +hg email --date '1970-1-1 0:1' -n --flag fooFlag -f quux -t foo -c bar -s test \ + -r 0:1 | fixheaders + +echo "% test mutiple flags for single patch" +hg email --date '1970-1-1 0:1' -n --flag fooFlag --flag barFlag -f quux -t foo \ + -c bar -s test -r 2 | fixheaders + +echo "% test multiple flags for multiple patches" +hg email --date '1970-1-1 0:1' -n --flag fooFlag --flag barFlag -f quux -t foo \ + -c bar -s test -r 0:1 | fixheaders
--- a/tests/test-patchbomb.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-patchbomb.out Wed Sep 16 23:46:06 2009 +0200 @@ -1254,3 +1254,215 @@ @@ -0,0 +1,1 @@ +b +% test single flag for single patch +This patch series consists of 1 patches. + + +Displaying [PATCH fooFlag] test ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH fooFlag] test +X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f +Message-Id: <ff2c9fa2018b15fa74b3.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:00 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 3 0 +# Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f +# Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +c + +diff -r 97d72e5f12c7 -r ff2c9fa2018b c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/c Thu Jan 01 00:00:03 1970 +0000 +@@ -0,0 +1,1 @@ ++c + +% test single flag for multiple patches +This patch series consists of 2 patches. + + +Write the introductory message for the patch series. + + +Displaying [PATCH 0 of 2 fooFlag] test ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 0 of 2 fooFlag] test +Message-Id: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:00 +0000 +From: quux +To: foo +Cc: bar + + +Displaying [PATCH 1 of 2 fooFlag] a ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 1 of 2 fooFlag] a +X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab +Message-Id: <8580ff50825a50c8f716.61@ +In-Reply-To: <patchbomb.60@ +References: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:01 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 1 0 +# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab +# Parent 0000000000000000000000000000000000000000 +a + +diff -r 000000000000 -r 8580ff50825a a +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/a Thu Jan 01 00:00:01 1970 +0000 +@@ -0,0 +1,1 @@ ++a + +Displaying [PATCH 2 of 2 fooFlag] b ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 2 of 2 fooFlag] b +X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +Message-Id: <97d72e5f12c7e84f8506.62@ +In-Reply-To: <patchbomb.60@ +References: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:02 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 2 0 +# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +# Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab +b + +diff -r 8580ff50825a -r 97d72e5f12c7 b +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/b Thu Jan 01 00:00:02 1970 +0000 +@@ -0,0 +1,1 @@ ++b + +% test mutiple flags for single patch +This patch series consists of 1 patches. + + +Displaying [PATCH fooFlag barFlag] test ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH fooFlag barFlag] test +X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f +Message-Id: <ff2c9fa2018b15fa74b3.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:00 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 3 0 +# Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f +# Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +c + +diff -r 97d72e5f12c7 -r ff2c9fa2018b c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/c Thu Jan 01 00:00:03 1970 +0000 +@@ -0,0 +1,1 @@ ++c + +% test multiple flags for multiple patches +This patch series consists of 2 patches. + + +Write the introductory message for the patch series. + + +Displaying [PATCH 0 of 2 fooFlag barFlag] test ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 0 of 2 fooFlag barFlag] test +Message-Id: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:00 +0000 +From: quux +To: foo +Cc: bar + + +Displaying [PATCH 1 of 2 fooFlag barFlag] a ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 1 of 2 fooFlag barFlag] a +X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab +Message-Id: <8580ff50825a50c8f716.61@ +In-Reply-To: <patchbomb.60@ +References: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:01 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 1 0 +# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab +# Parent 0000000000000000000000000000000000000000 +a + +diff -r 000000000000 -r 8580ff50825a a +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/a Thu Jan 01 00:00:01 1970 +0000 +@@ -0,0 +1,1 @@ ++a + +Displaying [PATCH 2 of 2 fooFlag barFlag] b ... +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH 2 of 2 fooFlag barFlag] b +X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +Message-Id: <97d72e5f12c7e84f8506.62@ +In-Reply-To: <patchbomb.60@ +References: <patchbomb.60@ +User-Agent: Mercurial-patchbomb +Date: Thu, 01 Jan 1970 00:01:02 +0000 +From: quux +To: foo +Cc: bar + +# HG changeset patch +# User test +# Date 2 0 +# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9 +# Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab +b + +diff -r 8580ff50825a -r 97d72e5f12c7 b +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/b Thu Jan 01 00:00:02 1970 +0000 +@@ -0,0 +1,1 @@ ++b +
--- a/tests/test-tags Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-tags Wed Sep 16 23:46:06 2009 +0200 @@ -37,9 +37,17 @@ hg identify # repeat with cold tag cache +echo "% identify with cold cache" rm -f .hg/tags.cache hg identify +# and again, but now unable to write tag cache +echo "% identify with unwritable cache" +rm -f .hg/tags.cache +chmod 555 .hg +hg identify +chmod 755 .hg + echo "% create a branch" echo bb > a hg status
--- a/tests/test-tags.out Wed Sep 16 16:11:44 2009 +0200 +++ b/tests/test-tags.out Wed Sep 16 23:46:06 2009 +0200 @@ -13,6 +13,9 @@ tip 1:b9154636be93 first 0:acb14030fe0a b9154636be93 tip +% identify with cold cache +b9154636be93 tip +% identify with unwritable cache b9154636be93 tip % create a branch M a