no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / config / nsinstall.py
blob200a7ee19c918a007f7b1df63600147eb1e8d3bb
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 import os
13 import os.path
14 import shutil
15 import sys
16 from optparse import OptionParser
18 import mozfile
19 import six
22 def _nsinstall_internal(argv):
23 usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
24 p = OptionParser(usage=usage)
26 p.add_option("-D", action="store_true", help="Create a single directory only")
27 p.add_option("-t", action="store_true", help="Preserve time stamp")
28 p.add_option("-m", action="store", help="Set mode", metavar="mode")
29 p.add_option("-d", action="store_true", help="Create directories in target")
30 p.add_option(
31 "-R", action="store_true", help="Use relative symbolic links (ignored)"
33 p.add_option(
34 "-L", action="store", metavar="linkprefix", help="Link prefix (ignored)"
36 p.add_option(
37 "-X",
38 action="append",
39 metavar="file",
40 help="Ignore a file when installing a directory recursively.",
43 # The remaining arguments are not used in our tree, thus they're not
44 # implented.
45 def BadArg(option, opt, value, parser):
46 parser.error("option not supported: {0}".format(opt))
48 p.add_option(
49 "-C", action="callback", metavar="CWD", callback=BadArg, help="NOT SUPPORTED"
51 p.add_option(
52 "-o",
53 action="callback",
54 callback=BadArg,
55 help="Set owner (NOT SUPPORTED)",
56 metavar="owner",
58 p.add_option(
59 "-g",
60 action="callback",
61 callback=BadArg,
62 help="Set group (NOT SUPPORTED)",
63 metavar="group",
66 (options, args) = p.parse_args(argv)
68 if options.m:
69 # mode is specified
70 try:
71 options.m = int(options.m, 8)
72 except Exception:
73 sys.stderr.write("nsinstall: {0} is not a valid mode\n".format(options.m))
74 return 1
76 # just create one directory?
77 def maybe_create_dir(dir, mode, try_again):
78 dir = os.path.abspath(dir)
79 if os.path.exists(dir):
80 if not os.path.isdir(dir):
81 print("nsinstall: {0} is not a directory".format(dir), file=sys.stderr)
82 return 1
83 if mode:
84 os.chmod(dir, mode)
85 return 0
87 try:
88 if mode:
89 os.makedirs(dir, mode)
90 else:
91 os.makedirs(dir)
92 except Exception as e:
93 # We might have hit EEXIST due to a race condition (see bug 463411) -- try again once
94 if try_again:
95 return maybe_create_dir(dir, mode, False)
96 print("nsinstall: failed to create directory {0}: {1}".format(dir, e))
97 return 1
98 else:
99 return 0
101 if options.X:
102 options.X = [os.path.abspath(path) for path in options.X]
104 if options.D:
105 return maybe_create_dir(args[0], options.m, True)
107 # nsinstall arg1 [...] directory
108 if len(args) < 2:
109 p.error("not enough arguments")
111 def copy_all_entries(entries, target):
112 for e in entries:
113 e = os.path.abspath(e)
114 if options.X and e in options.X:
115 continue
117 dest = os.path.join(target, os.path.basename(e))
118 dest = os.path.abspath(dest)
119 handleTarget(e, dest)
120 if options.m:
121 os.chmod(dest, options.m)
123 # set up handler
124 if options.d:
125 # we're supposed to create directories
126 def handleTarget(srcpath, targetpath):
127 # target directory was already created, just use mkdir
128 os.mkdir(targetpath)
130 else:
131 # we're supposed to copy files
132 def handleTarget(srcpath, targetpath):
133 if os.path.isdir(srcpath):
134 if not os.path.exists(targetpath):
135 os.mkdir(targetpath)
136 entries = [os.path.join(srcpath, e) for e in os.listdir(srcpath)]
137 copy_all_entries(entries, targetpath)
138 # options.t is not relevant for directories
139 if options.m:
140 os.chmod(targetpath, options.m)
141 else:
142 if os.path.exists(targetpath):
143 if sys.platform == "win32":
144 mozfile.remove(targetpath)
145 else:
146 os.remove(targetpath)
147 if options.t:
148 shutil.copy2(srcpath, targetpath)
149 else:
150 shutil.copy(srcpath, targetpath)
152 # the last argument is the target directory
153 target = args.pop()
154 # ensure target directory (importantly, we do not apply a mode to the directory
155 # because we want to copy files into it and the mode might be read-only)
156 rv = maybe_create_dir(target, None, True)
157 if rv != 0:
158 return rv
160 copy_all_entries(args, target)
161 return 0
164 # nsinstall as a native command is always UTF-8
167 def nsinstall(argv):
168 return _nsinstall_internal([six.ensure_text(arg, "utf-8") for arg in argv])
171 if __name__ == "__main__":
172 sys.exit(_nsinstall_internal(sys.argv[1:]))