blob: 74c46fd8476fc15c9c0e7a506c3f425e8292a546 [file] [log] [blame]
Viet-Trung Luua0bce062016-02-17 13:29:12 -08001#!/usr/bin/env python
2# Copyright 2016 The Chromium 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"""Builds an SDK (in a specified target directory) from the (current) source
7repository (which should not be dirty) and a given "specification" file."""
8
9
10import argparse
11from pylib.errors import FatalError
12from pylib.git import Git, IsGitTreeDirty, SanityCheckGit, GitLsFiles
13import os
14import shutil
15import sys
16
17
Viet-Trung Luuf3863542016-02-19 14:19:36 -080018def _MakeDirs(*args, **kwargs):
19 """Like |os.makedirs()|, but ignores |OSError| exceptions (it assumes that
20 these are due to the directory already existing)."""
21 try:
22 os.makedirs(*args, **kwargs)
23 except OSError:
24 pass
25
26
Viet-Trung Luu10fc7242016-03-04 15:40:04 -080027def _CopyHelper(source_file, dest_file):
28 """Copies |source_file| to |dest_file|. If |source_file| is user-executable,
29 it will set |dest_file|'s mode to 0755 (user: rwx, group/other: rx);
30 otherwise, it will set it to 0644 (user: rw, group/other: r)."""
31 shutil.copy(source_file, dest_file)
32 if os.stat(source_file).st_mode & 0100:
33 os.chmod(dest_file, 0755)
34 else:
35 os.chmod(dest_file, 0644)
36
37
Viet-Trung Luuf3863542016-02-19 14:19:36 -080038def _CopyDir(source_path, dest_path, **kwargs):
39 """Copies directories from the source git repository (the current working
40 directory should be the root of this repository) to the destination path.
41 |source_path| and the keyword arguments are as for the arguments of
42 |GitLsFiles|. |dest_path| should be the "root" destination path. Note that a
43 file such as <source_path>/foo/bar/baz.quux is copied to
44 <dest_path>/foo/bar/baz.quux."""
Viet-Trung Luua0bce062016-02-17 13:29:12 -080045
46 # Normalize the source path. Note that this strips any trailing '/'.
47 source_path = os.path.normpath(source_path)
48 source_files = GitLsFiles(source_path, **kwargs)
49 for source_file in source_files:
50 rel_path = source_file[len(source_path) + 1:]
51 dest_file = os.path.join(dest_path, rel_path)
Viet-Trung Luuf3863542016-02-19 14:19:36 -080052 _MakeDirs(os.path.dirname(dest_file))
Viet-Trung Luu10fc7242016-03-04 15:40:04 -080053 _CopyHelper(source_file, dest_file)
Viet-Trung Luuf3863542016-02-19 14:19:36 -080054
55
56def _CopyFiles(source_files, dest_path):
57 """Copies a given source file or files from the source git repository to the
58 given destination path (the current working directory should be the root of
59 this repository) |source_files| should either be a relative path to a single
60 file in the source git repository or an iterable of such paths; note that this
61 does not check that files are actually in the git repository (i.e., are
62 tracked)."""
63
64 if type(source_files) is str:
65 source_files = [source_files]
66 _MakeDirs(dest_path)
67 for source_file in source_files:
Viet-Trung Luu10fc7242016-03-04 15:40:04 -080068 _CopyHelper(source_file,
Viet-Trung Luuf3863542016-02-19 14:19:36 -080069 os.path.join(dest_path, os.path.basename(source_file)))
Viet-Trung Luua0bce062016-02-17 13:29:12 -080070
71
Viet-Trung Luu22675d72016-02-25 15:47:12 -080072def _GitGetRevision():
73 """Returns the HEAD revision of the source git repository (the current working
74 directory should be the root of this repository)."""
75
76 return Git("rev-parse", "HEAD").strip()
77
78
79def _ReadFile(source_file):
80 """Reads the specified file from the source git repository (note: It does not
81 verify that |source_file| is actually in the git repository, i.e., is tracked)
82 and returns its contents."""
83
84 with open(source_file, "rb") as f:
85 return f.read()
86
87
88def _WriteFile(dest_file, contents):
89 """Writes the given contents to the specified destination file."""
90
91 _MakeDirs(os.path.dirname(dest_file))
92 with open(dest_file, "wb") as f:
93 return f.write(contents)
94
95
Viet-Trung Luua0bce062016-02-17 13:29:12 -080096def main():
97 parser = argparse.ArgumentParser(
Viet-Trung Luuf3863542016-02-19 14:19:36 -080098 description="Constructs an SDK from a specification.")
Viet-Trung Luua0bce062016-02-17 13:29:12 -080099 parser.add_argument("--allow-dirty-tree", dest="allow_dirty_tree",
100 action="store_true",
101 help="proceed even if the source tree is dirty")
102 parser.add_argument("sdk_spec_file", metavar="sdk_spec_file.sdk",
103 type=argparse.FileType("rb"),
104 help="spec file for the SDK to build")
105 parser.add_argument("target_dir",
106 help="target directory (must not already exist)")
107 args = parser.parse_args()
108
109 target_dir = os.path.abspath(args.target_dir)
110
111 # CD to the "src" directory (we should currently be in src/sdk_build).
112 src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
113 os.chdir(src_dir)
114
115 SanityCheckGit()
116
117 if not args.allow_dirty_tree and IsGitTreeDirty():
118 FatalError("tree appears to be dirty")
119
Viet-Trung Luu10fc7242016-03-04 15:40:04 -0800120 # Set the umask, so that files/directories we create will be world- (and
121 # group-) readable (and executable, for directories).
122 os.umask(0022)
123
Viet-Trung Luua0bce062016-02-17 13:29:12 -0800124 try:
125 os.mkdir(target_dir)
126 except OSError:
127 FatalError("failed to create target directory %s" % target_dir)
128
Viet-Trung Luu22675d72016-02-25 15:47:12 -0800129 # Wrappers to actually write things to the target directory:
130
Viet-Trung Luuf3863542016-02-19 14:19:36 -0800131 def CopyDirToTargetDir(source_path, rel_dest_path, **kwargs):
132 return _CopyDir(source_path, os.path.join(target_dir, rel_dest_path),
133 **kwargs)
134
135 def CopyFilesToTargetDir(source_files, rel_dest_path, **kwargs):
136 return _CopyFiles(source_files, os.path.join(target_dir, rel_dest_path),
Viet-Trung Luua0bce062016-02-17 13:29:12 -0800137 **kwargs)
138
Viet-Trung Luu22675d72016-02-25 15:47:12 -0800139 def WriteFileToTargetDir(rel_dest_file, contents):
140 return _WriteFile(os.path.join(target_dir, rel_dest_file), contents)
141
Viet-Trung Luuf3863542016-02-19 14:19:36 -0800142 execution_globals = {"CopyDir": CopyDirToTargetDir,
143 "CopyFiles": CopyFilesToTargetDir,
Viet-Trung Luua0bce062016-02-17 13:29:12 -0800144 "FatalError": FatalError,
Viet-Trung Luu22675d72016-02-25 15:47:12 -0800145 "GitGetRevision": _GitGetRevision,
146 "GitLsFiles": GitLsFiles,
147 "ReadFile": _ReadFile,
148 "WriteFile": WriteFileToTargetDir}
Viet-Trung Luua0bce062016-02-17 13:29:12 -0800149 exec args.sdk_spec_file in execution_globals
150
151 return 0
152
153
154if __name__ == "__main__":
155 sys.exit(main())