hgbook

changeset 6:69d90ab9fd80

Really run example command sequences under a single shell.
Grotesque hackery involved. Bring strong stomachs.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon Jun 26 10:15:49 2006 -0700 (2006-06-26)
parents faa29ca23fc8
children 339e75288632
files en/examples/mq.qinit-help en/examples/run-example
line diff
     1.1 --- a/en/examples/mq.qinit-help	Sun Jun 25 22:44:24 2006 -0700
     1.2 +++ b/en/examples/mq.qinit-help	Mon Jun 26 10:15:49 2006 -0700
     1.3 @@ -1,2 +1,5 @@
     1.4 +echo '[extensions]' >> $HGRC
     1.5 +echo 'hgext.mq =' >> $HGRC
     1.6 +
     1.7  #$ name: help
     1.8  hg help qinit
     2.1 --- a/en/examples/run-example	Sun Jun 25 22:44:24 2006 -0700
     2.2 +++ b/en/examples/run-example	Mon Jun 26 10:15:49 2006 -0700
     2.3 @@ -9,6 +9,7 @@
     2.4  import pty
     2.5  import re
     2.6  import shutil
     2.7 +import signal
     2.8  import sys
     2.9  import tempfile
    2.10  import time
    2.11 @@ -24,6 +25,7 @@
    2.12          
    2.13  class example:
    2.14      shell = '/bin/bash'
    2.15 +    prompt = '__run_example_prompt__\n'
    2.16      pi_re = re.compile('#\$\s*(name):\s*(.*)$')
    2.17      
    2.18      def __init__(self, name):
    2.19 @@ -45,18 +47,50 @@
    2.20          if not s.endswith('\n'):
    2.21              sys.stdout.flush()
    2.22  
    2.23 -    def drain(self, ifp, ofp):
    2.24 +    def send(self, s):
    2.25 +        self.cfp.write(s)
    2.26 +        self.cfp.flush()
    2.27 +
    2.28 +    def receive(self):
    2.29 +        out = cStringIO.StringIO()
    2.30          while True:
    2.31 -            s = ifp.read(4096)
    2.32 -            if not s: break
    2.33 -            if ofp: ofp.write(tex_escape(s))
    2.34 +            s = self.cfp.readline().replace('\r\n', '\n')
    2.35 +            if not s or s == self.prompt:
    2.36 +                break
    2.37 +            out.write(s)
    2.38 +        return out.getvalue()
    2.39          
    2.40 +    def sendreceive(self, s):
    2.41 +        self.send(s)
    2.42 +        r = self.receive()
    2.43 +        if r.startswith(s):
    2.44 +            r = r[len(s):]
    2.45 +        return r
    2.46 +    
    2.47      def run(self):
    2.48          ofp = None
    2.49          basename = os.path.basename(self.name)
    2.50          self.status('running %s ' % basename)
    2.51          tmpdir = tempfile.mkdtemp(prefix=basename)
    2.52 +        rcfile = os.path.join(tmpdir, '.bashrc')
    2.53 +        rcfp = open(rcfile, 'w')
    2.54 +        print >> rcfp, 'PS1="%s"' % self.prompt
    2.55 +        print >> rcfp, 'unset HISTFILE'
    2.56 +        print >> rcfp, 'export LANG=C'
    2.57 +        print >> rcfp, 'export LC_ALL=C'
    2.58 +        print >> rcfp, 'export TZ=GMT'
    2.59 +        print >> rcfp, 'export HGRC="%s/.hgrc"' % tmpdir
    2.60 +        print >> rcfp, 'export HGRCPATH=$HGRC'
    2.61 +        print >> rcfp, 'cd %s' % tmpdir
    2.62 +        rcfp.close()
    2.63 +        pid, fd = pty.fork()
    2.64 +        if pid == 0:
    2.65 +            #os.execl(self.shell, self.shell)
    2.66 +            os.system('/bin/bash --noediting --noprofile --rcfile %s' % rcfile)
    2.67 +            sys.exit(0)
    2.68 +        self.cfp = os.fdopen(fd, 'w+')
    2.69          try:
    2.70 +            self.receive()
    2.71              for hunk in self.parse():
    2.72                  # is this line a processing instruction?
    2.73                  m = self.pi_re.match(hunk)
    2.74 @@ -70,22 +104,30 @@
    2.75                              ofp = open('%s.%s.out' % (self.name, out), 'w')
    2.76                          else:
    2.77                              ofp = None
    2.78 -                else:
    2.79 +                elif hunk.strip():
    2.80                      # it's something we should execute
    2.81 -                    cin, cout = os.popen4('cd %s; %s' % (tmpdir, hunk))
    2.82 -                    cin.close()
    2.83 -                    if ofp:
    2.84 -                        # first, print the command we ran
    2.85 -                        if not hunk.startswith('#'):
    2.86 -                            nl = hunk.endswith('\n')
    2.87 -                            hunk = ('$ \\textbf{%s}' %
    2.88 -                                    tex_escape(hunk.rstrip('\n')))
    2.89 -                            if nl: hunk += '\n'
    2.90 -                        ofp.write(hunk)
    2.91 +                    output = self.sendreceive(hunk)
    2.92 +                    if not ofp:
    2.93 +                        continue
    2.94 +                    # first, print the command we ran
    2.95 +                    if not hunk.startswith('#'):
    2.96 +                        nl = hunk.endswith('\n')
    2.97 +                        hunk = ('$ \\textbf{%s}' %
    2.98 +                                tex_escape(hunk.rstrip('\n')))
    2.99 +                        if nl: hunk += '\n'
   2.100 +                    ofp.write(hunk)
   2.101                      # then its output
   2.102 -                    self.drain(cout, ofp)
   2.103 +                    ofp.write(output)
   2.104              self.status('\n')
   2.105          finally:
   2.106 +            try:
   2.107 +                output = self.sendreceive('exit\n')
   2.108 +                if ofp:
   2.109 +                    ofp.write(output)
   2.110 +                self.cfp.close()
   2.111 +            except IOError:
   2.112 +                pass
   2.113 +            os.kill(pid, signal.SIGTERM)
   2.114              os.wait()
   2.115              shutil.rmtree(tmpdir)
   2.116