Edward Lemur | 3c81495 | 2019-08-12 19:43:00 +0000 | [diff] [blame] | 1 | #!/usr/bin/env vpython |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 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: |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 7 | # gclient-new-workdir.py [options] <repository> <new_workdir> |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 8 | # |
| 9 | |
Raul Tambre | 80ee78e | 2019-05-06 22:41:05 +0000 | [diff] [blame] | 10 | from __future__ import print_function |
| 11 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 12 | import argparse |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 13 | import os |
| 14 | import shutil |
| 15 | import subprocess |
| 16 | import sys |
Wei-Yin Chen (陳威尹) | 56e4ad9 | 2017-05-23 01:05:38 -0700 | [diff] [blame] | 17 | import textwrap |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 18 | |
sammc@chromium.org | 900a33f | 2015-09-29 06:57:09 +0000 | [diff] [blame] | 19 | import git_common |
| 20 | |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 21 | |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 22 | def parse_options(): |
| 23 | if sys.platform == 'win32': |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 24 | print('ERROR: This script cannot run on Windows because it uses symlinks.') |
| 25 | sys.exit(1) |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 26 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 27 | parser = argparse.ArgumentParser(description='''\ |
| 28 | Clone an existing gclient directory, taking care of all sub-repositories. |
| 29 | Works similarly to 'git new-workdir'.''') |
| 30 | parser.add_argument('repository', type=os.path.abspath, |
| 31 | help='should contain a .gclient file') |
| 32 | parser.add_argument('new_workdir', help='must not exist') |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 33 | parser.add_argument('--reflink', action='store_true', default=None, |
| 34 | help='''force to use "cp --reflink" for speed and disk |
| 35 | space. need supported FS like btrfs or ZFS.''') |
| 36 | parser.add_argument('--no-reflink', action='store_false', dest='reflink', |
| 37 | help='''force not to use "cp --reflink" even on supported |
| 38 | FS like btrfs or ZFS.''') |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 39 | args = parser.parse_args() |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 40 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 41 | if not os.path.exists(args.repository): |
| 42 | parser.error('Repository "%s" does not exist.' % args.repository) |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 43 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 44 | gclient = os.path.join(args.repository, '.gclient') |
| 45 | if not os.path.exists(gclient): |
| 46 | parser.error('No .gclient file at "%s".' % gclient) |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 47 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 48 | if os.path.exists(args.new_workdir): |
| 49 | parser.error('New workdir "%s" already exists.' % args.new_workdir) |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 50 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 51 | return args |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 52 | |
| 53 | |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 54 | def support_cow(src, dest): |
Henrique Ferreiro | fd4ad24 | 2018-01-10 12:19:18 +0100 | [diff] [blame] | 55 | # 'cp --reflink' always succeeds when 'src' is a symlink or a directory |
| 56 | assert os.path.isfile(src) and not os.path.islink(src) |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 57 | try: |
| 58 | subprocess.check_output(['cp', '-a', '--reflink', src, dest], |
| 59 | stderr=subprocess.STDOUT) |
| 60 | except subprocess.CalledProcessError: |
| 61 | return False |
| 62 | finally: |
Wei-Yin Chen (陳威尹) | 2fa1203 | 2017-06-01 20:30:11 -0700 | [diff] [blame] | 63 | if os.path.isfile(dest): |
| 64 | os.remove(dest) |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 65 | return True |
| 66 | |
| 67 | |
Wei-Yin Chen (陳威尹) | 5666446 | 2017-05-23 18:37:23 -0700 | [diff] [blame] | 68 | def try_vol_snapshot(src, dest): |
| 69 | try: |
| 70 | subprocess.check_call(['btrfs', 'subvol', 'snapshot', src, dest], |
| 71 | stderr=subprocess.STDOUT) |
Wei-Yin Chen (陳威尹) | 2fa1203 | 2017-06-01 20:30:11 -0700 | [diff] [blame] | 72 | except (subprocess.CalledProcessError, OSError): |
Wei-Yin Chen (陳威尹) | 5666446 | 2017-05-23 18:37:23 -0700 | [diff] [blame] | 73 | return False |
| 74 | return True |
| 75 | |
| 76 | |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 77 | def main(): |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 78 | args = parse_options() |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 79 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 80 | gclient = os.path.join(args.repository, '.gclient') |
Henrique Ferreiro | fd4ad24 | 2018-01-10 12:19:18 +0100 | [diff] [blame] | 81 | if os.path.islink(gclient): |
Henrique Ferreiro | aea45d2 | 2018-02-19 09:48:36 +0100 | [diff] [blame] | 82 | gclient = os.path.realpath(gclient) |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 83 | new_gclient = os.path.join(args.new_workdir, '.gclient') |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 84 | |
Wei-Yin Chen (陳威尹) | 5666446 | 2017-05-23 18:37:23 -0700 | [diff] [blame] | 85 | if try_vol_snapshot(args.repository, args.new_workdir): |
| 86 | args.reflink = True |
| 87 | else: |
| 88 | os.makedirs(args.new_workdir) |
| 89 | if args.reflink is None: |
| 90 | args.reflink = support_cow(gclient, new_gclient) |
| 91 | if args.reflink: |
| 92 | print('Copy-on-write support is detected.') |
| 93 | os.symlink(gclient, new_gclient) |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 94 | |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 95 | for root, dirs, _ in os.walk(args.repository): |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 96 | if '.git' in dirs: |
Wei-Yin Chen (陳威尹) | 0520349 | 2017-05-11 00:07:53 -0700 | [diff] [blame] | 97 | workdir = root.replace(args.repository, args.new_workdir, 1) |
sammc@chromium.org | 900a33f | 2015-09-29 06:57:09 +0000 | [diff] [blame] | 98 | print('Creating: %s' % workdir) |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 99 | |
| 100 | if args.reflink: |
| 101 | if not os.path.exists(workdir): |
| 102 | print('Copying: %s' % workdir) |
| 103 | subprocess.check_call(['cp', '-a', '--reflink', root, workdir]) |
| 104 | shutil.rmtree(os.path.join(workdir, '.git')) |
| 105 | |
sammc@chromium.org | 900a33f | 2015-09-29 06:57:09 +0000 | [diff] [blame] | 106 | git_common.make_workdir(os.path.join(root, '.git'), |
| 107 | os.path.join(workdir, '.git')) |
Wei-Yin Chen (陳威尹) | 704be87 | 2017-05-11 00:58:26 -0700 | [diff] [blame] | 108 | if args.reflink: |
| 109 | subprocess.check_call(['cp', '-a', '--reflink', |
| 110 | os.path.join(root, '.git', 'index'), |
| 111 | os.path.join(workdir, '.git', 'index')]) |
| 112 | else: |
| 113 | subprocess.check_call(['git', 'checkout', '-f'], cwd=workdir) |
| 114 | |
Wei-Yin Chen (陳威尹) | 56e4ad9 | 2017-05-23 01:05:38 -0700 | [diff] [blame] | 115 | if args.reflink: |
| 116 | print(textwrap.dedent('''\ |
| 117 | The repo was copied with copy-on-write, and the artifacts were retained. |
| 118 | More details on http://crbug.com/721585. |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 119 | |
Wei-Yin Chen (陳威尹) | 56e4ad9 | 2017-05-23 01:05:38 -0700 | [diff] [blame] | 120 | Depending on your usage pattern, you might want to do "gn gen" |
| 121 | on the output directories. More details: http://crbug.com/723856.''')) |
adam.treat@samsung.com | 62d817c | 2013-11-05 15:18:13 +0000 | [diff] [blame] | 122 | |
| 123 | if __name__ == '__main__': |
pgervais@chromium.org | f13c205 | 2013-11-15 20:09:23 +0000 | [diff] [blame] | 124 | sys.exit(main()) |