cb9b839cecb7d7e1576b7c3efd950c5157356fbc
[platform/framework/web/crosswalk.git] / src / native_client / build / file_tools.py
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Convience stand-alone file operations."""
7
8
9 import os
10 import shutil
11 import sys
12 import tempfile
13
14
15 def AtomicWriteFile(data, filename):
16   """Write a file atomically.
17
18   NOTE: Not atomic on Windows!
19   Args:
20     data: String to write to the file.
21     filename: Filename to write.
22   """
23   filename = os.path.abspath(filename)
24   handle, temp_file = tempfile.mkstemp(
25       prefix='atomic_write', suffix='.tmp',
26       dir=os.path.dirname(filename))
27   fh = os.fdopen(handle, 'wb')
28   fh.write(data)
29   fh.close()
30   # Window's can't move into place atomically, delete first.
31   if sys.platform in ['win32', 'cygwin']:
32     try:
33       os.remove(filename)
34     except OSError:
35       pass
36   os.rename(temp_file, filename)
37
38
39 def WriteFile(data, filename):
40   """Write a file in one step.
41
42   Args:
43     data: String to write to the file.
44     filename: Filename to write.
45   """
46   fh = open(filename, 'wb')
47   fh.write(data)
48   fh.close()
49
50
51 def ReadFile(filename):
52   """Read a file in one step.
53
54   Args:
55     filename: Filename to read.
56   Returns:
57     String containing complete file.
58   """
59   fh = open(filename, 'rb')
60   data = fh.read()
61   fh.close()
62   return data
63
64
65 class ExecutableNotFound(Exception):
66   pass
67
68
69 def Which(command, paths=None, require_executable=True):
70   """Find the absolute path of a command in the current PATH.
71
72   Args:
73     command: Command name to look for.
74     paths: Optional paths to search.
75   Returns:
76     Absolute path of the command (first one found),
77     or default to a bare command if nothing is found.
78   """
79   if paths is None:
80     paths = os.environ.get('PATH', '').split(os.pathsep)
81   exe_suffixes = ['']
82   if sys.platform == 'win32':
83     exe_suffixes += ['.exe']
84   for p in paths:
85     np = os.path.abspath(os.path.join(p, command))
86     for suffix in exe_suffixes:
87       full_path = np + suffix
88       if (os.path.isfile(full_path) and
89           (not require_executable or os.access(full_path, os.X_OK))):
90         return full_path
91   raise ExecutableNotFound('Unable to find: ' + command)
92
93
94 def MakeDirectoryIfAbsent(path):
95   """Create a directory if it doesn't already exist.
96
97   Args:
98     path: Directory to create.
99   """
100   if not os.path.exists(path):
101     os.mkdir(path)
102
103
104 def RemoveDirectoryIfPresent(path):
105   """Remove a directory if it exists.
106
107   Args:
108     path: Directory to remove.
109   """
110
111   # On Windows, attempts to remove read-only files get Error 5. This
112   # error handler fixes the permissions and retries the removal.
113   def onerror_readonly(func, path, exc_info):
114     import stat
115     if not os.access(path, os.W_OK):
116       os.chmod(path, stat.S_IWUSR)
117       func(path)
118
119   if os.path.exists(path):
120     shutil.rmtree(path, onerror=onerror_readonly)