f68e9f70db9ad1c3e99541b8562d52347c204f03
[beastbuild.git] / buildutils.py
1 import utils
2 import urlparse
3 import os
4 import hashlib
5 import sys
6 import subprocess
7 import stat
8 from config import config
9 from Path import Path
10
11 def download_and_check (url, md5_hash):
12   scheme, host, path, params, qu, fr = urlparse.urlparse (url)
13   filename = os.path.basename (path)
14   download_dir = config.DOWNLOAD.native()
15   if (not os.path.exists (download_dir)):
16     os.makedirs (download_dir)
17   filename_full = os.path.join (download_dir, filename)
18   if (os.path.exists (filename_full)):
19     if (file_md5_hash (filename_full) == md5_hash):
20       return
21   print "downloading " + filename_full + " from " + url
22   sys.stdout.flush()
23   utils.getFile (url, download_dir)
24   local_hash = file_md5_hash (filename_full) 
25   if (local_hash == md5_hash):
26     print "md5 hash check ok."
27     return
28   else:
29     utils.die ("md5 hash of file " + filename_full + " does not match expected value\n"
30              + "expected md5 hash: " + md5_hash + "\n" + "   local md5 hash: " + local_hash)
31
32 def git_checkout (repo, project, branch):
33   bb_file_name = config.SRC_DIR.join (Path (project + "/.BEASTBUILD")).native()
34   if not os.path.exists (bb_file_name + "_CLONE_OK"):
35     os.chdir (config.SRC_DIR.native())
36     cmd = "git clone %s/%s" % (config.REPOSITORY[repo], project)
37     print cmd
38     status = call_log (["sh", "-c", cmd ])
39     if (status != 0):
40       utils.die ("cannot clone git repository %s project %s" % (repo, project))
41     # create stamp file
42     file = open (bb_file_name + "_CLONE_OK", "w")
43     file.write ("stamp file needed by beastbuild")
44     file.close()
45   if not os.path.exists (bb_file_name + "_CHECKOUT_OK"):
46     os.chdir (os.path.join (config.SRC_DIR.native(), project))
47     cmd = "git checkout -b %s origin/%s" % (branch, branch)
48     print cmd
49     status = call_log (["sh", "-c", cmd ])
50     if (status != 0):
51       utils.die ("cannot checkout branch %s (project %s)" % (branch, project))
52     # create stamp file
53     file = open (bb_file_name + "_CHECKOUT_OK", "w")
54     file.write ("stamp file needed by beastbuild")
55     file.close()
56   os.chdir (os.path.join (config.SRC_DIR.native(), project))
57   cmd = "git pull"
58   print cmd
59   status = call_log (["sh", "-c", cmd ])
60   if (status != 0):
61     utils.die ("cannot pull from project %s" % project)
62  
63 def file_md5_hash (path):
64   m = hashlib.md5()
65   file = open (path, "rb")
66   block = file.read (65536)
67   while block != "":
68     m.update (block)
69     block = file.read (65536)
70   file.close()
71   return m.hexdigest()
72
73 def configure (cmd, dir):
74   if (dir != "."):
75     os.chdir (os.path.join (config.SRC_DIR.native(), dir))
76   cmd_string = ""
77   for i in cmd:
78     cmd_string += i + " ";
79   print "configure: " + cmd_string
80   sys.stdout.flush()
81   status = call_log (cmd)
82   if (status != 0):
83     utils.die ("error (%d) while configuring package" % status)
84
85 def make (cmd, dir):
86   if (dir != "."):
87     os.chdir (os.path.join (config.SRC_DIR.native(), dir))
88   cmd_string = ""
89   for i in cmd:
90     cmd_string += i + " ";
91   print "make: " + cmd_string
92   sys.stdout.flush()
93   status = call_log (cmd)
94   if (status != 0):
95     utils.die ("error (%d) while compiling package" % status)
96
97 ### patch file functions
98 def apply_patch(patch, dir, patch_depth):
99   if (dir != "."):
100     os.chdir (os.path.join (config.SRC_DIR.native(), dir))
101   cmd = "set -o pipefail ; stripm < %s | patch -p%d" % (config.BEASTBUILD.join (Path (patch)).unix(), patch_depth)
102   print "apply_patch: " + cmd
103   sys.stdout.flush()
104   status = call_log (["sh", "-c", cmd])
105   if (status != 0):
106     utils.die ("error: can not apply patch " + patch)
107
108 ### rm -rf
109 # shutil.rmtree (dir) fails with write protected files on windows
110 def rm_rf (path):
111   try:
112     mode = os.lstat(path).st_mode
113     if stat.S_ISDIR(mode):
114       for entry in os.listdir (path):
115         rm_rf (os.path.join (path, entry))
116       os.rmdir (path)
117     else:
118       try:
119         os.remove (path)
120       except:
121         os.chmod (path, 0777)
122         os.remove (path)
123   except OSError,e:
124     if e.errno != os.errno.ENOENT:  # ignore non-existant files
125       utils.die ("error: can not delete '" + path + "' from cwd=" + os.getcwd() + ":" + os.strerror (e.errno))
126
127 #--------------------------------------------------------------------------------------------
128 # subprocess with logfile output
129 #--------------------------------------------------------------------------------------------
130
131 from subprocess import Popen, PIPE
132 import thread, threading
133 import os, sys
134
135 thread_lock = threading.Lock()
136 log_file = False
137
138 def out_reader (file):
139   while True:
140     line = file.readline ()
141     if line == '':
142       return
143     thread_lock.acquire()
144     sys.stdout.write (line)
145     log_file.write (line)
146     log_file.flush()
147     thread_lock.release()
148
149
150 def call_log_file (file_name):
151   global log_file
152   try:
153     log_file = open (file_name, 'w')
154   except:
155     utils.die ("error: can't write log file: '" + file_name + "'")
156
157 def call_log (cmd):
158   proc = Popen(cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE)
159   t1 = thread.start_new_thread (out_reader, (proc.stdout,))
160   t2 = thread.start_new_thread (out_reader, (proc.stderr,))
161   return proc.wait()
162
163 ## platform specific code
164 #
165 def platform_is_win32():
166   return sys.platform == "win32"
167
168 def platform_is_unix():
169   return not platform_is_win32()
170
171 def prepend_path (path):
172   if platform_is_win32():
173     old_path = os.environ['Path']
174     new_path = path.win32() + ";" + old_path
175     os.environ['Path'] = new_path
176   else:
177     old_path = os.environ['PATH']
178     new_path = path.unix() + ":" + old_path
179     os.environ['PATH'] = new_path
180
181 # vim:set sw=2 sts=2: