Upload upstream chromium 76.0.3809.146
[platform/framework/web/chromium-efl.git] / build / symlink.py
1 #!/usr/bin/env python
2 # Copyright (c) 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 description = """
7 Make a symlink and optionally touch a file (to handle dependencies).
8 """
9 usage = "%prog [options] source[ source ...] linkname"
10 epilog = """
11 A sym link to source is created at linkname. If multiple sources are specfied,
12 then linkname is assumed to be a directory, and will contain all the links to
13 the sources (basenames identical to their source).
14
15 On Windows, this will use hard links (mklink /H) to avoid requiring elevation.
16 This means that if the original is deleted and replaced, the link will still
17 have the old contents. This is not expected to interfere with the Chromium
18 build.
19 """
20
21 import errno
22 import optparse
23 import os.path
24 import shutil
25 import subprocess
26 import sys
27
28
29 def Main(argv):
30   parser = optparse.OptionParser(usage=usage, description=description,
31                                  epilog=epilog)
32   parser.add_option('-f', '--force', action='store_true')
33   parser.add_option('--touch')
34
35   options, args = parser.parse_args(argv[1:])
36   if len(args) < 2:
37     parser.error('at least two arguments required.')
38
39   target = args[-1]
40   sources = args[:-1]
41   for s in sources:
42     t = os.path.join(target, os.path.basename(s))
43     if len(sources) == 1 and not os.path.isdir(target):
44       t = target
45     t = os.path.expanduser(t)
46     if os.path.realpath(t) == os.path.realpath(s):
47       continue
48     try:
49       # N.B. Python 2.x does not have os.symlink for Windows.
50       #   Python 3 has os.symlink for Windows, but requires either the admin-
51       #   granted privilege SeCreateSymbolicLinkPrivilege or, as of Windows 10
52       #   1703, that Developer Mode be enabled. Hard links and junctions do not
53       #   require any extra privileges to create.
54       if os.name == 'nt':
55         # mklink does not tolerate /-delimited path names.
56         t = t.replace('/', '\\')
57         s = s.replace('/', '\\')
58         # N.B. This tool only handles file hardlinks, not directory junctions.
59         subprocess.check_output(['cmd.exe', '/c', 'mklink', '/H', t, s],
60                                 stderr=subprocess.STDOUT)
61       else:
62         os.symlink(s, t)
63     except OSError, e:
64       if e.errno == errno.EEXIST and options.force:
65         if os.path.isdir(t):
66           shutil.rmtree(t, ignore_errors=True)
67         else:
68           os.remove(t)
69         os.symlink(s, t)
70       else:
71         raise
72     except subprocess.CalledProcessError, e:
73       # Since subprocess.check_output does not return an easily checked error
74       # number, in the 'force' case always assume it is 'file already exists'
75       # and retry.
76       if options.force:
77         if os.path.isdir(t):
78           shutil.rmtree(t, ignore_errors=True)
79         else:
80           os.remove(t)
81         subprocess.check_output(e.cmd, stderr=subprocess.STDOUT)
82       else:
83         raise
84
85
86   if options.touch:
87     with open(options.touch, 'w') as f:
88       pass
89
90
91 if __name__ == '__main__':
92   sys.exit(Main(sys.argv))