Mercurial > hgbook
changeset 679:80928ea6e7ae
Add the ability to include text files and have them XML-mangled.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Tue, 17 Mar 2009 21:47:12 -0700 |
parents | cd978765da64 |
children | 8366882f67f2 |
files | en/ch02-tour-basic.xml en/ch03-tour-merge.xml en/ch06-collab.xml en/examples/auto-snippets.xml en/examples/ch06/apache-config.lst en/examples/run-example |
diffstat | 6 files changed, 138 insertions(+), 93 deletions(-) [+] |
line wrap: on
line diff
--- a/en/ch02-tour-basic.xml Tue Mar 10 22:40:47 2009 -0700 +++ b/en/ch02-tour-basic.xml Tue Mar 17 21:47:12 2009 -0700 @@ -30,21 +30,17 @@ <itemizedlist> <listitem><para>Debian:</para> - <programlisting>apt-get install - mercurial</programlisting></listitem> + <programlisting>apt-get install mercurial</programlisting></listitem> <listitem><para>Fedora Core:</para> - <programlisting>yum install - mercurial</programlisting></listitem> + <programlisting>yum install mercurial</programlisting></listitem> <listitem><para>Gentoo:</para> <programlisting>emerge mercurial</programlisting></listitem> <listitem><para>OpenSUSE:</para> - <programlisting>yum install - mercurial</programlisting></listitem> + <programlisting>yum install mercurial</programlisting></listitem> <listitem><para>Ubuntu: Ubuntu's Mercurial package is based on Debian's. To install it, run the following command.</para> - <programlisting>apt-get install - mercurial</programlisting></listitem> + <programlisting>apt-get install mercurial</programlisting></listitem> </itemizedlist> </sect2> @@ -554,7 +550,8 @@ <filename role="special">.hgrc</filename> should look like this.</para> <programlisting># This is a Mercurial configuration file. -[ui] username = Firstname Lastname +[ui] +username = Firstname Lastname <email.address@domain.net></programlisting> <para>The <quote><literal>[ui]</literal></quote> line begins a @@ -626,8 +623,8 @@ <programlisting> changeset: 73:584af0e231be -user: Censored Person <censored.person@example.org> -date: Tue Sep 26 21:37:07 2006 -0700 +user: Censored Person <censored.person@example.org> +date: Tue Sep 26 21:37:07 2006 -0700 summary: include buildmeister/commondefs. Add exports.</programlisting> <para>As far as the remainder of the contents of the
--- a/en/ch03-tour-merge.xml Tue Mar 10 22:40:47 2009 -0700 +++ b/en/ch03-tour-merge.xml Tue Mar 17 21:47:12 2009 -0700 @@ -337,9 +337,9 @@ <para>The process of merging changes as outlined above is straightforward, but requires running three commands in sequence.</para> - <programlisting> - hg pull hg merge hg commit -m 'Merged remote changes' - </programlisting> + <programlisting>hg pull +hg merge +hg commit -m 'Merged remote changes'</programlisting> <para>In the case of the final commit, you also need to enter a commit message, which is almost always going to be a piece of uninteresting <quote>boilerplate</quote> text.</para> @@ -376,9 +376,8 @@ <literal role="rc-extensions">extensions</literal> section. Then add a line that simply reads <quote><literal>fetch </literal></quote>.</para> - <programlisting> - [extensions] fetch = - </programlisting> + <programlisting>[extensions] +fetch =</programlisting> <para>(Normally, on the right-hand side of the <quote><literal>=</literal></quote> would appear the location of the extension, but since the <literal
--- a/en/ch06-collab.xml Tue Mar 10 22:40:47 2009 -0700 +++ b/en/ch06-collab.xml Tue Mar 17 21:47:12 2009 -0700 @@ -536,8 +536,8 @@ </listitem> <listitem><para>The <quote>:22</quote> identifies the port number to connect to the server on. The default port is - 22, so you only need to specify this part if you're - <emphasis>not</emphasis> using port 22.</para> + 22, so you only need to specify a colon and port number if + you're <emphasis>not</emphasis> using port 22.</para> </listitem> <listitem><para>The remainder of the URL is the local path to the repository on the server.</para> @@ -597,8 +597,8 @@ example, if you're using PuTTY, you'll need to use the <command>plink</command> command as a command-line ssh client.</para> - <programlisting>[ui] ssh = C:/path/to/plink.exe -ssh -i - "C:/path/to/my/private/key"</programlisting> + <programlisting>[ui] +ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"</programlisting> <note> <para> The path to <command>plink</command> shouldn't contain @@ -840,15 +840,17 @@ turns on compression. You can easily edit your <filename role="special"> /.hgrc</filename>\ to enable compression for all of Mercurial's uses of the ssh protocol.</para> - <programlisting>[ui] ssh = ssh -C</programlisting> + <programlisting>[ui] +ssh = ssh -C</programlisting> <para>If you use <command>ssh</command>, you can configure it to always use compression when talking to your server. To do this, edit your <filename role="special">.ssh/config</filename> file (which may not yet exist), as follows.</para> - <programlisting>Host hg Compression yes HostName - hg.example.com</programlisting> + <programlisting>Host hg + Compression yes + HostName hg.example.com</programlisting> <para>This defines an alias, <literal>hg</literal>. When you use it on the <command>ssh</command> command line or in a Mercurial <literal>ssh</literal>-protocol URL, it will cause @@ -936,8 +938,8 @@ <para>You'll need to copy this script into your <filename class="directory">public_html</filename> directory, and ensure that it's executable.</para> - <programlisting>cp .../hgweb.cgi ~/public_html chmod 755 - ~/public_html/hgweb.cgi</programlisting> + <programlisting>cp .../hgweb.cgi ~/public_html +chmod 755 ~/public_html/hgweb.cgi</programlisting> <para>The <literal>755</literal> argument to <command>chmod</command> is a little more general than just making the script executable: it ensures that the script is @@ -986,9 +988,9 @@ class="directory">public_html</filename> directory, and read files under the latter too. Here's a quick recipe to help you to make your permissions more appropriate.</para> - <programlisting>chmod 755 ~ find ~/public_html -type d -print0 - | xargs -0r chmod 755 find ~/public_html -type f -print0 | - xargs -0r chmod 644</programlisting> + <programlisting>chmod 755 ~ +find ~/public_html -type d -print0 | xargs -0r chmod 755 +find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting> <para>The other possibility with permissions is that you might get a completely empty window when you try to load the @@ -1001,6 +1003,9 @@ of CGI programs in your per-user web directory. Here's Apache's default per-user configuration from my Fedora system.</para> + + &ch06-apache-config.lst; + <programlisting><Directory /home/*/public_html> AllowOverride FileInfo AuthConfig Limit Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec <Limit GET
--- a/en/examples/auto-snippets.xml Tue Mar 10 22:40:47 2009 -0700 +++ b/en/examples/auto-snippets.xml Tue Mar 17 21:47:12 2009 -0700 @@ -1,3 +1,4 @@ +<!ENTITY ch06-apache-config.lst SYSTEM "results/ch06-apache-config.lst.out"> <!ENTITY interaction.backout.init SYSTEM "results/backout.init.out"> <!ENTITY interaction.backout.manual.backout SYSTEM "results/backout.manual.backout.out"> <!ENTITY interaction.backout.manual.cat SYSTEM "results/backout.manual.cat.out">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/ch06/apache-config.lst Tue Mar 17 21:47:12 2009 -0700 @@ -0,0 +1,11 @@ +<Directory /home/*/public_html> + AllowOverride FileInfo AuthConfig Limit + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + <Limit GET POST OPTIONS> + Order allow,deny + Allow from all + </Limit> + <LimitExcept GET POST OPTIONS> + Order deny,allow Deny from all + </LimitExcept> +</Directory>
--- a/en/examples/run-example Tue Mar 10 22:40:47 2009 -0700 +++ b/en/examples/run-example Tue Mar 17 21:47:12 2009 -0700 @@ -54,10 +54,83 @@ return None def result_name(name): - dirname, basename = os.path.split(name) - return os.path.join(dirname, 'results', basename) + return os.path.join('results', name.replace(os.sep, '-')) class example: + entities = dict.fromkeys(l.rstrip() for l in open('auto-snippets.xml')) + + def __init__(self, name, verbose, keep_change): + self.name = name + self.verbose = verbose + self.keep_change = keep_change + + def rename_output(self, base, ignore=[]): + mangle_re = re.compile('(?:' + '|'.join(ignore) + ')') + def mangle(s): + return mangle_re.sub('', s) + def matchfp(fp1, fp2): + while True: + s1 = mangle(fp1.readline()) + s2 = mangle(fp2.readline()) + if cmp(s1, s2): + break + if not s1: + return True + return False + + oldname = result_name(base + '.out') + tmpname = result_name(base + '.tmp') + errname = result_name(base + '.err') + errfp = open(errname, 'w+') + for line in open(tmpname): + errfp.write(mangle_re.sub('', line)) + os.rename(tmpname, result_name(base + '.lxo')) + errfp.seek(0) + try: + oldfp = open(oldname) + except IOError, err: + if err.errno != errno.ENOENT: + raise + os.rename(errname, oldname) + return False + if matchfp(oldfp, errfp): + os.unlink(errname) + return False + else: + print >> sys.stderr, '\nOutput of %s has changed!' % baseq + if self.keep_change: + os.rename(errname, oldname) + return False + else: + os.system('diff -u %s %s 1>&2' % (oldname, errname)) + return True + +def wopen(name): + path = os.path.dirname(name) + if path: + try: + os.makedirs(path) + except OSError, err: + if err.errno != errno.EEXIST: + raise + return open(name, 'w') + +class static_example(example): + def run(self): + s = open(self.name).read().rstrip() + s = s.replace('&', '&').replace('<', '<').replace('>', '>') + ofp = wopen(result_name(self.name + '.tmp')) + ofp.write('<programlisting>') + ofp.write(s) + ofp.write('</programlisting>\n') + ofp.close() + self.rename_output(self.name) + norm = self.name.replace(os.sep, '-') + example.entities[ + '<!ENTITY %s SYSTEM "results/%s.out">' % (norm, norm)] = 1 + + +class shell_example(example): shell = '/usr/bin/env bash' ps1 = '__run_example_ps1__ ' ps2 = '__run_example_ps2__ ' @@ -65,12 +138,8 @@ timeout = 10 - entities = dict.fromkeys(l.rstrip() for l in open('auto-snippets.xml')) - def __init__(self, name, verbose, keep_change): - self.name = name - self.verbose = verbose - self.keep_change = keep_change + example.__init__(self, name, verbose, keep_change) self.poll = select.poll() def parse(self): @@ -153,12 +222,12 @@ maybe_unlink(self.name + '.run') rcfile = os.path.join(tmpdir, '.hgrc') - rcfp = open(rcfile, 'w') + rcfp = wopen(rcfile) print >> rcfp, '[ui]' print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>" rcfile = os.path.join(tmpdir, '.bashrc') - rcfp = open(rcfile, 'w') + rcfp = wopen(rcfile) print >> rcfp, 'PS1="%s"' % self.ps1 print >> rcfp, 'PS2="%s"' % self.ps2 print >> rcfp, 'unset HISTFILE' @@ -248,8 +317,7 @@ 'SYSTEM "results/%s.out">' % (norm, norm)] = 1 read_hint = ofp_basename + ' ' - ofp = open(result_name(ofp_basename + '.tmp'), - 'w') + ofp = wopen(result_name(ofp_basename + '.tmp')) ofp.write('<screen>') else: ofp = None @@ -297,52 +365,11 @@ elif os.WIFSIGNALED(rc): print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc) else: - open(result_name(self.name + '.run'), 'w') + wopen(result_name(self.name + '.run')) return err finally: shutil.rmtree(tmpdir) - def rename_output(self, base, ignore): - mangle_re = re.compile('(?:' + '|'.join(ignore) + ')') - def mangle(s): - return mangle_re.sub('', s) - def matchfp(fp1, fp2): - while True: - s1 = mangle(fp1.readline()) - s2 = mangle(fp2.readline()) - if cmp(s1, s2): - break - if not s1: - return True - return False - - oldname = result_name(base + '.out') - tmpname = result_name(base + '.tmp') - errname = result_name(base + '.err') - errfp = open(errname, 'w+') - for line in open(tmpname): - errfp.write(mangle_re.sub('', line)) - os.rename(tmpname, result_name(base + '.lxo')) - errfp.seek(0) - try: - oldfp = open(oldname) - except IOError, err: - if err.errno != errno.ENOENT: - raise - os.rename(errname, oldname) - return False - if matchfp(oldfp, errfp): - os.unlink(errname) - return False - else: - print >> sys.stderr, '\nOutput of %s has changed!' % base - if self.keep_change: - os.rename(errname, oldname) - return False - else: - os.system('diff -u %s %s 1>&2' % (oldname, errname)) - return True - def print_help(exit, msg=None): if msg: print >> sys.stderr, 'Error:', msg @@ -383,18 +410,20 @@ print >> sys.stderr, '%s: %s' % (a, err.strerror) errs += 1 continue - if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: - if example(a, verbose, keep_change).run(): - errs += 1 + if stat.S_ISREG(st.st_mode): + if st.st_mode & 0111: + if shell_example(a, verbose, keep_change).run(): + errs += 1 + elif a.endswith('.lst'): + static_example(a, verbose, keep_change).run() else: print >> sys.stderr, '%s: not a file, or not executable' % a errs += 1 elif run_all: - names = os.listdir(path) + names = glob.glob("*") + glob.glob("app*/*") + glob.glob("ch*/*") names.sort() for name in names: - if name == 'run-example' or name.startswith('.'): continue - if name.endswith('~'): continue + if name == 'run-example' or name.endswith('~'): continue pathname = os.path.join(path, name) try: st = os.lstat(pathname) @@ -403,14 +432,17 @@ if err.errno != errno.ENOENT: raise continue - if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: - if example(pathname, verbose, keep_change).run(): - errs += 1 - print >> open(os.path.join(path, '.run'), 'w'), time.asctime() + if stat.S_ISREG(st.st_mode): + if st.st_mode & 0111: + if shell_example(pathname, verbose, keep_change).run(): + errs += 1 + elif pathname.endswith('.lst'): + static_example(pathname, verbose, keep_change).run() + print >> wopen(os.path.join(path, '.run')), time.asctime() else: print_help(1, msg='no test names given, and --all not provided') - fp = open('auto-snippets.xml', 'w') + fp = wopen('auto-snippets.xml') for key in sorted(example.entities.iterkeys()): print >> fp, key fp.close()