" " -> "\t"
authorFabian Groffen <grobian@gentoo.org>
Tue, 10 Apr 2007 15:34:22 +0000 (15:34 -0000)
committerFabian Groffen <grobian@gentoo.org>
Tue, 10 Apr 2007 15:34:22 +0000 (15:34 -0000)
Mixing them in Python is asking for trouble.  In fact, even Python
didn't know what to do with this file anymore.

svn path=/main/branches/prefix/; revision=6365

bin/dispatch-conf

index 2c9f25446ac4feaef34a0ba5811906611180a0df..c4ef6d4953a0902f4db113763291b187a805d73b 100755 (executable)
@@ -19,350 +19,350 @@ from stat import *
 from random import *
 import atexit, commands, os, re, shutil, stat, sys
 try:
-    import portage
+       import portage
 except ImportError:
        from os import path as osp
        sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
-    import portage
+       import portage
 
 import dispatch_conf, portage_const
 from portage.process import find_binary
 
 FIND_EXTANT_CONFIGS  = "find '%s' %s -iname '._cfg????_%s' ! -iname '.*~' ! -iname '.*.bak'"
-DIFF_CONTENTS        = 'diff -Nu %s %s'
-DIFF_CVS_INTERP      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"'
-DIFF_WSCOMMENTS      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"'
+DIFF_CONTENTS          = 'diff -Nu %s %s'
+DIFF_CVS_INTERP          = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"'
+DIFF_WSCOMMENTS          = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"'
 
 # We need a secure scratch dir and python does silly verbose errors on the use of tempnam
 oldmask = os.umask(0077)
 SCRATCH_DIR = None
 while SCRATCH_DIR is None:
-    try:
-        mydir = portage_const.EPREFIX+"/var/tmp/dispatch-conf."
-        for x in range(0,8):
-            if int(random() * 3) == 0:
-                mydir += chr(int(65+random()*26.0))
-            elif int(random() * 2) == 0:
-                mydir += chr(int(97+random()*26.0))
-            else:
-                mydir += chr(int(48+random()*10.0))
-        if os.path.exists(mydir):
-            continue
-        os.mkdir(mydir)
-        SCRATCH_DIR = mydir
-    except OSError, e:
-        if e.errno != 17:
-            raise
+       try:
+               mydir = portage_const.EPREFIX+"/var/tmp/dispatch-conf."
+               for x in range(0,8):
+                       if int(random() * 3) == 0:
+                               mydir += chr(int(65+random()*26.0))
+                       elif int(random() * 2) == 0:
+                               mydir += chr(int(97+random()*26.0))
+                       else:
+                               mydir += chr(int(48+random()*10.0))
+               if os.path.exists(mydir):
+                       continue
+               os.mkdir(mydir)
+               SCRATCH_DIR = mydir
+       except OSError, e:
+               if e.errno != 17:
+                       raise
 os.umask(oldmask)
 
 # Ensure the scratch dir is deleted
 def cleanup(mydir=SCRATCH_DIR):
-    shutil.rmtree(mydir)
+       shutil.rmtree(mydir)
 atexit.register(cleanup)
 
 MANDATORY_OPTS  = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]
 
 class dispatch:
