Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: bootstrap/win/git_bootstrap.py

Issue 2254843004: Add git_bootstrap.py, which bootstraps git on Windows using CIPD (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: fixes Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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'):
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'),
52 '--platform', 'windows-amd64',
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('\\', '\\\\'),
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 scripts = (
136 ('git.bat', 'cmd\\git.exe'),
137 ('gitk.bat', 'cmd\\gitk.exe'),
138 ('ssh.bat', 'usr\\bin\\ssh.exe'),
139 ('ssh-keygen.bat', 'usr\\bin\\ssh-keygen.exe'),
140 )
141 for script in scripts:
142 with open(os.path.join(ROOT_DIR, script[0]), 'w') as f:
143 f.write(git_template.replace('GIT_PROGRAM', script[1]))
144 with open(os.path.join(THIS_DIR, 'git-bash.template.sh')) as f:
145 git_bash_template = f.read()
146 with open(os.path.join(ROOT_DIR, 'git-bash'), 'w') as f:
147 f.write(git_bash_template.replace(
148 'GIT_BIN_DIR', os.path.relpath(git_directory, ROOT_DIR)))
149 shutil.copyfile(
150 os.path.join(THIS_DIR, 'profile.d.python.sh'),
151 os.path.join(git_directory, 'etc', 'profile.d', 'python.sh'))
152
153 git_bat_path = os.path.join(ROOT_DIR, 'git.bat')
154 _check_call([git_bat_path, 'config', '--system', 'core.autocrlf', 'false'])
155 _check_call([git_bat_path, 'config', '--system', 'core.filemode', 'false'])
156 _check_call([git_bat_path, 'config', '--system', 'core.preloadindex', 'true'])
157 _check_call([git_bat_path, 'config', '--system', 'core.fscache', 'true'])
158
159
160 def sync_git_help_files(git_directory):
161 """Updates depot_tools help files inside |git_directory|."""
162 # TODO(phajdan.jr): consider replacing the call with python code.
163 _check_call([
164 'xcopy', '/i', '/q', '/d', '/y',
165 os.path.join(ROOT_DIR, 'man', 'html', '*'),
166 os.path.join(git_directory, 'mingw64', 'share', 'doc', 'git-doc')],
167 stdout=DEVNULL)
168
169
170 def main(argv):
171 parser = argparse.ArgumentParser()
172 parser.add_argument('--cipd-client', help='Path to CIPD client binary.')
173 parser.add_argument('--cipd-cache-directory',
174 help='Path to CIPD cache directory.')
175 parser.add_argument('--force', action='store_true',
176 help='Always re-install git.')
177 parser.add_argument('--verbose', action='store_true')
178 args = parser.parse_args(argv)
179
180 if os.environ.get('WIN_TOOLS_FORCE') == '1':
181 args.force = True
182
183 logging.basicConfig(level=logging.INFO if args.verbose else logging.WARN)
184
185 git_version = get_target_git_version()
186 git_directory = os.path.join(ROOT_DIR, 'git-%s-64_bin' % git_version)
187
188 clean_up_old_git_installations(git_directory)
189
190 if need_to_install_git(args, git_directory):
191 install_git(args, git_version, git_directory)
192
193 sync_git_help_files(git_directory)
194
195 return 0
196
197
198 if __name__ == '__main__':
199 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698