Bug 1728955: part 4) Add logging for some cases when `nsBaseClipboard::SetData` fails...
[gecko.git] / config / nsinstall.py
blob49d57b795f7f397c246860b029fc08b7be631e8e
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 # This is a partial python port of nsinstall.
6 # It's intended to be used when there's no natively compile nsinstall
7 # available, and doesn't intend to be fully equivalent.
8 # Its major use is for l10n repackaging on systems that don't have
9 # a full build environment set up.
10 # The basic limitation is, it doesn't even try to link and ignores
11 # all related options.
12 from __future__ import absolute_import
13 from __future__ import print_function
14 from optparse import OptionParser
15 import mozfile
16 import os
17 import os.path
18 import six
19 import sys
20 import shutil
23 def _nsinstall_internal(argv):
24 usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
25 p = OptionParser(usage=usage)
27 p.add_option("-D", action="store_true", help="Create a single directory only")
28 p.add_option("-t", action="store_true", help="Preserve time stamp")
29 p.add_option("-m", action="store", help="Set mode", metavar="mode")
30 p.add_option("-d", action="store_true", help="Create directories in target")
31 p.add_option(
32 "-R", action="store_true", help="Use relative symbolic links (ignored)"
34 p.add_option(
35 "-L", action="store", metavar="linkprefix", help="Link prefix (ignored)"
37 p.add_option(
38 "-X",
39 action="append",
40 metavar="file",
41 help="Ignore a file when installing a directory recursively.",
44 # The remaining arguments are not used in our tree, thus they're not
45 # implented.
46 def BadArg(option, opt, value, parser):
47 parser.error("option not supported: {0}".format(opt))
49 p.add_option(
50 "-C", action="callback", metavar="CWD", callback=BadArg, help="NOT SUPPORTED"
52 p.add_option(
53 "-o",
54 action="callback",
55 callback=BadArg,
56 help="Set owner (NOT SUPPORTED)",
57 metavar="owner",
59 p.add_option(
60 "-g",
61 action="callback",
62 callback=BadArg,
63 help="Set group (NOT SUPPORTED)",
64 metavar="group",
67 (options, args) = p.parse_args(argv)
69 if options.m:
70 # mode is specified
71 try:
72 options.m = int(options.m, 8)
73 except Exception:
74 sys.stderr.write("nsinstall: {0} is not a valid mode\n".format(options.m))
75 return 1
77 # just create one directory?
78 def maybe_create_dir(dir, mode, try_again):
79 dir = os.path.abspath(dir)
80 if os.path.exists(dir):
81 if not os.path.isdir(dir):
82 print("nsinstall: {0} is not a directory".format(dir), file=sys.stderr)
83 return 1
84 if mode:
85 os.chmod(dir, mode)
86 return 0
88 try:
89 if mode:
90 os.makedirs(dir, mode)
91 else:
92 os.makedirs(dir)
93 except Exception as e:
94 # We might have hit EEXIST due to a race condition (see bug 463411) -- try again once
95 if try_again:
96 return maybe_create_dir(dir, mode, False)
97 print("nsinstall: failed to create directory {0}: {1}".format(dir, e))
98 return 1
99 else:
100 return 0
102 if options.X:
103 options.X = [os.path.abspath(path) for path in options.X]
105 if options.D:
106 return maybe_create_dir(args[0], options.m, True)
108 # nsinstall arg1 [...] directory
109 if len(args) < 2:
110 p.error("not enough arguments")
112 def copy_all_entries(entries, target):
113 for e in entries:
114 e = os.path.abspath(e)
115 if options.X and e in options.X:
116 continue
118 dest = os.path.join(target, os.path.basename(e))
119 dest = os.path.abspath(dest)
120 handleTarget(e, dest)
121 if options.m:
122 os.chmod(dest, options.m)
124 # set up handler
125 if options.d:
126 # we're supposed to create directories
127 def handleTarget(srcpath, targetpath):
128 # target directory was already created, just use mkdir
129 os.mkdir(targetpath)
131 else:
132 # we're supposed to copy files
133 def handleTarget(srcpath, targetpath):
134 if os.path.isdir(srcpath):
135 if not os.path.exists(targetpath):
136 os.mkdir(targetpath)
137 entries = [os.path.join(srcpath, e) for e in os.listdir(srcpath)]
138 copy_all_entries(entries, targetpath)
139 # options.t is not relevant for directories
140 if options.m:
141 os.chmod(targetpath, options.m)
142 else:
143 if os.path.exists(targetpath):
144 if sys.platform == "win32":
145 mozfile.remove(targetpath)
146 else:
147 os.remove(targetpath)
148 if options.t:
149 shutil.copy2(srcpath, targetpath)
150 else:
151 shutil.copy(srcpath, targetpath)
153 # the last argument is the target directory
154 target = args.pop()
155 # ensure target directory (importantly, we do not apply a mode to the directory
156 # because we want to copy files into it and the mode might be read-only)
157 rv = maybe_create_dir(target, None, True)
158 if rv != 0:
159 return rv
161 copy_all_entries(args, target)
162 return 0
165 # nsinstall as a native command is always UTF-8
168 def nsinstall(argv):
169 return _nsinstall_internal([six.ensure_text(arg, "utf-8") for arg in argv])
172 if __name__ == "__main__":
173 sys.exit(_nsinstall_internal(sys.argv[1:]))