Add vcs-load-dirs project to thirdparty directory.
[Melange.git] / thirdparty / vcs-load-dirs / vcs_support / util.py
blob9c6702a6b095baffb0f294175c37a37f21c16886
1 # Copyright (C) 2003-2007 John Goerzen
2 # <jgoerzen@complete.org>
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.
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.
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
18 import os, sys, re
20 nulldev = None
21 verbose = 0
23 class ExecProblem(Exception):
24 pass
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.
31 If wait is 1, wait until the child exits, then return the result code from
32 os.waitpid().
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)
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
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)
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
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)
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
97 def checkpid(pid, expected):
98 return checkresult(os.waitpid(pid, 0)[1], expected)
100 def getnull():
101 global nulldev
102 if not nulldev:
103 nulldev = open("/dev/null", "w+")
104 return nulldev
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)
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)
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
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)