OLD | NEW |
---|---|
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. 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 from __future__ import with_statement | 5 from __future__ import with_statement |
6 | 6 |
7 import collections | 7 import collections |
8 import errno | 8 import errno |
9 import filecmp | 9 import filecmp |
10 import os.path | 10 import os.path |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 | 338 |
339 class Writer(object): | 339 class Writer(object): |
340 """Wrapper around file which only covers the target if it differs.""" | 340 """Wrapper around file which only covers the target if it differs.""" |
341 def __init__(self): | 341 def __init__(self): |
342 # Pick temporary file. | 342 # Pick temporary file. |
343 tmp_fd, self.tmp_path = tempfile.mkstemp( | 343 tmp_fd, self.tmp_path = tempfile.mkstemp( |
344 suffix='.tmp', | 344 suffix='.tmp', |
345 prefix=os.path.split(filename)[1] + '.gyp.', | 345 prefix=os.path.split(filename)[1] + '.gyp.', |
346 dir=os.path.split(filename)[0]) | 346 dir=os.path.split(filename)[0]) |
347 try: | 347 try: |
348 self.tmp_file = os.fdopen(tmp_fd, 'wb') | 348 self.tmp_file = os.fdopen(tmp_fd, 'w') |
Nico
2016/07/29 22:22:06
doesn't this change behavior on windows?
AWhetter
2016/11/05 23:59:49
Yes but we only ever write text so I think we shou
| |
349 except Exception: | 349 except Exception: |
350 # Don't leave turds behind. | 350 # Don't leave turds behind. |
351 os.unlink(self.tmp_path) | 351 os.unlink(self.tmp_path) |
352 raise | 352 raise |
353 | 353 |
354 def __getattr__(self, attrname): | 354 def __getattr__(self, attrname): |
355 # Delegate everything else to self.tmp_file | 355 # Delegate everything else to self.tmp_file |
356 return getattr(self.tmp_file, attrname) | 356 return getattr(self.tmp_file, attrname) |
357 | 357 |
358 def close(self): | 358 def close(self): |
359 try: | 359 try: |
360 # Close tmp file. | 360 # Close tmp file. |
361 self.tmp_file.close() | 361 self.tmp_file.close() |
362 # Determine if different. | 362 # Determine if different. |
363 same = False | 363 same = False |
364 try: | 364 try: |
365 same = filecmp.cmp(self.tmp_path, filename, False) | 365 same = filecmp.cmp(self.tmp_path, filename, False) |
366 except OSError, e: | 366 except OSError as e: |
367 if e.errno != errno.ENOENT: | 367 if e.errno != errno.ENOENT: |
368 raise | 368 raise |
369 | 369 |
370 if same: | 370 if same: |
371 # The new file is identical to the old one, just get rid of the new | 371 # The new file is identical to the old one, just get rid of the new |
372 # one. | 372 # one. |
373 os.unlink(self.tmp_path) | 373 os.unlink(self.tmp_path) |
374 else: | 374 else: |
375 # The new file is different from the old one, or there is no old one. | 375 # The new file is different from the old one, or there is no old one. |
376 # Rename the new file to the permanent name. | 376 # Rename the new file to the permanent name. |
377 # | 377 # |
378 # tempfile.mkstemp uses an overly restrictive mode, resulting in a | 378 # tempfile.mkstemp uses an overly restrictive mode, resulting in a |
379 # file that can only be read by the owner, regardless of the umask. | 379 # file that can only be read by the owner, regardless of the umask. |
380 # There's no reason to not respect the umask here, which means that | 380 # There's no reason to not respect the umask here, which means that |
381 # an extra hoop is required to fetch it and reset the new file's mode. | 381 # an extra hoop is required to fetch it and reset the new file's mode. |
382 # | 382 # |
383 # No way to get the umask without setting a new one? Set a safe one | 383 # No way to get the umask without setting a new one? Set a safe one |
384 # and then set it back to the old value. | 384 # and then set it back to the old value. |
385 umask = os.umask(077) | 385 umask = os.umask(0o77) |
386 os.umask(umask) | 386 os.umask(umask) |
387 os.chmod(self.tmp_path, 0666 & ~umask) | 387 os.chmod(self.tmp_path, 0o666 & ~umask) |
388 if sys.platform == 'win32' and os.path.exists(filename): | 388 if sys.platform == 'win32' and os.path.exists(filename): |
389 # NOTE: on windows (but not cygwin) rename will not replace an | 389 # NOTE: on windows (but not cygwin) rename will not replace an |
390 # existing file, so it must be preceded with a remove. Sadly there | 390 # existing file, so it must be preceded with a remove. Sadly there |
391 # is no way to make the switch atomic. | 391 # is no way to make the switch atomic. |
392 os.remove(filename) | 392 os.remove(filename) |
393 os.rename(self.tmp_path, filename) | 393 os.rename(self.tmp_path, filename) |
394 except Exception: | 394 except Exception: |
395 # Don't leave turds behind. | 395 # Don't leave turds behind. |
396 os.unlink(self.tmp_path) | 396 os.unlink(self.tmp_path) |
397 raise | 397 raise |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
460 header += "import os;\nos.environ['DEVELOPER_DIR']='%s'\n" \ | 460 header += "import os;\nos.environ['DEVELOPER_DIR']='%s'\n" \ |
461 % mac_toolchain_dir | 461 % mac_toolchain_dir |
462 | 462 |
463 # Add header and write it out. | 463 # Add header and write it out. |
464 tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) | 464 tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) |
465 with open(tool_path, 'w') as tool_file: | 465 with open(tool_path, 'w') as tool_file: |
466 tool_file.write( | 466 tool_file.write( |
467 ''.join([source[0], header] + source[1:])) | 467 ''.join([source[0], header] + source[1:])) |
468 | 468 |
469 # Make file executable. | 469 # Make file executable. |
470 os.chmod(tool_path, 0755) | 470 os.chmod(tool_path, 0o755) |
471 | 471 |
472 | 472 |
473 # From Alex Martelli, | 473 # From Alex Martelli, |
474 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560 | 474 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560 |
475 # ASPN: Python Cookbook: Remove duplicates from a sequence | 475 # ASPN: Python Cookbook: Remove duplicates from a sequence |
476 # First comment, dated 2001/10/13. | 476 # First comment, dated 2001/10/13. |
477 # (Also in the printed Python Cookbook.) | 477 # (Also in the printed Python Cookbook.) |
478 | 478 |
479 def uniquer(seq, idfun=None): | 479 def uniquer(seq, idfun=None): |
480 if idfun is None: | 480 if idfun is None: |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 def CrossCompileRequested(): | 606 def CrossCompileRequested(): |
607 # TODO: figure out how to not build extra host objects in the | 607 # TODO: figure out how to not build extra host objects in the |
608 # non-cross-compile case when this is enabled, and enable unconditionally. | 608 # non-cross-compile case when this is enabled, and enable unconditionally. |
609 return (os.environ.get('GYP_CROSSCOMPILE') or | 609 return (os.environ.get('GYP_CROSSCOMPILE') or |
610 os.environ.get('AR_host') or | 610 os.environ.get('AR_host') or |
611 os.environ.get('CC_host') or | 611 os.environ.get('CC_host') or |
612 os.environ.get('CXX_host') or | 612 os.environ.get('CXX_host') or |
613 os.environ.get('AR_target') or | 613 os.environ.get('AR_target') or |
614 os.environ.get('CC_target') or | 614 os.environ.get('CC_target') or |
615 os.environ.get('CXX_target')) | 615 os.environ.get('CXX_target')) |
OLD | NEW |