-    options = {}
-
-    def grind (self, config_paths):
-        confs = []
-        count = 0
-
-
-        self.options = portage.dispatch_conf.read_config(MANDATORY_OPTS)
-
-        if self.options.has_key("log-file"):
-            if os.path.isfile(self.options["log-file"]):
-                shutil.copy(self.options["log-file"], self.options["log-file"] + '.old')
-            if os.path.isfile(self.options["log-file"]) \
-               or not os.path.exists(self.options["log-file"]):
-                open(self.options["log-file"], 'w').close() # Truncate it
-                os.chmod(self.options["log-file"], 0600)
-        else:
-            self.options["log-file"] = "/dev/null"
-
-        #
-        # Build list of extant configs
-        #
-
-        for path in config_paths.split ():
-            path = portage.normalize_path(portage_const.EPREFIX + path)
-            try:
-                mymode = os.stat(path).st_mode
-            except OSError:
-                continue
-            basename = "*"
-            find_opts = ""
-            if not stat.S_ISDIR(mymode):
-                path, basename = os.path.split(path)
-                find_opts = "-maxdepth 1"
-
-            confs += self.massage(os.popen(FIND_EXTANT_CONFIGS % (path, find_opts, basename)).readlines())
-
-        if self.options['use-rcs'] == 'yes' and ((os.system( "which rcs >/dev/null 2>&1" ) == 256)
-                                                 or (os.system( "which ci >/dev/null 2>&1" ) == 256)
-                                                 or (os.system( "which co >/dev/null 2>&1" ) == 256) 
-                                                 or (os.system( "which rcsmerge >/dev/null 2>&1" ) == 256)):
-            print >> sys.stderr, 'dispatch-conf: Error finding all RCS utils and use-rcs=yes in config; fatal'
-            return False
-
-
-        # config file freezing support
-        frozen_files = set(self.options.get("frozen-files", "").split())
-        auto_zapped = []
-
-        #
-        # Remove new configs identical to current
-        #                  and
-        # Auto-replace configs a) whose differences are simply CVS interpolations,
-        #                  or  b) whose differences are simply ws or comments,
-        #                  or  c) in paths now unprotected by CONFIG_PROTECT_MASK,
-        #
-
-        def f (conf):
-            mrgconf = re.sub(r'\._cfg', '._mrg', conf['new'])
-            archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/'))
-            if self.options['use-rcs'] == 'yes':
-                mrgfail = portage.dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
-            else:
-                mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
-            if os.path.exists(archive + '.dist'):
-                unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
-            else:
-                unmodified = 0
-            if os.path.exists(mrgconf):
-                if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
-                    os.unlink(mrgconf)
-                    newconf = conf['new']
-                else:
-                    newconf = mrgconf
-            else:
-                newconf = conf['new']
-
-            mystatus, myoutput = commands.getstatusoutput(
-                DIFF_CONTENTS  % (conf ['current'], newconf))
-            same_file = 0 == len(myoutput)
-            if mystatus >> 8 == 2:
-                # Binary files differ
-                same_cvs = False
-                same_wsc = False
-            else:
-                same_cvs = 0 == len(commands.getoutput(
-                    DIFF_CVS_INTERP % (conf ['current'], newconf)))
-                same_wsc = 0 == len(commands.getoutput(
-                    DIFF_WSCOMMENTS % (conf ['current'], newconf)))
-
-            # Do options permit?
-            same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
-            same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes'
-            unmodified = unmodified and self.options['replace-unmodified'] == 'yes'
-
-            if same_file:
-                os.unlink (conf ['new'])
-                self.post_process(conf['current'])
-                if os.path.exists(mrgconf):
-                    os.unlink(mrgconf)
-                return False
-            elif conf['current'] in frozen_files:
-                """Frozen files are automatically zapped. The new config has
-                already been archived with a .new suffix.  When zapped, it is
-                left with the .new suffix (post_process is skipped), since it
-                hasn't been merged into the current config."""
-                auto_zapped.append(conf['current'])
-                os.unlink(conf['new'])
-                try:
-                    os.unlink(mrgconf)
-                except OSError:
-                    pass
-                return False
-            elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split ():
-                self.replace(newconf, conf['current'])
-                self.post_process(conf['current'])
-                if newconf == mrgconf:
-                    os.unlink(conf['new'])
-                elif os.path.exists(mrgconf):
-                    os.unlink(mrgconf)
-                return False
-            else:
-                return True
-
-        confs = filter (f, confs)
-
-        #
-        # Interactively process remaining
-        #
-
-        for conf in confs:
-            count = count + 1
-
-            newconf = conf['new']
-            mrgconf = re.sub(r'\._cfg', '._mrg', newconf)
-            if os.path.exists(mrgconf):
-                newconf = mrgconf
-            show_new_diff = 0
-
-            while 1:
-                if show_new_diff:
-                    os.system((self.options['diff']) % (conf['new'], mrgconf))
-                    show_new_diff = 0
-                else:
-                    os.system((self.options['diff']) % (conf['current'], newconf))
-
-                print
-                print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current'])
-                print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n   m merge, t toggle-merge, l look-merge: ',
-
-                c = getch ()
-
-                if c == 'q':
-                    sys.exit (0)
-                if c == 'h':
-                    self.do_help ()
-                    continue
-                elif c == 't':
-                    if newconf == mrgconf:
-                        newconf = conf['new']
-                    elif os.path.exists(mrgconf):
-                        newconf = mrgconf
-                    continue
-                elif c == 'n':
-                    break
-                elif c == 'm':
-                    merged = SCRATCH_DIR+"/"+os.path.basename(conf['current'])
-                    print
-                    ret = os.system (self.options['merge'] % (merged, conf ['current'], newconf))
-                    if ret:
-                        print "Failure running 'merge' command"
-                        continue
-                    shutil.copyfile(merged, mrgconf)
-                    os.remove(merged)
-                    mystat = os.lstat(conf['new'])
-                    os.chmod(mrgconf, mystat[ST_MODE])
-                    os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
-                    newconf = mrgconf
-                    continue
-                elif c == 'l':
-                    show_new_diff = 1
-                    continue
-                elif c == 'e':
-                    if not os.environ.has_key('EDITOR'):
-                        os.environ['EDITOR']='nano'
-                    os.system(os.environ['EDITOR'] + ' ' + newconf)
-                    continue
-                elif c == 'z':
-                    os.unlink(conf['new'])
-                    if os.path.exists(mrgconf):
-                        os.unlink(mrgconf)
-                    break
-                elif c == 'u':
-                    self.replace(newconf, conf ['current'])
-                    self.post_process(conf['current'])
-                    if newconf == mrgconf:
-                        os.unlink(conf['new'])
-                    elif os.path.exists(mrgconf):
-                        os.unlink(mrgconf)
-                    break
-                else:
-                    continue
-
-        if auto_zapped:
-            print
-            print " One or more updates are frozen and have been automatically zapped:"
-            print
-            for frozen in auto_zapped:
-                print "  * '%s'" % frozen
-            print
-
-    def replace (self, newconf, curconf):
-        """Replace current config with the new/merged version.  Also logs
-        the diff of what changed into the configured log file."""
-        os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
-        try:
-            shutil.copyfile(newconf, curconf)
-            os.remove(newconf)
-        except (IOError, os.error), why:
-            print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \
-                  (newconf, curconf, str(why))
-
-
-    def post_process(self, curconf):
-        archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/'))
-        if self.options['use-rcs'] == 'yes':
-            portage.dispatch_conf.rcs_archive_post_process(archive)
-        else:
-            portage.dispatch_conf.file_archive_post_process(archive)
-
-
-    def massage (self, newconfigs):
-        """Sort, rstrip, remove old versions, break into triad hash.
-
-        Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf)
-        and dir (/etc).
-
-        We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf.
-        """
-        h = {}
-
-        newconfigs.sort ()
-
-        for nconf in newconfigs:
-            nconf = nconf.rstrip ()
-            conf  = re.sub (r'\._cfg\d+_', '', nconf)
-            dir   = re.match (r'^(.+)/', nconf).group (1)
-
-            if h.has_key (conf):
-                mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new'])
-                if os.path.exists(mrgconf):
-                    os.unlink(mrgconf)
-                os.unlink(h[conf]['new'])
-
-            h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf }
-
-        configs = h.values ()
-        configs.sort (lambda a, b: cmp(a ['current'], b ['current']))
-
-        return configs
-
-
-    def do_help (self):
-        print; print
-
-        print '  u -- update current config with new config and continue'
-        print '  z -- zap (delete) new config and continue'
-        print '  n -- skip to next config, leave all intact'
-        print '  e -- edit new config'
-        print '  m -- interactively merge current and new configs'
-        print '  l -- look at diff between pre-merged and merged configs'
-        print '  t -- toggle new config between merged and pre-merged state'
-        print '  h -- this screen'
-        print '  q -- quit'
-
-        print; print 'press any key to return to diff...',
-
-        getch ()
+       options = {}
+
+       def grind (self, config_paths):
+               confs = []
+               count = 0
+
+
+               self.options = portage.dispatch_conf.read_config(MANDATORY_OPTS)
+
+               if self.options.has_key("log-file"):
+                       if os.path.isfile(self.options["log-file"]):
+                               shutil.copy(self.options["log-file"], self.options["log-file"] + '.old')
+                       if os.path.isfile(self.options["log-file"]) \
+                                       or not os.path.exists(self.options["log-file"]):
+                               open(self.options["log-file"], 'w').close() # Truncate it
+                               os.chmod(self.options["log-file"], 0600)
+               else:
+                       self.options["log-file"] = "/dev/null"
+
+               #
+               # Build list of extant configs
+               #
+
+               for path in config_paths.split ():
+                       path = portage.normalize_path(portage_const.EPREFIX + path)
+                       try:
+                               mymode = os.stat(path).st_mode
+                       except OSError:
+                               continue
+                       basename = "*"
+                       find_opts = ""
+                       if not stat.S_ISDIR(mymode):
+                               path, basename = os.path.split(path)
+                               find_opts = "-maxdepth 1"
+
+                       confs += self.massage(os.popen(FIND_EXTANT_CONFIGS % (path, find_opts, basename)).readlines())
+
+               if self.options['use-rcs'] == 'yes' and ((os.system( "which rcs >/dev/null 2>&1" ) == 256)
+                                                                                                or (os.system( "which ci >/dev/null 2>&1" ) == 256)
+                                                                                                or (os.system( "which co >/dev/null 2>&1" ) == 256) 
+                                                                                                or (os.system( "which rcsmerge >/dev/null 2>&1" ) == 256)):
+                       print >> sys.stderr, 'dispatch-conf: Error finding all RCS utils and use-rcs=yes in config; fatal'
+                       return False
+
+
+               # config file freezing support
+               frozen_files = set(self.options.get("frozen-files", "").split())
+               auto_zapped = []
+
+               #
+               # Remove new configs identical to current
+               #                                 and
+               # Auto-replace configs a) whose differences are simply CVS interpolations,
+               #                                 or  b) whose differences are simply ws or comments,
+               #                                 or  c) in paths now unprotected by CONFIG_PROTECT_MASK,
+               #
+
+               def f (conf):
+                       mrgconf = re.sub(r'\._cfg', '._mrg', conf['new'])
+                       archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/'))
+                       if self.options['use-rcs'] == 'yes':
+                               mrgfail = portage.dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
+                       else:
+                               mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
+                       if os.path.exists(archive + '.dist'):
+                               unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
+                       else:
+                               unmodified = 0
+                       if os.path.exists(mrgconf):
+                               if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
+                                       os.unlink(mrgconf)
+                                       newconf = conf['new']
+                               else:
+                                       newconf = mrgconf
+                       else:
+                               newconf = conf['new']
+
+                       mystatus, myoutput = commands.getstatusoutput(
+                               DIFF_CONTENTS  % (conf ['current'], newconf))
+                       same_file = 0 == len(myoutput)
+                       if mystatus >> 8 == 2:
+                               # Binary files differ
+                               same_cvs = False
+                               same_wsc = False
+                       else:
+                               same_cvs = 0 == len(commands.getoutput(
+                                       DIFF_CVS_INTERP % (conf ['current'], newconf)))
+                               same_wsc = 0 == len(commands.getoutput(
+                                       DIFF_WSCOMMENTS % (conf ['current'], newconf)))
+
+                       # Do options permit?
+                       same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
+                       same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes'
+                       unmodified = unmodified and self.options['replace-unmodified'] == 'yes'
+
+                       if same_file:
+                               os.unlink (conf ['new'])
+                               self.post_process(conf['current'])
+                               if os.path.exists(mrgconf):
+                                       os.unlink(mrgconf)
+                               return False
+                       elif conf['current'] in frozen_files:
+                               """Frozen files are automatically zapped. The new config has
+                               already been archived with a .new suffix.  When zapped, it is
+                               left with the .new suffix (post_process is skipped), since it
+                               hasn't been merged into the current config."""
+                               auto_zapped.append(conf['current'])
+                               os.unlink(conf['new'])
+                               try:
+                                       os.unlink(mrgconf)
+                               except OSError:
+                                       pass
+                               return False
+                       elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split ():
+                               self.replace(newconf, conf['current'])
+                               self.post_process(conf['current'])
+                               if newconf == mrgconf:
+                                       os.unlink(conf['new'])
+                               elif os.path.exists(mrgconf):
+                                       os.unlink(mrgconf)
+                               return False
+                       else:
+                               return True
+
+               confs = filter (f, confs)
+
+               #
+               # Interactively process remaining
+               #
+
+               for conf in confs:
+                       count = count + 1
+
+                       newconf = conf['new']
+                       mrgconf = re.sub(r'\._cfg', '._mrg', newconf)
+                       if os.path.exists(mrgconf):
+                               newconf = mrgconf
+                       show_new_diff = 0
+
+                       while 1:
+                               if show_new_diff:
+                                       os.system((self.options['diff']) % (conf['new'], mrgconf))
+                                       show_new_diff = 0
+                               else:
+                                       os.system((self.options['diff']) % (conf['current'], newconf))
+
+                               print
+                               print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current'])
+                               print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n   m merge, t toggle-merge, l look-merge: ',
+
+                               c = getch ()
+
+                               if c == 'q':
+                                       sys.exit (0)
+                               if c == 'h':
+                                       self.do_help ()
+                                       continue
+                               elif c == 't':
+                                       if newconf == mrgconf:
+                                               newconf = conf['new']
+                                       elif os.path.exists(mrgconf):
+                                               newconf = mrgconf
+                                       continue
+                               elif c == 'n':
+                                       break
+                               elif c == 'm':
+                                       merged = SCRATCH_DIR+"/"+os.path.basename(conf['current'])
+                                       print
+                                       ret = os.system (self.options['merge'] % (merged, conf ['current'], newconf))
+                                       if ret:
+                                               print "Failure running 'merge' command"
+                                               continue
+                                       shutil.copyfile(merged, mrgconf)
+                                       os.remove(merged)
+                                       mystat = os.lstat(conf['new'])
+                                       os.chmod(mrgconf, mystat[ST_MODE])
+                                       os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+                                       newconf = mrgconf
+                                       continue
+                               elif c == 'l':
+                                       show_new_diff = 1
+                                       continue
+                               elif c == 'e':
+                                       if not os.environ.has_key('EDITOR'):
+                                               os.environ['EDITOR']='nano'
+                                       os.system(os.environ['EDITOR'] + ' ' + newconf)
+                                       continue
+                               elif c == 'z':
+                                       os.unlink(conf['new'])
+                                       if os.path.exists(mrgconf):
+                                               os.unlink(mrgconf)
+                                       break
+                               elif c == 'u':
+                                       self.replace(newconf, conf ['current'])
+                                       self.post_process(conf['current'])
+                                       if newconf == mrgconf:
+                                               os.unlink(conf['new'])
+                                       elif os.path.exists(mrgconf):
+                                               os.unlink(mrgconf)
+                                       break
+                               else:
+                                       continue
+
+               if auto_zapped:
+                       print
+                       print " One or more updates are frozen and have been automatically zapped:"
+                       print
+                       for frozen in auto_zapped:
+                               print "  * '%s'" % frozen
+                       print
+
+       def replace (self, newconf, curconf):
+               """Replace current config with the new/merged version.  Also logs
+               the diff of what changed into the configured log file."""
+               os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
+               try:
+                       shutil.copyfile(newconf, curconf)
+                       os.remove(newconf)
+               except (IOError, os.error), why:
+                       print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \
+                                 (newconf, curconf, str(why))
+
+
+       def post_process(self, curconf):
+               archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/'))
+               if self.options['use-rcs'] == 'yes':
+                       portage.dispatch_conf.rcs_archive_post_process(archive)
+               else:
+                       portage.dispatch_conf.file_archive_post_process(archive)
+
+
+       def massage (self, newconfigs):
+               """Sort, rstrip, remove old versions, break into triad hash.
+
+               Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf)
+               and dir (/etc).
+
+               We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf.
+               """
+               h = {}
+
+               newconfigs.sort ()
+
+               for nconf in newconfigs:
+                       nconf = nconf.rstrip ()
+                       conf  = re.sub (r'\._cfg\d+_', '', nconf)
+                       dir   = re.match (r'^(.+)/', nconf).group (1)
+
+                       if h.has_key (conf):
+                               mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new'])
+                               if os.path.exists(mrgconf):
+                                       os.unlink(mrgconf)
+                               os.unlink(h[conf]['new'])
+
+                       h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf }
+
+               configs = h.values ()
+               configs.sort (lambda a, b: cmp(a ['current'], b ['current']))
+
+               return configs
+
+
+       def do_help (self):
+               print; print
+
+               print '  u -- update current config with new config and continue'
+               print '  z -- zap (delete) new config and continue'
+               print '  n -- skip to next config, leave all intact'
+               print '  e -- edit new config'
+               print '  m -- interactively merge current and new configs'
+               print '  l -- look at diff between pre-merged and merged configs'
+               print '  t -- toggle new config between merged and pre-merged state'
+               print '  h -- this screen'
+               print '  q -- quit'
+
+               print; print 'press any key to return to diff...',
+
+               getch ()
 
 
 def getch ():
-    # from ASPN - Danny Yoo
-    #
-    import sys, tty, termios
+       # from ASPN - Danny Yoo
+       #
+       import sys, tty, termios
 
-    fd = sys.stdin.fileno()
-    old_settings = termios.tcgetattr(fd)
-    try:
-        tty.setraw(sys.stdin.fileno())
-        ch = sys.stdin.read(1)
-    finally:
-        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
-    return ch
+       fd = sys.stdin.fileno()
+       old_settings = termios.tcgetattr(fd)
+       try:
+               tty.setraw(sys.stdin.fileno())
+               ch = sys.stdin.read(1)
+       finally:
+               termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+       return ch
 
 
 # run
 d = dispatch ()
 
 if len(sys.argv) > 1:
-    # for testing
-    d.grind (" ".join(sys.argv[1:]))
+       # for testing
+       d.grind (" ".join(sys.argv[1:]))
 else:
-    d.grind (portage.settings ['CONFIG_PROTECT'])
+       d.grind (portage.settings ['CONFIG_PROTECT'])