blob: 0087aef63a17871920552a962625aa435317866b [file] [log] [blame]
[email protected]62d817c2013-11-05 15:18:131#!/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 07:07:537# gclient-new-workdir.py [options] <repository> <new_workdir>
[email protected]62d817c2013-11-05 15:18:138#
9
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5310import argparse
[email protected]62d817c2013-11-05 15:18:1311import os
12import shutil
13import subprocess
14import sys
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 08:05:3815import textwrap
[email protected]62d817c2013-11-05 15:18:1316
[email protected]900a33f2015-09-29 06:57:0917import git_common
18
[email protected]62d817c2013-11-05 15:18:1319
[email protected]f13c2052013-11-15 20:09:2320def parse_options():
21 if sys.platform == 'win32':
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5322 print('ERROR: This script cannot run on Windows because it uses symlinks.')
23 sys.exit(1)
[email protected]f13c2052013-11-15 20:09:2324
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5325 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 07:58:2631 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 07:07:5337 args = parser.parse_args()
[email protected]f13c2052013-11-15 20:09:2338
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5339 if not os.path.exists(args.repository):
40 parser.error('Repository "%s" does not exist.' % args.repository)
[email protected]62d817c2013-11-05 15:18:1341
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5342 gclient = os.path.join(args.repository, '.gclient')
43 if not os.path.exists(gclient):
44 parser.error('No .gclient file at "%s".' % gclient)
[email protected]62d817c2013-11-05 15:18:1345
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5346 if os.path.exists(args.new_workdir):
47 parser.error('New workdir "%s" already exists.' % args.new_workdir)
[email protected]62d817c2013-11-05 15:18:1348
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5349 return args
[email protected]62d817c2013-11-05 15:18:1350
51
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:2652def support_cow(src, dest):
Henrique Ferreirofd4ad242018-01-10 11:19:1853 # 'cp --reflink' always succeeds when 'src' is a symlink or a directory
54 assert os.path.isfile(src) and not os.path.islink(src)
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:2655 try:
56 subprocess.check_output(['cp', '-a', '--reflink', src, dest],
57 stderr=subprocess.STDOUT)
58 except subprocess.CalledProcessError:
59 return False
60 finally:
Wei-Yin Chen (陳威尹)2fa12032017-06-02 03:30:1161 if os.path.isfile(dest):
62 os.remove(dest)
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:2663 return True
64
65
Wei-Yin Chen (陳威尹)56664462017-05-24 01:37:2366def try_vol_snapshot(src, dest):
67 try:
68 subprocess.check_call(['btrfs', 'subvol', 'snapshot', src, dest],
69 stderr=subprocess.STDOUT)
Wei-Yin Chen (陳威尹)2fa12032017-06-02 03:30:1170 except (subprocess.CalledProcessError, OSError):
Wei-Yin Chen (陳威尹)56664462017-05-24 01:37:2371 return False
72 return True
73
74
[email protected]f13c2052013-11-15 20:09:2375def main():
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5376 args = parse_options()
[email protected]62d817c2013-11-05 15:18:1377
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5378 gclient = os.path.join(args.repository, '.gclient')
Henrique Ferreirofd4ad242018-01-10 11:19:1879 if os.path.islink(gclient):
Henrique Ferreiroaea45d22018-02-19 08:48:3680 gclient = os.path.realpath(gclient)
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:2681 new_gclient = os.path.join(args.new_workdir, '.gclient')
[email protected]62d817c2013-11-05 15:18:1382
Wei-Yin Chen (陳威尹)56664462017-05-24 01:37:2383 if try_vol_snapshot(args.repository, args.new_workdir):
84 args.reflink = True
85 else:
86 os.makedirs(args.new_workdir)
87 if args.reflink is None:
88 args.reflink = support_cow(gclient, new_gclient)
89 if args.reflink:
90 print('Copy-on-write support is detected.')
91 os.symlink(gclient, new_gclient)
[email protected]62d817c2013-11-05 15:18:1392
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5393 for root, dirs, _ in os.walk(args.repository):
[email protected]f13c2052013-11-15 20:09:2394 if '.git' in dirs:
Wei-Yin Chen (陳威尹)05203492017-05-11 07:07:5395 workdir = root.replace(args.repository, args.new_workdir, 1)
[email protected]900a33f2015-09-29 06:57:0996 print('Creating: %s' % workdir)
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:2697
98 if args.reflink:
99 if not os.path.exists(workdir):
100 print('Copying: %s' % workdir)
101 subprocess.check_call(['cp', '-a', '--reflink', root, workdir])
102 shutil.rmtree(os.path.join(workdir, '.git'))
103
[email protected]900a33f2015-09-29 06:57:09104 git_common.make_workdir(os.path.join(root, '.git'),
105 os.path.join(workdir, '.git'))
Wei-Yin Chen (陳威尹)704be872017-05-11 07:58:26106 if args.reflink:
107 subprocess.check_call(['cp', '-a', '--reflink',
108 os.path.join(root, '.git', 'index'),
109 os.path.join(workdir, '.git', 'index')])
110 else:
111 subprocess.check_call(['git', 'checkout', '-f'], cwd=workdir)
112
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 08:05:38113 if args.reflink:
114 print(textwrap.dedent('''\
115 The repo was copied with copy-on-write, and the artifacts were retained.
116 More details on http://crbug.com/721585.
[email protected]62d817c2013-11-05 15:18:13117
Wei-Yin Chen (陳威尹)56e4ad92017-05-23 08:05:38118 Depending on your usage pattern, you might want to do "gn gen"
119 on the output directories. More details: http://crbug.com/723856.'''))
[email protected]62d817c2013-11-05 15:18:13120
121if __name__ == '__main__':
[email protected]f13c2052013-11-15 20:09:23122 sys.exit(main())