[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright 2013 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 | # Usage: |
| 7 | # gclient-new-workdir.py <repository> <new_workdir> [<branch>] |
| 8 | # |
| 9 | |
| 10 | import os |
| 11 | import shutil |
| 12 | import subprocess |
| 13 | import sys |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 14 | import textwrap |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 15 | |
| 16 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 17 | def print_err(msg): |
| 18 | print >> sys.stderr, msg |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 19 | |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 20 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 21 | def usage(msg=None): |
| 22 | |
| 23 | if msg is not None: |
| 24 | print_err('\n' + textwrap.dedent(msg) + '\n') |
| 25 | usage_msg = 'Run without arguments to get usage help.' |
| 26 | else: |
| 27 | usage_msg = '''\ |
| 28 | usage: %s <repository> <new_workdir> |
| 29 | |
| 30 | Clone an existing gclient directory, taking care of all sub-repositories |
| 31 | Works similarly to 'git new-workdir'. |
| 32 | |
| 33 | <repository> should contain a .gclient file |
| 34 | <new_workdir> must not exist |
| 35 | ''' % os.path.basename(sys.argv[0]) |
| 36 | |
| 37 | print_err(textwrap.dedent(usage_msg)) |
| 38 | sys.exit(1) |
| 39 | |
| 40 | |
| 41 | def parse_options(): |
| 42 | if sys.platform == 'win32': |
| 43 | usage('This script cannot run on Windows because it uses symlinks.') |
| 44 | |
| 45 | if len(sys.argv) != 3: |
| 46 | usage() |
| 47 | |
| 48 | repository = os.path.abspath(sys.argv[1]) |
| 49 | new_workdir = sys.argv[2] |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 50 | |
| 51 | if not os.path.exists(repository): |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 52 | usage('Repository does not exist: ' + repository) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 53 | |
| 54 | if os.path.exists(new_workdir): |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 55 | usage('New workdir already exists: ' + new_workdir) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 56 | |
| 57 | return repository, new_workdir |
| 58 | |
| 59 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 60 | def main(): |
| 61 | repository, new_workdir = parse_options() |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 62 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 63 | gclient = os.path.join(repository, '.gclient') |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 64 | if not os.path.exists(gclient): |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 65 | print_err('No .gclient file: ' + gclient) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 66 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 67 | os.makedirs(new_workdir) |
| 68 | os.symlink(gclient, os.path.join(new_workdir, '.gclient')) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 69 | |
| 70 | for root, dirs, _ in os.walk(repository): |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 71 | if '.git' in dirs: |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 72 | workdir = root.replace(repository, new_workdir, 1) |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 73 | make_workdir(os.path.join(root, '.git'), |
| 74 | os.path.join(workdir, '.git')) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 75 | |
| 76 | |
| 77 | def make_workdir(repository, new_workdir): |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 78 | print('Creating: ' + new_workdir) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 79 | os.makedirs(new_workdir) |
| 80 | |
| 81 | GIT_DIRECTORY_WHITELIST = [ |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 82 | 'config', |
| 83 | 'info', |
| 84 | 'hooks', |
| 85 | 'logs/refs', |
| 86 | 'objects', |
| 87 | 'packed-refs', |
| 88 | 'refs', |
| 89 | 'remotes', |
| 90 | 'rr-cache', |
| 91 | 'svn' |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 92 | ] |
| 93 | |
| 94 | for entry in GIT_DIRECTORY_WHITELIST: |
| 95 | make_symlink(repository, new_workdir, entry) |
| 96 | |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 97 | shutil.copy2(os.path.join(repository, 'HEAD'), |
| 98 | os.path.join(new_workdir, 'HEAD')) |
| 99 | subprocess.check_call(['git', 'checkout', '-f'], |
| 100 | cwd=new_workdir.rstrip('.git')) |
[email protected] | 62d817c | 2013-11-05 15:18:13 | [diff] [blame] | 101 | |
| 102 | |
| 103 | def make_symlink(repository, new_workdir, link): |
| 104 | if not os.path.exists(os.path.join(repository, link)): |
| 105 | return |
| 106 | link_dir = os.path.dirname(os.path.join(new_workdir, link)) |
| 107 | if not os.path.exists(link_dir): |
| 108 | os.makedirs(link_dir) |
| 109 | os.symlink(os.path.join(repository, link), os.path.join(new_workdir, link)) |
| 110 | |
| 111 | |
| 112 | if __name__ == '__main__': |
[email protected] | f13c205 | 2013-11-15 20:09:23 | [diff] [blame] | 113 | sys.exit(main()) |