blob: e2a61248c18ce53aa7787e2c64364582f0f988e1 [file] [log] [blame]
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +00001#!/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:
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -07007# gclient-new-workdir.py [options] <repository> <new_workdir>
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +00008#
9
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070010import argparse
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000011import os
12import shutil
13import subprocess
14import sys
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 01:05:38 -070015import textwrap
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000016
sammc@chromium.org900a33f2015-09-29 06:57:09 +000017import git_common
18
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000019
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +000020def parse_options():
21 if sys.platform == 'win32':
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070022 print('ERROR: This script cannot run on Windows because it uses symlinks.')
23 sys.exit(1)
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +000024
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070025 parser = argparse.ArgumentParser(description='''\
26 Clone an existing gclient directory, taking care of all sub-repositories.
27 Works similarly to 'git new-workdir'.''')
28 parser.add_argument('repository', type=os.path.abspath,
29 help='should contain a .gclient file')
30 parser.add_argument('new_workdir', help='must not exist')
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -070031 parser.add_argument('--reflink', action='store_true', default=None,
32 help='''force to use "cp --reflink" for speed and disk
33 space. need supported FS like btrfs or ZFS.''')
34 parser.add_argument('--no-reflink', action='store_false', dest='reflink',
35 help='''force not to use "cp --reflink" even on supported
36 FS like btrfs or ZFS.''')
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070037 args = parser.parse_args()
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +000038
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070039 if not os.path.exists(args.repository):
40 parser.error('Repository "%s" does not exist.' % args.repository)
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000041
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070042 gclient = os.path.join(args.repository, '.gclient')
43 if not os.path.exists(gclient):
44 parser.error('No .gclient file at "%s".' % gclient)
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000045
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070046 if os.path.exists(args.new_workdir):
47 parser.error('New workdir "%s" already exists.' % args.new_workdir)
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000048
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070049 return args
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000050
51
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -070052def support_cow(src, dest):
53 try:
54 subprocess.check_output(['cp', '-a', '--reflink', src, dest],
55 stderr=subprocess.STDOUT)
56 except subprocess.CalledProcessError:
57 return False
58 finally:
Wei-Yin Chen (陳威尹)2fa12032017-06-01 20:30:11 -070059 if os.path.isfile(dest):
60 os.remove(dest)
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -070061 return True
62
63
Wei-Yin Chen (陳威尹)56664462017-05-23 18:37:23 -070064def try_vol_snapshot(src, dest):
65 try:
66 subprocess.check_call(['btrfs', 'subvol', 'snapshot', src, dest],
67 stderr=subprocess.STDOUT)
Wei-Yin Chen (陳威尹)2fa12032017-06-01 20:30:11 -070068 except (subprocess.CalledProcessError, OSError):
Wei-Yin Chen (陳威尹)56664462017-05-23 18:37:23 -070069 return False
70 return True
71
72
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +000073def main():
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070074 args = parse_options()
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000075
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070076 gclient = os.path.join(args.repository, '.gclient')
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -070077 new_gclient = os.path.join(args.new_workdir, '.gclient')
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000078
Wei-Yin Chen (陳威尹)56664462017-05-23 18:37:23 -070079 if try_vol_snapshot(args.repository, args.new_workdir):
80 args.reflink = True
81 else:
82 os.makedirs(args.new_workdir)
83 if args.reflink is None:
84 args.reflink = support_cow(gclient, new_gclient)
85 if args.reflink:
86 print('Copy-on-write support is detected.')
87 os.symlink(gclient, new_gclient)
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +000088
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070089 for root, dirs, _ in os.walk(args.repository):
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +000090 if '.git' in dirs:
Wei-Yin Chen (陳威尹)05203492017-05-11 00:07:53 -070091 workdir = root.replace(args.repository, args.new_workdir, 1)
sammc@chromium.org900a33f2015-09-29 06:57:09 +000092 print('Creating: %s' % workdir)
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -070093
94 if args.reflink:
95 if not os.path.exists(workdir):
96 print('Copying: %s' % workdir)
97 subprocess.check_call(['cp', '-a', '--reflink', root, workdir])
98 shutil.rmtree(os.path.join(workdir, '.git'))
99
sammc@chromium.org900a33f2015-09-29 06:57:09 +0000100 git_common.make_workdir(os.path.join(root, '.git'),
101 os.path.join(workdir, '.git'))
Wei-Yin Chen (陳威尹)704be872017-05-11 00:58:26 -0700102 if args.reflink:
103 subprocess.check_call(['cp', '-a', '--reflink',
104 os.path.join(root, '.git', 'index'),
105 os.path.join(workdir, '.git', 'index')])
106 else:
107 subprocess.check_call(['git', 'checkout', '-f'], cwd=workdir)
108
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 01:05:38 -0700109 if args.reflink:
110 print(textwrap.dedent('''\
111 The repo was copied with copy-on-write, and the artifacts were retained.
112 More details on http://crbug.com/721585.
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +0000113
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 01:05:38 -0700114 Depending on your usage pattern, you might want to do "gn gen"
115 on the output directories. More details: http://crbug.com/723856.'''))
adam.treat@samsung.com62d817c2013-11-05 15:18:13 +0000116
117if __name__ == '__main__':
pgervais@chromium.orgf13c2052013-11-15 20:09:23 +0000118 sys.exit(main())