##// END OF EJS Templates
hg: don't attempt to extend `sys.path` with the user site without `APPDATA`...
Matt Harbison -
r48694:769cd570 stable
parent child Browse files
Show More
@@ -1,59 +1,61 b''
1 1 #!/usr/bin/env python3
2 2 #
3 3 # mercurial - scalable distributed SCM
4 4 #
5 5 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9 from __future__ import absolute_import
10 10
11 11 import os
12 12 import sys
13 13
14 14 libdir = '@LIBDIR@'
15 15
16 16 if libdir != '@' 'LIBDIR' '@':
17 17 if not os.path.isabs(libdir):
18 18 libdir = os.path.join(
19 19 os.path.dirname(os.path.realpath(__file__)), libdir
20 20 )
21 21 libdir = os.path.abspath(libdir)
22 22 sys.path.insert(0, libdir)
23 23
24 24 # Make `pip install --user ...` packages available to the official Windows
25 25 # build. Most py2 packaging installs directly into the system python
26 26 # environment, so no changes are necessary for other platforms. The Windows
27 27 # py2 package uses py2exe, which lacks a `site` module. Hardcode it according
28 28 # to the documentation.
29 29 if getattr(sys, 'frozen', None) == 'console_exe':
30 30 vi = sys.version_info
31 sys.path.append(
32 os.path.join(
33 os.environ['APPDATA'],
34 'Python',
35 'Python%d%d' % (vi[0], vi[1]),
36 'site-packages',
31 appdata = os.environ.get('APPDATA')
32 if appdata:
33 sys.path.append(
34 os.path.join(
35 appdata,
36 'Python',
37 'Python%d%d' % (vi[0], vi[1]),
38 'site-packages',
39 )
37 40 )
38 )
39 41
40 42 from hgdemandimport import tracing
41 43
42 44 with tracing.log('hg script'):
43 45 # enable importing on demand to reduce startup time
44 46 try:
45 47 if sys.version_info[0] < 3 or sys.version_info >= (3, 6):
46 48 import hgdemandimport
47 49
48 50 hgdemandimport.enable()
49 51 except ImportError:
50 52 sys.stderr.write(
51 53 "abort: couldn't find mercurial libraries in [%s]\n"
52 54 % ' '.join(sys.path)
53 55 )
54 56 sys.stderr.write("(check your install and PYTHONPATH)\n")
55 57 sys.exit(-1)
56 58
57 59 from mercurial import dispatch
58 60
59 61 dispatch.run()
@@ -1,314 +1,316 b''
1 1 # The following variables can be passed in as parameters:
2 2 #
3 3 # VERSION
4 4 # Version string of program being produced.
5 5 #
6 6 # MSI_NAME
7 7 # Root name of MSI installer.
8 8 #
9 9 # EXTRA_MSI_FEATURES
10 10 # ; delimited string of extra features to advertise in the built MSA.
11 11 #
12 12 # SIGNING_PFX_PATH
13 13 # Path to code signing certificate to use.
14 14 #
15 15 # SIGNING_PFX_PASSWORD
16 16 # Password to code signing PFX file defined by SIGNING_PFX_PATH.
17 17 #
18 18 # SIGNING_SUBJECT_NAME
19 19 # String fragment in code signing certificate subject name used to find
20 20 # code signing certificate in Windows certificate store.
21 21 #
22 22 # TIME_STAMP_SERVER_URL
23 23 # URL of time-stamp token authority (RFC 3161) servers to stamp code signatures.
24 24
25 25 ROOT = CWD + "/../.."
26 26
27 27 VERSION = VARS.get("VERSION", "5.8")
28 28 MSI_NAME = VARS.get("MSI_NAME", "mercurial")
29 29 EXTRA_MSI_FEATURES = VARS.get("EXTRA_MSI_FEATURES")
30 30 SIGNING_PFX_PATH = VARS.get("SIGNING_PFX_PATH")
31 31 SIGNING_PFX_PASSWORD = VARS.get("SIGNING_PFX_PASSWORD", "")
32 32 SIGNING_SUBJECT_NAME = VARS.get("SIGNING_SUBJECT_NAME")
33 33 TIME_STAMP_SERVER_URL = VARS.get("TIME_STAMP_SERVER_URL", "http://timestamp.digicert.com")
34 34
35 35 IS_WINDOWS = "windows" in BUILD_TARGET_TRIPLE
36 36
37 37 # Code to run in Python interpreter.
38 38 RUN_CODE = """
39 39 import os
40 40 import sys
41 41 extra_path = os.environ.get('PYTHONPATH')
42 42 if extra_path is not None:
43 43 # extensions and hooks expect a working python environment
44 44 # We do not prepend the values because the Mercurial library wants to be in
45 45 # the front of the sys.path to avoid picking up other installations.
46 46 sys.path.extend(extra_path.split(os.pathsep))
47 47 # Add user site to sys.path to load extensions without the full path
48 48 if os.name == 'nt':
49 49 vi = sys.version_info
50 sys.path.append(
51 os.path.join(
52 os.environ['APPDATA'],
53 'Python',
54 'Python%d%d' % (vi[0], vi[1]),
55 'site-packages',
50 appdata = os.environ.get('APPDATA')
51 if appdata:
52 sys.path.append(
53 os.path.join(
54 appdata,
55 'Python',
56 'Python%d%d' % (vi[0], vi[1]),
57 'site-packages',
58 )
56 59 )
57 )
58 60 import hgdemandimport;
59 61 hgdemandimport.enable();
60 62 from mercurial import dispatch;
61 63 dispatch.run();
62 64 """
63 65
64 66 set_build_path(ROOT + "/build/pyoxidizer")
65 67
66 68 def make_distribution():
67 69 return default_python_distribution(python_version = "3.9")
68 70
69 71 def resource_callback(policy, resource):
70 72 if not IS_WINDOWS:
71 73 resource.add_location = "in-memory"
72 74 return
73 75
74 76 # We use a custom resource routing policy to influence where things are loaded
75 77 # from.
76 78 #
77 79 # For Python modules and resources, we load from memory if they are in
78 80 # the standard library and from the filesystem if not. This is because
79 81 # parts of Mercurial and some 3rd party packages aren't yet compatible
80 82 # with memory loading.
81 83 #
82 84 # For Python extension modules, we load from the filesystem because
83 85 # this yields greatest compatibility.
84 86 if type(resource) in ("PythonModuleSource", "PythonPackageResource", "PythonPackageDistributionResource"):
85 87 if resource.is_stdlib:
86 88 resource.add_location = "in-memory"
87 89 else:
88 90 resource.add_location = "filesystem-relative:lib"
89 91
90 92 elif type(resource) == "PythonExtensionModule":
91 93 resource.add_location = "filesystem-relative:lib"
92 94
93 95 def make_exe(dist):
94 96 """Builds a Rust-wrapped Mercurial binary."""
95 97 packaging_policy = dist.make_python_packaging_policy()
96 98
97 99 # Extension may depend on any Python functionality. Include all
98 100 # extensions.
99 101 packaging_policy.extension_module_filter = "all"
100 102 packaging_policy.resources_location = "in-memory"
101 103 if IS_WINDOWS:
102 104 packaging_policy.resources_location_fallback = "filesystem-relative:lib"
103 105 packaging_policy.register_resource_callback(resource_callback)
104 106
105 107 config = dist.make_python_interpreter_config()
106 108 config.allocator_backend = "default"
107 109 config.run_command = RUN_CODE
108 110
109 111 # We want to let the user load extensions from the file system
110 112 config.filesystem_importer = True
111 113
112 114 # We need this to make resourceutil happy, since it looks for sys.frozen.
113 115 config.sys_frozen = True
114 116 config.legacy_windows_stdio = True
115 117
116 118 exe = dist.to_python_executable(
117 119 name = "hg",
118 120 packaging_policy = packaging_policy,
119 121 config = config,
120 122 )
121 123
122 124 # Add Mercurial to resources.
123 125 exe.add_python_resources(exe.pip_install(["--verbose", ROOT]))
124 126
125 127 # On Windows, we install extra packages for convenience.
126 128 if IS_WINDOWS:
127 129 exe.add_python_resources(
128 130 exe.pip_install(["-r", ROOT + "/contrib/packaging/requirements-windows-py3.txt"]),
129 131 )
130 132 extra_packages = VARS.get("extra_py_packages", "")
131 133 if extra_packages:
132 134 for extra in extra_packages.split(","):
133 135 extra_src, pkgs = extra.split("=")
134 136 pkgs = pkgs.split(":")
135 137 exe.add_python_resources(exe.read_package_root(extra_src, pkgs))
136 138
137 139 return exe
138 140
139 141 def make_manifest(dist, exe):
140 142 m = FileManifest()
141 143 m.add_python_resource(".", exe)
142 144
143 145 return m
144 146
145 147
146 148 # This adjusts the InstallManifest produced from exe generation to provide
147 149 # additional files found in a Windows install layout.
148 150 def make_windows_install_layout(manifest):
149 151 # Copy various files to new install locations. This can go away once
150 152 # we're using the importlib resource reader.
151 153 RECURSIVE_COPIES = {
152 154 "lib/mercurial/locale/": "locale/",
153 155 "lib/mercurial/templates/": "templates/",
154 156 }
155 157 for (search, replace) in RECURSIVE_COPIES.items():
156 158 for path in manifest.paths():
157 159 if path.startswith(search):
158 160 new_path = path.replace(search, replace)
159 161 print("copy %s to %s" % (path, new_path))
160 162 file = manifest.get_file(path)
161 163 manifest.add_file(file, path = new_path)
162 164
163 165 # Similar to above, but with filename pattern matching.
164 166 # lib/mercurial/helptext/**/*.txt -> helptext/
165 167 # lib/mercurial/defaultrc/*.rc -> defaultrc/
166 168 for path in manifest.paths():
167 169 if path.startswith("lib/mercurial/helptext/") and path.endswith(".txt"):
168 170 new_path = path[len("lib/mercurial/"):]
169 171 elif path.startswith("lib/mercurial/defaultrc/") and path.endswith(".rc"):
170 172 new_path = path[len("lib/mercurial/"):]
171 173 else:
172 174 continue
173 175
174 176 print("copying %s to %s" % (path, new_path))
175 177 manifest.add_file(manifest.get_file(path), path = new_path)
176 178
177 179 extra_install_files = VARS.get("extra_install_files", "")
178 180 if extra_install_files:
179 181 for extra in extra_install_files.split(","):
180 182 print("adding extra files from %s" % extra)
181 183 # TODO: I expected a ** glob to work, but it didn't.
182 184 #
183 185 # TODO: I know this has forward-slash paths. As far as I can tell,
184 186 # backslashes don't ever match glob() expansions in
185 187 # tugger-starlark, even on Windows.
186 188 manifest.add_manifest(glob(include=[extra + "/*/*"], strip_prefix=extra+"/"))
187 189
188 190 # We also install a handful of additional files.
189 191 EXTRA_CONTRIB_FILES = [
190 192 "bash_completion",
191 193 "hgweb.fcgi",
192 194 "hgweb.wsgi",
193 195 "logo-droplets.svg",
194 196 "mercurial.el",
195 197 "mq.el",
196 198 "tcsh_completion",
197 199 "tcsh_completion_build.sh",
198 200 "xml.rnc",
199 201 "zsh_completion",
200 202 ]
201 203
202 204 for f in EXTRA_CONTRIB_FILES:
203 205 manifest.add_file(FileContent(path = ROOT + "/contrib/" + f), directory = "contrib")
204 206
205 207 # Individual files with full source to destination path mapping.
206 208 EXTRA_FILES = {
207 209 "contrib/hgk": "contrib/hgk.tcl",
208 210 "contrib/win32/postinstall.txt": "ReleaseNotes.txt",
209 211 "contrib/win32/ReadMe.html": "ReadMe.html",
210 212 "doc/style.css": "doc/style.css",
211 213 "COPYING": "Copying.txt",
212 214 }
213 215
214 216 for source, dest in EXTRA_FILES.items():
215 217 print("adding extra file %s" % dest)
216 218 manifest.add_file(FileContent(path = ROOT + "/" + source), path = dest)
217 219
218 220 # And finally some wildcard matches.
219 221 manifest.add_manifest(glob(
220 222 include = [ROOT + "/contrib/vim/*"],
221 223 strip_prefix = ROOT + "/"
222 224 ))
223 225 manifest.add_manifest(glob(
224 226 include = [ROOT + "/doc/*.html"],
225 227 strip_prefix = ROOT + "/"
226 228 ))
227 229
228 230 # But we don't ship hg-ssh on Windows, so exclude its documentation.
229 231 manifest.remove("doc/hg-ssh.8.html")
230 232
231 233 return manifest
232 234
233 235
234 236 def make_msi(manifest):
235 237 manifest = make_windows_install_layout(manifest)
236 238
237 239 if "x86_64" in BUILD_TARGET_TRIPLE:
238 240 platform = "x64"
239 241 else:
240 242 platform = "x86"
241 243
242 244 manifest.add_file(
243 245 FileContent(path = ROOT + "/contrib/packaging/wix/COPYING.rtf"),
244 246 path = "COPYING.rtf",
245 247 )
246 248 manifest.remove("Copying.txt")
247 249 manifest.add_file(
248 250 FileContent(path = ROOT + "/contrib/win32/mercurial.ini"),
249 251 path = "defaultrc/mercurial.rc",
250 252 )
251 253 manifest.add_file(
252 254 FileContent(filename = "editor.rc", content = "[ui]\neditor = notepad\n"),
253 255 path = "defaultrc/editor.rc",
254 256 )
255 257
256 258 wix = WiXInstaller("hg", "%s-%s.msi" % (MSI_NAME, VERSION))
257 259
258 260 # Materialize files in the manifest to the install layout.
259 261 wix.add_install_files(manifest)
260 262
261 263 # From mercurial.wxs.
262 264 wix.install_files_root_directory_id = "INSTALLDIR"
263 265
264 266 # Pull in our custom .wxs files.
265 267 defines = {
266 268 "PyOxidizer": "1",
267 269 "Platform": platform,
268 270 "Version": VERSION,
269 271 "Comments": "Installs Mercurial version %s" % VERSION,
270 272 "PythonVersion": "3",
271 273 "MercurialHasLib": "1",
272 274 }
273 275
274 276 if EXTRA_MSI_FEATURES:
275 277 defines["MercurialExtraFeatures"] = EXTRA_MSI_FEATURES
276 278
277 279 wix.add_wxs_file(
278 280 ROOT + "/contrib/packaging/wix/mercurial.wxs",
279 281 preprocessor_parameters=defines,
280 282 )
281 283
282 284 # Our .wxs references to other files. Pull those into the build environment.
283 285 for f in ("defines.wxi", "guids.wxi", "COPYING.rtf"):
284 286 wix.add_build_file(f, ROOT + "/contrib/packaging/wix/" + f)
285 287
286 288 wix.add_build_file("mercurial.ico", ROOT + "/contrib/win32/mercurial.ico")
287 289
288 290 return wix
289 291
290 292
291 293 def register_code_signers():
292 294 if not IS_WINDOWS:
293 295 return
294 296
295 297 if SIGNING_PFX_PATH:
296 298 signer = code_signer_from_pfx_file(SIGNING_PFX_PATH, SIGNING_PFX_PASSWORD)
297 299 elif SIGNING_SUBJECT_NAME:
298 300 signer = code_signer_from_windows_store_subject(SIGNING_SUBJECT_NAME)
299 301 else:
300 302 signer = None
301 303
302 304 if signer:
303 305 signer.set_time_stamp_server(TIME_STAMP_SERVER_URL)
304 306 signer.activate()
305 307
306 308
307 309 register_code_signers()
308 310
309 311 register_target("distribution", make_distribution)
310 312 register_target("exe", make_exe, depends = ["distribution"])
311 313 register_target("app", make_manifest, depends = ["distribution", "exe"], default = True)
312 314 register_target("msi", make_msi, depends = ["app"])
313 315
314 316 resolve_targets()
General Comments 0
You need to be logged in to leave comments. Login now