##// END OF EJS Templates
packaging: stage installed files for Inno...
Gregory Szorc -
r43916:d053d3f1 default
parent child Browse files
Show More
@@ -14,7 +14,10 b' import subprocess'
14 14
15 15 import jinja2
16 16
17 from .py2exe import build_py2exe
17 from .py2exe import (
18 build_py2exe,
19 stage_install,
20 )
18 21 from .util import find_vc_runtime_files
19 22
20 23 EXTRA_PACKAGES = {
@@ -24,6 +27,11 b' EXTRA_PACKAGES = {'
24 27 'win32ctypes',
25 28 }
26 29
30 PACKAGE_FILES_METADATA = {
31 'ReadMe.html': 'Flags: isreadme',
32 'hg.exe': "AfterInstall: Touch('{app}\\hg.exe.local')",
33 }
34
27 35
28 36 def build(
29 37 source_dir: pathlib.Path,
@@ -47,6 +55,7 b' def build('
47 55 arch = 'x64' if vc_x64 else 'x86'
48 56 inno_source_dir = source_dir / 'contrib' / 'packaging' / 'inno'
49 57 inno_build_dir = build_dir / ('inno-%s' % arch)
58 staging_dir = inno_build_dir / 'stage'
50 59
51 60 requirements_txt = (
52 61 source_dir / 'contrib' / 'packaging' / 'inno' / 'requirements.txt'
@@ -63,6 +72,15 b' def build('
63 72 extra_packages=EXTRA_PACKAGES,
64 73 )
65 74
75 # Purge the staging directory for every build so packaging is
76 # pristine.
77 if staging_dir.exists():
78 print('purging %s' % staging_dir)
79 shutil.rmtree(staging_dir)
80
81 # Now assemble all the packaged files into the staging directory.
82 stage_install(source_dir, staging_dir)
83
66 84 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
67 85 for f in find_vc_runtime_files(vc_x64):
68 86 if f.name.endswith('.manifest'):
@@ -70,11 +88,34 b' def build('
70 88 else:
71 89 basename = f.name
72 90
73 dest_path = source_dir / 'dist' / basename
91 dest_path = staging_dir / basename
74 92
75 93 print('copying %s to %s' % (f, dest_path))
76 94 shutil.copyfile(f, dest_path)
77 95
96 # The final package layout is simply a mirror of the staging directory.
97 package_files = []
98 for root, dirs, files in os.walk(staging_dir):
99 dirs.sort()
100
101 root = pathlib.Path(root)
102
103 for f in sorted(files):
104 full = root / f
105 rel = full.relative_to(staging_dir)
106 if str(rel.parent) == '.':
107 dest_dir = '{app}'
108 else:
109 dest_dir = '{app}\\%s' % rel.parent
110
111 package_files.append(
112 {
113 'source': rel,
114 'dest_dir': dest_dir,
115 'metadata': PACKAGE_FILES_METADATA.get(str(rel), None),
116 }
117 )
118
78 119 print('creating installer')
79 120
80 121 # Install Inno files by rendering a template.
@@ -93,11 +134,17 b' def build('
93 134 % (e.name, e.lineno, e.message,)
94 135 )
95 136
96 content = template.render()
137 content = template.render(package_files=package_files)
97 138
98 139 with (inno_build_dir / 'mercurial.iss').open('w', encoding='utf-8') as fh:
99 140 fh.write(content)
100 141
142 # Copy additional files used by Inno.
143 for p in ('mercurial.ico', 'postinstall.txt'):
144 shutil.copyfile(
145 source_dir / 'contrib' / 'win32' / p, inno_build_dir / p
146 )
147
101 148 args = [str(iscc_exe)]
102 149
103 150 if vc_x64:
@@ -15,10 +15,43 b' from .downloads import download_entry'
15 15 from .util import (
16 16 extract_tar_to_directory,
17 17 extract_zip_to_directory,
18 process_install_rules,
18 19 python_exe_info,
19 20 )
20 21
21 22
23 STAGING_RULES = [
24 ('contrib/bash_completion', 'Contrib/'),
25 ('contrib/hgk', 'Contrib/hgk.tcl'),
26 ('contrib/hgweb.fcgi', 'Contrib/'),
27 ('contrib/hgweb.wsgi', 'Contrib/'),
28 ('contrib/mercurial.el', 'Contrib/'),
29 ('contrib/mq.el', 'Contrib/'),
30 ('contrib/tcsh_completion', 'Contrib/'),
31 ('contrib/tcsh_completion_build.sh', 'Contrib/'),
32 ('contrib/vim/*', 'Contrib/Vim/'),
33 ('contrib/win32/postinstall.txt', 'ReleaseNotes.txt'),
34 ('contrib/win32/ReadMe.html', 'ReadMe.html'),
35 ('contrib/xml.rnc', 'Contrib/'),
36 ('contrib/zsh_completion', 'Contrib/'),
37 ('dist/hg.exe', './'),
38 ('dist/lib/*.dll', 'lib/'),
39 ('dist/lib/*.pyd', 'lib/'),
40 ('dist/lib/library.zip', 'lib/'),
41 ('dist/Microsoft.VC*.CRT.manifest', './'),
42 ('dist/msvc*.dll', './'),
43 ('dist/python*.dll', './'),
44 ('doc/*.html', 'Docs/'),
45 ('doc/style.css', 'Docs/'),
46 ('mercurial/help/**/*.txt', 'help/'),
47 ('mercurial/default.d/*.rc', 'default.d/'),
48 ('mercurial/locale/**/*', 'locale/'),
49 ('mercurial/templates/**/*', 'Templates/'),
50 ('CONTRIBUTORS', 'Contributors.txt'),
51 ('COPYING', 'Copying.txt'),
52 ]
53
54
22 55 def build_py2exe(
23 56 source_dir: pathlib.Path,
24 57 build_dir: pathlib.Path,
@@ -169,3 +202,12 b' def build_py2exe('
169 202 env=env,
170 203 check=True,
171 204 )
205
206
207 def stage_install(source_dir: pathlib.Path, staging_dir: pathlib.Path):
208 """Copy all files to be installed to a directory.
209
210 This allows packaging to simply walk a directory tree to find source
211 files.
212 """
213 process_install_rules(STAGING_RULES, source_dir, staging_dir)
@@ -9,8 +9,10 b''
9 9
10 10 import distutils.version
11 11 import getpass
12 import glob
12 13 import os
13 14 import pathlib
15 import shutil
14 16 import subprocess
15 17 import tarfile
16 18 import zipfile
@@ -164,3 +166,47 b' def python_exe_info(python_exe: pathlib.'
164 166 'version': version,
165 167 'py3': version >= distutils.version.LooseVersion('3'),
166 168 }
169
170
171 def process_install_rules(
172 rules: list, source_dir: pathlib.Path, dest_dir: pathlib.Path
173 ):
174 for source, dest in rules:
175 if '*' in source:
176 if not dest.endswith('/'):
177 raise ValueError('destination must end in / when globbing')
178
179 # We strip off the source path component before the first glob
180 # character to construct the relative install path.
181 prefix_end_index = source[: source.index('*')].rindex('/')
182 relative_prefix = source_dir / source[0:prefix_end_index]
183
184 for res in glob.glob(str(source_dir / source), recursive=True):
185 source_path = pathlib.Path(res)
186
187 if source_path.is_dir():
188 continue
189
190 rel_path = source_path.relative_to(relative_prefix)
191
192 dest_path = dest_dir / dest[:-1] / rel_path
193
194 dest_path.parent.mkdir(parents=True, exist_ok=True)
195 print('copying %s to %s' % (source_path, dest_path))
196 shutil.copy(source_path, dest_path)
197
198 # Simple file case.
199 else:
200 source_path = pathlib.Path(source)
201
202 if dest.endswith('/'):
203 dest_path = pathlib.Path(dest) / source_path.name
204 else:
205 dest_path = pathlib.Path(dest)
206
207 full_source_path = source_dir / source_path
208 full_dest_path = dest_dir / dest_path
209
210 full_dest_path.parent.mkdir(parents=True, exist_ok=True)
211 shutil.copy(full_source_path, full_dest_path)
212 print('copying %s to %s' % (full_source_path, full_dest_path))
@@ -33,8 +33,8 b' ArchitecturesInstallIn64BitMode=x64'
33 33 AppVerName=Mercurial {#VERSION}
34 34 OutputBaseFilename=Mercurial-{#VERSION}
35 35 #endif
36 InfoAfterFile=contrib/win32/postinstall.txt
37 LicenseFile=COPYING
36 InfoAfterFile=../postinstall.txt
37 LicenseFile=Copying.txt
38 38 ShowLanguageDialog=yes
39 39 AppPublisher=Matt Mackall and others
40 40 AppPublisherURL=https://mercurial-scm.org/
@@ -43,49 +43,23 b' AppUpdatesURL=https://mercurial-scm.org/'
43 43 {{ 'AppID={{4B95A5F1-EF59-4B08-BED8-C891C46121B3}' }}
44 44 AppContact=mercurial@mercurial-scm.org
45 45 DefaultDirName={pf}\Mercurial
46 SourceDir=..\..
46 SourceDir=stage
47 47 VersionInfoDescription=Mercurial distributed SCM (version {#VERSION})
48 48 VersionInfoCopyright=Copyright 2005-2019 Matt Mackall and others
49 49 VersionInfoCompany=Matt Mackall and others
50 50 InternalCompressLevel=max
51 51 SolidCompression=true
52 SetupIconFile=contrib\win32\mercurial.ico
52 SetupIconFile=../mercurial.ico
53 53 AllowNoIcons=true
54 54 DefaultGroupName=Mercurial
55 55 PrivilegesRequired=none
56 56 ChangesEnvironment=true
57 57
58 58 [Files]
59 Source: contrib\mercurial.el; DestDir: {app}/Contrib
60 Source: contrib\vim\*.*; DestDir: {app}/Contrib/Vim
61 Source: contrib\zsh_completion; DestDir: {app}/Contrib
62 Source: contrib\bash_completion; DestDir: {app}/Contrib
63 Source: contrib\tcsh_completion; DestDir: {app}/Contrib
64 Source: contrib\tcsh_completion_build.sh; DestDir: {app}/Contrib
65 Source: contrib\hgk; DestDir: {app}/Contrib; DestName: hgk.tcl
66 Source: contrib\xml.rnc; DestDir: {app}/Contrib
67 Source: contrib\mercurial.el; DestDir: {app}/Contrib
68 Source: contrib\mq.el; DestDir: {app}/Contrib
69 Source: contrib\hgweb.fcgi; DestDir: {app}/Contrib
70 Source: contrib\hgweb.wsgi; DestDir: {app}/Contrib
71 Source: contrib\win32\ReadMe.html; DestDir: {app}; Flags: isreadme
72 Source: contrib\win32\postinstall.txt; DestDir: {app}; DestName: ReleaseNotes.txt
73 Source: dist\hg.exe; DestDir: {app}; AfterInstall: Touch('{app}\hg.exe.local')
74 Source: dist\lib\*.dll; Destdir: {app}\lib
75 Source: dist\lib\*.pyd; Destdir: {app}\lib
76 Source: dist\python*.dll; Destdir: {app}; Flags: skipifsourcedoesntexist
77 Source: dist\msvc*.dll; DestDir: {app}; Flags: skipifsourcedoesntexist
78 Source: dist\Microsoft.VC*.CRT.manifest; DestDir: {app}; Flags: skipifsourcedoesntexist
79 Source: dist\lib\library.zip; DestDir: {app}\lib
80 Source: doc\*.html; DestDir: {app}\Docs
81 Source: doc\style.css; DestDir: {app}\Docs
82 Source: mercurial\help\*.txt; DestDir: {app}\help
83 Source: mercurial\help\internals\*.txt; DestDir: {app}\help\internals
84 Source: mercurial\default.d\*.rc; DestDir: {app}\default.d
85 Source: mercurial\locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs skipifsourcedoesntexist
86 Source: mercurial\templates\*.*; DestDir: {app}\Templates; Flags: recursesubdirs createallsubdirs
87 Source: CONTRIBUTORS; DestDir: {app}; DestName: Contributors.txt
88 Source: COPYING; DestDir: {app}; DestName: Copying.txt
59 {% for entry in package_files -%}
60 Source: {{ entry.source }}; DestDir: {{ entry.dest_dir }}
61 {%- if entry.metadata %}; {{ entry.metadata }}{% endif %}
62 {% endfor %}
89 63
90 64 [INI]
91 65 Filename: {app}\Mercurial.url; Section: InternetShortcut; Key: URL; String: https://mercurial-scm.org/
General Comments 0
You need to be logged in to leave comments. Login now