thirdparty/vcs-load-dirs/vcs_support/util.py
changeset 2311 e8262ca32109
equal deleted inserted replaced
2310:d51331eaec15 2311:e8262ca32109
       
     1 # Copyright (C) 2003-2007 John Goerzen
       
     2 # <jgoerzen@complete.org>
       
     3 #
       
     4 #    This program is free software; you can redistribute it and/or modify
       
     5 #    it under the terms of the GNU General Public License as published by
       
     6 #    the Free Software Foundation; either version 2 of the License, or
       
     7 #    (at your option) any later version.
       
     8 #
       
     9 #    This program is distributed in the hope that it will be useful,
       
    10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 #    GNU General Public License for more details.
       
    13 #
       
    14 #    You should have received a copy of the GNU General Public License
       
    15 #    along with this program; if not, write to the Free Software
       
    16 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17 
       
    18 import os, sys, re
       
    19 
       
    20 nulldev = None
       
    21 verbose = 0
       
    22 
       
    23 class ExecProblem(Exception):
       
    24     pass
       
    25 
       
    26 def mainexec(program, args = [], child_stdout = None,
       
    27              child_stdin = None, child_stderr = None, wait = 1, closefds = []):
       
    28     """Runs the program as a sub-process, passing to it args if specified.
       
    29     The sub-process has its file descriptors adjusted as per the arguments.
       
    30 
       
    31     If wait is 1, wait until the child exits, then return the result code from
       
    32     os.waitpid().
       
    33 
       
    34     If wait is 0, return the PID immediately."""
       
    35     global verbose
       
    36     def setfds(source, dest):
       
    37         if source != None:
       
    38             if hasattr(source, 'fileno'):
       
    39                 source = source.fileno()
       
    40             os.dup2(source, dest)
       
    41             
       
    42     pid = os.fork()
       
    43     if not pid:
       
    44         if verbose:
       
    45             print "Running: ", program, args
       
    46         setfds(child_stdin, 0)
       
    47         setfds(child_stdout, 1)
       
    48         setfds(child_stderr, 2)
       
    49         for fd in closefds:
       
    50             os.close(fd)
       
    51         os.execvp(program, (program,) + tuple(args))
       
    52         sys.exit(255)
       
    53     else:
       
    54         if wait:
       
    55             return os.waitpid(pid, 0)[1]
       
    56         else:
       
    57             return pid
       
    58 
       
    59 def safeexec(program, args = [], child_stdout = None,
       
    60              child_stdin = None, child_stderr = None,
       
    61              expected = 0):
       
    62     """Calls mainexec() with the appropriate arguments, and raises
       
    63     an exception if the program died with a signal or returned an
       
    64     error code other than expected.  This function will always wait."""
       
    65     result = mainexec(program, args, child_stdout, child_stdin, child_stderr)
       
    66     return checkresult(result, expected)
       
    67 
       
    68 def getstdoutsafeexec(program, args, expected = 0):
       
    69     pipes = os.pipe()
       
    70     pid = mainexec(program, args, child_stdout = pipes[1], wait  = 0)
       
    71     os.close(pipes[1])
       
    72     fd = os.fdopen(pipes[0], 'r')
       
    73     retval = fd.readlines()
       
    74     checkpid(pid, expected)
       
    75     os.close(pipes[0])
       
    76     return retval
       
    77 
       
    78 def silentsafeexec(program, args, expected = 0):
       
    79     """Silently runs the specified program."""
       
    80     null = getnull()
       
    81     result = mainexec(program, args, null, null, null)
       
    82     return checkresult(result, expected)
       
    83 
       
    84 def checkresult(result, expected):
       
    85     info = []
       
    86     if os.WIFSIGNALED(result):
       
    87         info.append("got signal %d" % os.WTERMSIG(result))
       
    88     if os.WIFEXITED(result):
       
    89         info.append("exited with code %d" % os.WEXITSTATUS(result))
       
    90     info = ",".join(info)
       
    91     if not os.WIFEXITED(result):
       
    92         raise ExecProblem, info
       
    93     if os.WEXITSTATUS(result) != expected:
       
    94         raise ExecProblem, info + " (expected exit code %d)" % expected
       
    95     return result
       
    96 
       
    97 def checkpid(pid, expected):
       
    98     return checkresult(os.waitpid(pid, 0)[1], expected)
       
    99 
       
   100 def getnull():
       
   101     global nulldev
       
   102     if not nulldev:
       
   103         nulldev = open("/dev/null", "w+")
       
   104     return nulldev
       
   105 
       
   106 def chdircmd(newdir, func, *args, **kwargs):
       
   107     cwd = os.getcwd()
       
   108     os.chdir(newdir)
       
   109     try:
       
   110         return apply(func, args, kwargs)
       
   111     finally:
       
   112         os.chdir(cwd)
       
   113 
       
   114 def maketree(path, addpath = None, ignore = [], res = None):
       
   115     thisdir = os.listdir(path)
       
   116     retval = []
       
   117     others = []
       
   118     if res == None:
       
   119         res = [re.compile(x) for x in ignore]
       
   120     for item in thisdir:
       
   121         skip = 0
       
   122         for retest in res:
       
   123             if retest.search(item):
       
   124                 skip = 1
       
   125                 break
       
   126         if skip:
       
   127             continue
       
   128         dirname = os.path.join(path, item)
       
   129         if os.path.isdir(dirname) and not os.path.islink(dirname):
       
   130             if addpath:
       
   131                 retval.append(os.path.join(addpath, item) + '/')
       
   132             else:
       
   133                 retval.append(item + '/')
       
   134             if addpath:
       
   135                 newaddpath = os.path.join(addpath, item)
       
   136             else:
       
   137                 newaddpath = item
       
   138             others.extend(maketree(dirname, newaddpath, res = res))
       
   139         else:
       
   140             if addpath:
       
   141                 retval.append(os.path.join(addpath, item))
       
   142             else:
       
   143                 retval.append(item)
       
   144     return sorttree(retval + others)
       
   145 
       
   146 def sorttree(srctree, filesfirst = False):
       
   147     retval = []
       
   148     dirs = [x for x in srctree if x.endswith('/')]
       
   149     files = [x for x in srctree if not x.endswith('/')]
       
   150     dirs.sort()
       
   151     files.sort()
       
   152     if filesfirst:
       
   153         return files + dirs
       
   154     else:
       
   155         return dirs + files
       
   156     
       
   157         
       
   158 def copyfrom(srcdir, destdir):
       
   159     pipes = os.pipe()
       
   160     verbargs = []
       
   161     #if verbose:
       
   162     #    verbargs.append('-v')
       
   163     readerpid = chdircmd(srcdir, mainexec, "tar", ["-cSpf", "-", "."],
       
   164                          child_stdout = pipes[1], wait = 0,
       
   165                          closefds = [pipes[0]])
       
   166     writerpid = chdircmd(destdir, mainexec, "tar", ["-xSpf", "-"] + verbargs,
       
   167                          child_stdin = pipes[0], wait = 0, closefds = [pipes[1]])
       
   168     os.close(pipes[0])
       
   169     os.close(pipes[1])
       
   170     checkpid(readerpid, 0)
       
   171     checkpid(writerpid, 0)
       
   172