Upstream version 5.34.104.0
[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)
121
122
123 def CopyTree(src, dst):
124   """Recursively copy the items in the src directory to the dst directory.
125
126   Unlike shutil.copytree, the destination directory and any subdirectories and
127   files may exist. Existing directories are left untouched, and existing files
128   are removed and copied from the source using shutil.copy2. It is also not
129   symlink-aware.
130
131   Args:
132     src: Source. Must be an existing directory.
133     dst: Destination directory. If it exists, must be a directory. Otherwise it
134          will be created, along with parent directories.
135   """
136   if not os.path.isdir(dst):
137     os.makedirs(dst)
138   for root, dirs, files in os.walk(src):
139     relroot = os.path.relpath(root, src)
140     dstroot = os.path.join(dst, relroot)
141     for d in dirs:
142       dstdir = os.path.join(dstroot, d)
143       if not os.path.isdir(dstdir):
144         os.mkdir(dstdir)
145     for f in files:
146       dstfile = os.path.join(dstroot, f)
147       if os.path.isfile(dstfile):
148         os.remove(dstfile)
149       shutil.copy2(os.path.join(root, f), dstfile)