# HG changeset patch # User Bryan O'Sullivan # Date 1237351632 25200 # Node ID 80928ea6e7ae18a71a0a63f633b49fb43bbefd89 # Parent cd978765da64cd6dcf46254134e8179b54dd66de Add the ability to include text files and have them XML-mangled. diff -r cd978765da64 -r 80928ea6e7ae en/ch02-tour-basic.xml --- 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 @@ Debian: - apt-get install - mercurial + apt-get install mercurial Fedora Core: - yum install - mercurial + yum install mercurial Gentoo: emerge mercurial OpenSUSE: - yum install - mercurial + yum install mercurial Ubuntu: Ubuntu's Mercurial package is based on Debian's. To install it, run the following command. - apt-get install - mercurial + apt-get install mercurial @@ -554,7 +550,8 @@ .hgrc should look like this. # This is a Mercurial configuration file. -[ui] username = Firstname Lastname +[ui] +username = Firstname Lastname <email.address@domain.net> The [ui] line begins a @@ -626,8 +623,8 @@ 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. As far as the remainder of the contents of the diff -r cd978765da64 -r 80928ea6e7ae en/ch03-tour-merge.xml --- 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 @@ The process of merging changes as outlined above is straightforward, but requires running three commands in sequence. - - hg pull hg merge hg commit -m 'Merged remote changes' - + hg pull +hg merge +hg commit -m 'Merged remote changes' 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 boilerplate text. @@ -376,9 +376,8 @@ extensions section. Then add a line that simply reads fetch . - - [extensions] fetch = - + [extensions] +fetch = (Normally, on the right-hand side of the = would appear the location of the extension, but since the The :22 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 - not using port 22. + 22, so you only need to specify a colon and port number if + you're not using port 22. The remainder of the URL is the local path to the repository on the server. @@ -597,8 +597,8 @@ example, if you're using PuTTY, you'll need to use the plink command as a command-line ssh client. - [ui] ssh = C:/path/to/plink.exe -ssh -i - "C:/path/to/my/private/key" + [ui] +ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key" The path to plink shouldn't contain @@ -840,15 +840,17 @@ turns on compression. You can easily edit your /.hgrc\ to enable compression for all of Mercurial's uses of the ssh protocol. - [ui] ssh = ssh -C + [ui] +ssh = ssh -C If you use ssh, you can configure it to always use compression when talking to your server. To do this, edit your .ssh/config file (which may not yet exist), as follows. - Host hg Compression yes HostName - hg.example.com + Host hg + Compression yes + HostName hg.example.com This defines an alias, hg. When you use it on the ssh command line or in a Mercurial ssh-protocol URL, it will cause @@ -936,8 +938,8 @@ You'll need to copy this script into your public_html directory, and ensure that it's executable. - cp .../hgweb.cgi ~/public_html chmod 755 - ~/public_html/hgweb.cgi + cp .../hgweb.cgi ~/public_html +chmod 755 ~/public_html/hgweb.cgi The 755 argument to chmod 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 directory, and read files under the latter too. Here's a quick recipe to help you to make your permissions more appropriate. - chmod 755 ~ find ~/public_html -type d -print0 - | xargs -0r chmod 755 find ~/public_html -type f -print0 | - xargs -0r chmod 644 + chmod 755 ~ +find ~/public_html -type d -print0 | xargs -0r chmod 755 +find ~/public_html -type f -print0 | xargs -0r chmod 644 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. + + &ch06-apache-config.lst; + <Directory /home/*/public_html> AllowOverride FileInfo AuthConfig Limit Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec <Limit GET diff -r cd978765da64 -r 80928ea6e7ae en/examples/auto-snippets.xml --- 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 @@ + diff -r cd978765da64 -r 80928ea6e7ae en/examples/ch06/apache-config.lst --- /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 @@ + + AllowOverride FileInfo AuthConfig Limit + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + + Order allow,deny + Allow from all + + + Order deny,allow Deny from all + + diff -r cd978765da64 -r 80928ea6e7ae en/examples/run-example --- 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('') + ofp.write(s) + ofp.write('\n') + ofp.close() + self.rename_output(self.name) + norm = self.name.replace(os.sep, '-') + example.entities[ + '' % (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 " 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('') 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()