OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 import argparse | |
6 import fnmatch | |
7 import logging | |
8 import os | |
9 import shutil | |
10 import subprocess | |
11 import sys | |
12 import tempfile | |
13 | |
14 | |
15 THIS_DIR = os.path.abspath(os.path.dirname(__file__)) | |
16 ROOT_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..')) | |
17 | |
18 DEVNULL = open(os.devnull, 'w') | |
19 | |
20 | |
21 def _check_call(argv, **kwargs): | |
22 """Wrapper for subprocess.check_call that adds logging.""" | |
23 logging.info('running %r', argv) | |
24 subprocess.check_call(argv, **kwargs) | |
25 | |
26 | |
27 def get_target_git_version(): | |
28 """Returns git version that should be installed.""" | |
29 if os.path.exists(os.path.join(ROOT_DIR, '.git_bleeding_edge')): | |
30 git_version_file = 'git_version_bleeding_edge.txt' | |
31 else: | |
32 git_version_file = 'git_version.txt' | |
33 with open(os.path.join(THIS_DIR, git_version_file)) as f: | |
34 return f.read().strip() | |
35 | |
36 | |
37 def clean_up_old_git_installations(git_directory): | |
38 """Removes git installations other than |git_directory|.""" | |
39 for entry in fnmatch.filter(os.listdir(ROOT_DIR), 'git-*_bin'): | |
iannucci
2016/08/18 18:45:39
I think you just want to use the glob library: htt
| |
40 full_entry = os.path.join(ROOT_DIR, entry) | |
41 if full_entry != git_directory: | |
42 logging.info('Cleaning up old git installation %r', entry) | |
43 shutil.rmtree(full_entry, ignore_errors=True) | |
44 | |
45 | |
46 def bootstrap_cipd(cipd_directory): | |
47 """Bootstraps CIPD client into |cipd_directory|.""" | |
48 _check_call([ | |
49 sys.executable, | |
50 os.path.join(ROOT_DIR, 'recipe_modules', 'cipd', 'resources', | |
51 'bootstrap.py'), | |
iannucci
2016/08/18 18:45:39
Let's add a comment in this bootstrap.py file to m
| |
52 '--platform', 'windows-amd64', | |
iannucci
2016/08/18 18:45:39
why doesn't bootstrap.py automatically compute thi
| |
53 '--dest-directory', cipd_directory | |
54 ]) | |
55 | |
56 | |
57 def cipd_install(args, dest_directory, package, version): | |
58 """Installs CIPD |package| at |version| into |dest_directory|.""" | |
59 manifest_file = tempfile.mktemp() | |
60 try: | |
61 with open(manifest_file, 'w') as f: | |
62 f.write('%s %s\n' % (package, version)) | |
63 | |
64 cipd_args = [ | |
65 args.cipd_client, | |
66 'ensure', | |
67 '-list', manifest_file, | |
68 '-root', dest_directory, | |
69 ] | |
70 if args.cipd_cache_directory: | |
71 cipd_args.extend(['-cache-dir', args.cipd_cache_directory]) | |
72 if args.verbose: | |
73 cipd_args.append('-verbose') | |
74 _check_call(cipd_args) | |
75 finally: | |
76 os.remove(manifest_file) | |
77 | |
78 | |
79 def need_to_install_git(args, git_directory): | |
80 """Returns True if git needs to be installed.""" | |
81 if args.force: | |
82 return True | |
83 git_exe_path = os.path.join(git_directory, 'bin', 'git.exe') | |
84 if not os.path.exists(git_exe_path): | |
85 return True | |
86 if subprocess.call( | |
87 [git_exe_path, '--version'], | |
88 stdout=DEVNULL, stderr=DEVNULL) != 0: | |
89 return True | |
90 for script in ('git.bat', 'gitk.bat', 'ssh.bat', 'ssh-keygen.bat', | |
91 'git-bash'): | |
92 full_path = os.path.join(ROOT_DIR, script) | |
93 if not os.path.exists(full_path): | |
94 return True | |
95 with open(full_path) as f: | |
96 if os.path.relpath(git_directory, ROOT_DIR) not in f.read(): | |
97 return True | |
98 if not os.path.exists(os.path.join( | |
99 git_directory, 'etc', 'profile.d', 'python.sh')): | |
100 return True | |
101 return False | |
102 | |
103 | |
104 def install_git(args, git_version, git_directory): | |
105 """Installs |git_version| into |git_directory|.""" | |
106 if not args.cipd_client: | |
107 bootstrap_cipd(ROOT_DIR) | |
108 args.cipd_client = os.path.join(ROOT_DIR, 'cipd') | |
109 temp_dir = tempfile.mkdtemp() | |
110 try: | |
111 cipd_install(args, | |
112 temp_dir, | |
113 'infra/depot_tools/git_installer/windows-amd64', | |
114 'v' + git_version.replace('.', '_')) | |
115 | |
116 if not os.path.exists(git_directory): | |
117 os.makedirs(git_directory) | |
118 | |
119 # 7-zip has weird expectations for command-line syntax. Pass it as a string | |
120 # to avoid subprocess module quoting breaking it. Also double-escape | |
121 # backslashes in paths. | |
122 _check_call(' '.join([ | |
123 os.path.join(temp_dir, 'git-installer.exe'), | |
124 '-y', | |
125 '-InstallPath="%s"' % git_directory.replace('\\', '\\\\'), | |
126 '-Directory="%s"' % git_directory.replace('\\', '\\\\'), | |
iannucci
2016/08/18 18:45:38
if you use raw strings, you can halve the number o
| |
127 ])) | |
128 finally: | |
129 shutil.rmtree(temp_dir, ignore_errors=True) | |
130 | |
131 with open(os.path.join(THIS_DIR, 'git.template.bat')) as f: | |
132 git_template = f.read() | |
133 git_template = git_template.replace( | |
134 'GIT_BIN_DIR', os.path.relpath(git_directory, ROOT_DIR)) | |
135 with open(os.path.join(ROOT_DIR, 'git.bat'), 'w') as f: | |
136 f.write(git_template.replace('GIT_PROGRAM', 'cmd\\git.exe')) | |
137 with open(os.path.join(ROOT_DIR, 'gitk.bat'), 'w') as f: | |
138 f.write(git_template.replace('GIT_PROGRAM', 'cmd\\gitk.exe')) | |
139 with open(os.path.join(ROOT_DIR, 'ssh.bat'), 'w') as f: | |
140 f.write(git_template.replace('GIT_PROGRAM', 'usr\\bin\\ssh.exe')) | |
141 with open(os.path.join(ROOT_DIR, 'ssh-keygen.bat'), 'w') as f: | |
142 f.write(git_template.replace('GIT_PROGRAM', 'usr\\bin\\ssh-keygen.exe')) | |
iannucci
2016/08/18 18:45:39
can we make this a loop over e.g. a list of tuples
| |
143 with open(os.path.join(THIS_DIR, 'git-bash.template.sh')) as f: | |
144 git_bash_template = f.read() | |
145 with open(os.path.join(ROOT_DIR, 'git-bash'), 'w') as f: | |
146 f.write(git_bash_template.replace( | |
147 'GIT_BIN_DIR', os.path.relpath(git_directory, ROOT_DIR))) | |
148 shutil.copyfile( | |
149 os.path.join(THIS_DIR, 'profile.d.python.sh'), | |
150 os.path.join(git_directory, 'etc', 'profile.d', 'python.sh')) | |
151 | |
152 git_bat_path = os.path.join(ROOT_DIR, 'git.bat') | |
153 _check_call([git_bat_path, 'config', '--system', 'core.autocrlf', 'false']) | |
154 _check_call([git_bat_path, 'config', '--system', 'core.filemode', 'false']) | |
155 _check_call([git_bat_path, 'config', '--system', 'core.preloadindex', 'true']) | |
156 _check_call([git_bat_path, 'config', '--system', 'core.fscache', 'true']) | |
157 | |
158 | |
159 def sync_git_help_files(git_directory): | |
160 """Updates depot_tools help files inside |git_directory|.""" | |
161 _check_call([ | |
162 'xcopy', '/i', '/q', '/d', '/y', | |
163 os.path.join(ROOT_DIR, 'man', 'html', '*'), | |
164 os.path.join(git_directory, 'mingw64', 'share', 'doc', 'git-doc')], | |
165 stdout=DEVNULL) | |
iannucci
2016/08/18 18:45:39
this is a bit janky (it should probably not shell
| |
166 | |
167 | |
168 def main(argv): | |
169 parser = argparse.ArgumentParser() | |
170 parser.add_argument('--cipd-client', help='Path to CIPD client binary.') | |
171 parser.add_argument('--cipd-cache-directory', | |
172 help='Path to CIPD cache directory.') | |
173 parser.add_argument('--force', action='store_true', | |
174 help='Always re-install git.') | |
175 parser.add_argument('--verbose', action='store_true') | |
176 args = parser.parse_args(argv) | |
177 | |
178 if os.environ.get('WIN_TOOLS_FORCE') == '1': | |
179 args.force = True | |
180 | |
181 logging.basicConfig(level=logging.INFO if args.verbose else logging.WARN) | |
182 | |
183 git_version = get_target_git_version() | |
184 git_directory = os.path.join(ROOT_DIR, 'git-%s-64_bin' % git_version) | |
185 | |
186 clean_up_old_git_installations(git_directory) | |
187 | |
188 if need_to_install_git(args, git_directory): | |
189 install_git(args, git_version, git_directory) | |
190 | |
191 sync_git_help_files(git_directory) | |
192 | |
193 return 0 | |
194 | |
195 | |
196 if __name__ == '__main__': | |
197 sys.exit(main(sys.argv[1:])) | |
OLD | NEW |