| OLD | NEW |
| 1 # Copyright (c) 2014 The Native Client Authors. All rights reserved. | 1 # Copyright (c) 2014 The Native Client Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import contextlib | 5 import contextlib |
| 6 import os | 6 import os |
| 7 import re | 7 import re |
| 8 import shutil | 8 import shutil |
| 9 import subprocess | 9 import subprocess |
| 10 import sys | 10 import sys |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 | 28 |
| 29 @contextlib.contextmanager | 29 @contextlib.contextmanager |
| 30 def RedirectStdoutStderr(filename): | 30 def RedirectStdoutStderr(filename): |
| 31 """Context manager that replaces stdout and stderr streams.""" | 31 """Context manager that replaces stdout and stderr streams.""" |
| 32 if filename is None: | 32 if filename is None: |
| 33 yield | 33 yield |
| 34 return | 34 return |
| 35 | 35 |
| 36 with open(filename, 'a') as stream: | 36 with open(filename, 'a') as stream: |
| 37 old_stdout = sys.stdout |
| 38 old_stderr = sys.stderr |
| 37 sys.stdout = stream | 39 sys.stdout = stream |
| 38 sys.stderr = stream | 40 sys.stderr = stream |
| 41 util.CheckStdoutForColorSupport() |
| 39 try: | 42 try: |
| 40 yield | 43 yield |
| 41 finally: | 44 finally: |
| 42 sys.stdout = sys.__stdout__ | 45 sys.stdout = old_stdout |
| 43 sys.stderr = sys.__stdout__ | 46 sys.stderr = old_stderr |
| 47 util.CheckStdoutForColorSupport() |
| 44 | 48 |
| 45 | 49 |
| 46 def FormatTimeDelta(delta): | 50 def FormatTimeDelta(delta): |
| 47 """Converts a duration in seconds to a human readable string. | 51 """Converts a duration in seconds to a human readable string. |
| 48 | 52 |
| 49 Args: | 53 Args: |
| 50 delta: the amount of time in seconds. | 54 delta: the amount of time in seconds. |
| 51 | 55 |
| 52 Returns: A string desribing the ammount of time passed in. | 56 Returns: A string desribing the ammount of time passed in. |
| 53 """ | 57 """ |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 except PkgFormatError: | 230 except PkgFormatError: |
| 227 # If the package is malformed in some way or in some old format | 231 # If the package is malformed in some way or in some old format |
| 228 # then treat it as not built. | 232 # then treat it as not built. |
| 229 return False | 233 return False |
| 230 return pkg.IsInstallable() | 234 return pkg.IsInstallable() |
| 231 | 235 |
| 232 def Install(self, build_deps, force=None, from_source=False): | 236 def Install(self, build_deps, force=None, from_source=False): |
| 233 self.CheckInstallable() | 237 self.CheckInstallable() |
| 234 | 238 |
| 235 if force is None and self.IsInstalled(): | 239 if force is None and self.IsInstalled(): |
| 236 Log('Already installed %s' % self.InfoString()) | 240 self.LogStatus('Already installed') |
| 237 return | 241 return |
| 238 | 242 |
| 239 if build_deps: | 243 if build_deps: |
| 240 self.InstallDeps(force, from_source) | 244 self.InstallDeps(force, from_source) |
| 241 | 245 |
| 242 if force: | 246 if force: |
| 243 from_source = True | 247 from_source = True |
| 244 | 248 |
| 245 package_file = self.PackageFile() | 249 package_file = self.PackageFile() |
| 246 if not self.IsBuilt() and not from_source: | 250 if not self.IsBuilt() and not from_source: |
| 247 index = package_index.GetCurrentIndex() | 251 index = package_index.GetCurrentIndex() |
| 248 if index.Installable(self.NAME, self.config): | 252 if index.Installable(self.NAME, self.config): |
| 249 package_file = index.Download(self.NAME, self.config) | 253 package_file = index.Download(self.NAME, self.config) |
| 250 else: | 254 else: |
| 251 from_source = True | 255 from_source = True |
| 252 | 256 |
| 253 if from_source: | 257 if from_source: |
| 254 self.Build(build_deps, force) | 258 self.Build(build_deps, force) |
| 255 | 259 |
| 256 if self.IsAnyVersionInstalled(): | 260 if self.IsAnyVersionInstalled(): |
| 257 Log('Uninstalling existing %s' % self.InfoString()) | 261 self.LogStatus('Uninstalling existing') |
| 258 self.GetInstalledPackage().DoUninstall() | 262 self.GetInstalledPackage().DoUninstall() |
| 259 | 263 |
| 260 binary_package.BinaryPackage(package_file).Install() | 264 binary_package.BinaryPackage(package_file).Install() |
| 261 | 265 |
| 262 def GetInstalledPackage(self): | 266 def GetInstalledPackage(self): |
| 263 return package.CreateInstalledPackage(self.NAME, self.config) | 267 return package.CreateInstalledPackage(self.NAME, self.config) |
| 264 | 268 |
| 265 def Build(self, build_deps, force=None): | 269 def Build(self, build_deps, force=None): |
| 266 self.CheckBuildable() | 270 self.CheckBuildable() |
| 267 | 271 |
| 268 if build_deps: | 272 if build_deps: |
| 269 self.InstallDeps(force) | 273 self.InstallDeps(force) |
| 270 | 274 |
| 271 if not force and self.IsBuilt(): | 275 if not force and self.IsBuilt(): |
| 272 Log('Already built %s' % self.InfoString()) | 276 self.LogStatus('Already built') |
| 273 return | 277 return |
| 274 | 278 |
| 275 log_root = os.path.join(paths.OUT_DIR, 'logs') | 279 log_root = os.path.join(paths.OUT_DIR, 'logs') |
| 276 util.Makedirs(log_root) | 280 util.Makedirs(log_root) |
| 277 | 281 |
| 278 if util.verbose: | 282 self.LogStatus('Building') |
| 279 prefix = '*** ' | |
| 280 else: | |
| 281 prefix = '' | |
| 282 Log('%sBuilding %s' % (prefix, self.InfoString())) | |
| 283 | 283 |
| 284 if util.verbose: | 284 if util.verbose: |
| 285 log_filename = None | 285 log_filename = None |
| 286 else: | 286 else: |
| 287 log_filename = os.path.join(log_root, '%s_%s.log' % (self.NAME, | 287 log_filename = os.path.join(log_root, '%s_%s.log' % (self.NAME, |
| 288 str(self.config).replace('/', '_'))) | 288 str(self.config).replace('/', '_'))) |
| 289 if os.path.exists(log_filename): | 289 if os.path.exists(log_filename): |
| 290 os.remove(log_filename) | 290 os.remove(log_filename) |
| 291 | 291 |
| 292 start = time.time() | 292 start = time.time() |
| 293 with util.BuildLock(): | 293 with util.BuildLock(): |
| 294 with RedirectStdoutStderr(log_filename): | 294 with RedirectStdoutStderr(log_filename): |
| 295 old_verbose = util.verbose | 295 old_verbose = util.verbose |
| 296 try: | 296 try: |
| 297 util.verbose = True | 297 util.verbose = True |
| 298 self.Download() | 298 self.Download() |
| 299 self.Extract() | 299 self.Extract() |
| 300 self.Patch() | 300 self.Patch() |
| 301 self.RunBuildSh() | 301 self.RunBuildSh() |
| 302 finally: | 302 finally: |
| 303 util.verbose = old_verbose | 303 util.verbose = old_verbose |
| 304 | 304 |
| 305 duration = FormatTimeDelta(time.time() - start) | 305 duration = FormatTimeDelta(time.time() - start) |
| 306 Log('Build complete %s [took %s]' % (self.InfoString(), duration)) | 306 util.LogHeading('Build complete', ' [took %s]' % duration) |
| 307 | 307 |
| 308 def RunBuildSh(self): | 308 def RunBuildSh(self): |
| 309 build_port = os.path.join(paths.TOOLS_DIR, 'build_port.sh') | 309 build_port = os.path.join(paths.TOOLS_DIR, 'build_port.sh') |
| 310 cmd = [build_port] | 310 cmd = [build_port] |
| 311 | 311 |
| 312 env = os.environ.copy() | 312 env = os.environ.copy() |
| 313 env['TOOLCHAIN'] = self.config.toolchain | 313 env['TOOLCHAIN'] = self.config.toolchain |
| 314 env['NACL_ARCH'] = self.config.arch | 314 env['NACL_ARCH'] = self.config.arch |
| 315 env['NACL_DEBUG'] = self.config.debug and '1' or '0' | 315 env['NACL_DEBUG'] = self.config.debug and '1' or '0' |
| 316 rtn = subprocess.call(cmd, | 316 rtn = subprocess.call(cmd, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 stamp_file = self.GetExtractStamp() | 374 stamp_file = self.GetExtractStamp() |
| 375 stamp_contents = self.GetExtractStampContent() | 375 stamp_contents = self.GetExtractStampContent() |
| 376 if os.path.exists(dest): | 376 if os.path.exists(dest): |
| 377 if StampContentsMatch(stamp_file, stamp_contents): | 377 if StampContentsMatch(stamp_file, stamp_contents): |
| 378 Log('Already up-to-date: %s' % util.RelPath(dest)) | 378 Log('Already up-to-date: %s' % util.RelPath(dest)) |
| 379 return | 379 return |
| 380 | 380 |
| 381 raise Error("Upstream archive or patch has changed.\n" + | 381 raise Error("Upstream archive or patch has changed.\n" + |
| 382 "Please remove existing checkout and try again: '%s'" % dest) | 382 "Please remove existing checkout and try again: '%s'" % dest) |
| 383 | 383 |
| 384 self.Banner('Extracting') | 384 util.LogHeading('Extracting') |
| 385 util.Makedirs(paths.OUT_DIR) | 385 util.Makedirs(paths.OUT_DIR) |
| 386 tmp_output_path = tempfile.mkdtemp(dir=paths.OUT_DIR) | 386 tmp_output_path = tempfile.mkdtemp(dir=paths.OUT_DIR) |
| 387 try: | 387 try: |
| 388 ExtractArchive(archive, tmp_output_path) | 388 ExtractArchive(archive, tmp_output_path) |
| 389 src = os.path.join(tmp_output_path, new_foldername) | 389 src = os.path.join(tmp_output_path, new_foldername) |
| 390 if not os.path.isdir(src): | 390 if not os.path.isdir(src): |
| 391 raise Error('Archive contents not found: %s' % src) | 391 raise Error('Archive contents not found: %s' % src) |
| 392 Trace("renaming '%s' -> '%s'" % (src, dest)) | 392 Trace("renaming '%s' -> '%s'" % (src, dest)) |
| 393 os.rename(src, dest) | 393 os.rename(src, dest) |
| 394 finally: | 394 finally: |
| 395 shutil.rmtree(tmp_output_path) | 395 shutil.rmtree(tmp_output_path) |
| 396 | 396 |
| 397 self.RemoveStamps() | 397 self.RemoveStamps() |
| 398 WriteStamp(stamp_file, stamp_contents) | 398 WriteStamp(stamp_file, stamp_contents) |
| 399 | 399 |
| 400 def RunCmd(self, cmd, **args): | 400 def RunCmd(self, cmd, **args): |
| 401 try: | 401 try: |
| 402 subprocess.check_call(cmd, | 402 subprocess.check_call(cmd, |
| 403 stdout=sys.stdout, | 403 stdout=sys.stdout, |
| 404 stderr=sys.stderr, | 404 stderr=sys.stderr, |
| 405 cwd=self.GetBuildLocation(), | 405 cwd=self.GetBuildLocation(), |
| 406 **args) | 406 **args) |
| 407 except subprocess.CalledProcessError as e: | 407 except subprocess.CalledProcessError as e: |
| 408 raise Error(e) | 408 raise Error(e) |
| 409 | 409 |
| 410 def Log(self, message): | 410 def Log(self, message): |
| 411 Log('%s: %s' % (message, self.InfoString())) | 411 Log('%s: %s' % (message, self.InfoString())) |
| 412 | 412 |
| 413 def Banner(self, message): | |
| 414 Log("#####################################################################") | |
| 415 self.Log(message) | |
| 416 Log("#####################################################################") | |
| 417 | |
| 418 def GetStampDir(self): | 413 def GetStampDir(self): |
| 419 return os.path.join(paths.STAMP_DIR, self.NAME) | 414 return os.path.join(paths.STAMP_DIR, self.NAME) |
| 420 | 415 |
| 421 def RemoveStamps(self): | 416 def RemoveStamps(self): |
| 422 util.RemoveTree(self.GetStampDir()) | 417 util.RemoveTree(self.GetStampDir()) |
| 423 | 418 |
| 424 def Patch(self): | 419 def Patch(self): |
| 425 stamp_file = os.path.join(self.GetStampDir(), 'nacl_patch') | 420 stamp_file = os.path.join(self.GetStampDir(), 'nacl_patch') |
| 426 src_dir = self.GetBuildLocation() | 421 src_dir = self.GetBuildLocation() |
| 427 if self.URL is None: | 422 if self.URL is None: |
| 428 return | 423 return |
| 429 | 424 |
| 430 if os.path.exists(stamp_file): | 425 if os.path.exists(stamp_file): |
| 431 self.Log('Skipping patch step (cleaning source tree)') | 426 self.Log('Skipping patch step (cleaning source tree)') |
| 432 cmd = ['git', 'clean', '-f', '-d'] | 427 cmd = ['git', 'clean', '-f', '-d'] |
| 433 if not util.verbose: | 428 if not util.verbose: |
| 434 cmd.append('-q') | 429 cmd.append('-q') |
| 435 self.RunCmd(cmd) | 430 self.RunCmd(cmd) |
| 436 return | 431 return |
| 437 | 432 |
| 438 self.Banner('Patching') | 433 util.LogHeading('Patching') |
| 439 Log('Init git repo: %s' % src_dir) | 434 Log('Init git repo: %s' % src_dir) |
| 440 try: | 435 try: |
| 441 InitGitRepo(src_dir) | 436 InitGitRepo(src_dir) |
| 442 except subprocess.CalledProcessError as e: | 437 except subprocess.CalledProcessError as e: |
| 443 raise Error(e) | 438 raise Error(e) |
| 444 if os.path.exists(self.GetPatchFile()): | 439 if os.path.exists(self.GetPatchFile()): |
| 445 Trace('applying patch to: %s' % src_dir) | 440 Trace('applying patch to: %s' % src_dir) |
| 446 cmd = ['patch', '-p1', '-g0', '--no-backup-if-mismatch'] | 441 cmd = ['patch', '-p1', '-g0', '--no-backup-if-mismatch'] |
| 447 with open(self.GetPatchFile()) as f: | 442 with open(self.GetPatchFile()) as f: |
| 448 self.RunCmd(cmd, stdin=f) | 443 self.RunCmd(cmd, stdin=f) |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 stamp_content += '\n' | 559 stamp_content += '\n' |
| 565 | 560 |
| 566 dest = self.GetBuildLocation() | 561 dest = self.GetBuildLocation() |
| 567 if os.path.exists(self.GetBuildLocation()): | 562 if os.path.exists(self.GetBuildLocation()): |
| 568 if StampContentsMatch(stamp_file, stamp_content): | 563 if StampContentsMatch(stamp_file, stamp_content): |
| 569 return | 564 return |
| 570 | 565 |
| 571 raise Error('Upstream archive or patch has changed.\n' + | 566 raise Error('Upstream archive or patch has changed.\n' + |
| 572 "Please remove existing checkout and try again: '%s'" % dest) | 567 "Please remove existing checkout and try again: '%s'" % dest) |
| 573 | 568 |
| 574 self.Banner('Cloning') | 569 util.LogHeading('Cloning') |
| 575 # Ensure local mirror is up-to-date | 570 # Ensure local mirror is up-to-date |
| 576 git_mirror, git_commit = self.GitCloneToMirror() | 571 git_mirror, git_commit = self.GitCloneToMirror() |
| 577 # Clone from the local mirror. | 572 # Clone from the local mirror. |
| 578 RunGitCmd(None, ['clone', git_mirror, dest]) | 573 RunGitCmd(None, ['clone', git_mirror, dest]) |
| 579 RunGitCmd(dest, ['reset', '--hard', git_commit]) | 574 RunGitCmd(dest, ['reset', '--hard', git_commit]) |
| 580 | 575 |
| 581 # Set the origing to the original URL so it is possible to push directly | 576 # Set the origing to the original URL so it is possible to push directly |
| 582 # from the build tree. | 577 # from the build tree. |
| 583 RunGitCmd(dest, ['remote', 'set-url', 'origin', '${GIT_URL}']) | 578 RunGitCmd(dest, ['remote', 'set-url', 'origin', '${GIT_URL}']) |
| 584 | 579 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 if os.path.isdir(package_name): | 687 if os.path.isdir(package_name): |
| 693 return SourcePackage(package_name, config) | 688 return SourcePackage(package_name, config) |
| 694 | 689 |
| 695 for subdir in DEFAULT_LOCATIONS: | 690 for subdir in DEFAULT_LOCATIONS: |
| 696 pkg_root = os.path.join(paths.NACLPORTS_ROOT, subdir, package_name) | 691 pkg_root = os.path.join(paths.NACLPORTS_ROOT, subdir, package_name) |
| 697 info = os.path.join(pkg_root, 'pkg_info') | 692 info = os.path.join(pkg_root, 'pkg_info') |
| 698 if os.path.exists(info): | 693 if os.path.exists(info): |
| 699 return SourcePackage(pkg_root, config) | 694 return SourcePackage(pkg_root, config) |
| 700 | 695 |
| 701 raise Error("Package not found: %s" % package_name) | 696 raise Error("Package not found: %s" % package_name) |
| OLD | NEW |