##// END OF EJS Templates
packaging: stage installed files for Inno...
Gregory Szorc -
r43916:d053d3f1 default
parent child Browse files
Show More
@@ -1,112 +1,159 b''
1 1 # inno.py - Inno Setup functionality.
2 2 #
3 3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # no-check-code because Python 3 native.
9 9
10 10 import os
11 11 import pathlib
12 12 import shutil
13 13 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 = {
21 24 'dulwich',
22 25 'keyring',
23 26 'pygments',
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,
30 38 build_dir: pathlib.Path,
31 39 python_exe: pathlib.Path,
32 40 iscc_exe: pathlib.Path,
33 41 version=None,
34 42 ):
35 43 """Build the Inno installer.
36 44
37 45 Build files will be placed in ``build_dir``.
38 46
39 47 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
40 48 for finding the Python 2.7 toolchain. So, we require the environment
41 49 to already be configured with an active toolchain.
42 50 """
43 51 if not iscc_exe.exists():
44 52 raise Exception('%s does not exist' % iscc_exe)
45 53
46 54 vc_x64 = r'\x64' in os.environ.get('LIB', '')
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'
53 62 )
54 63
55 64 inno_build_dir.mkdir(parents=True, exist_ok=True)
56 65
57 66 build_py2exe(
58 67 source_dir,
59 68 build_dir,
60 69 python_exe,
61 70 'inno',
62 71 requirements_txt,
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'):
69 87 basename = 'Microsoft.VC90.CRT.manifest'
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.
81 122 jinja_env = jinja2.Environment(
82 123 loader=jinja2.FileSystemLoader(str(inno_source_dir)),
83 124 # Need to change these to prevent conflict with Inno Setup.
84 125 comment_start_string='{##',
85 126 comment_end_string='##}',
86 127 )
87 128
88 129 try:
89 130 template = jinja_env.get_template('mercurial.iss')
90 131 except jinja2.TemplateSyntaxError as e:
91 132 raise Exception(
92 133 'template syntax error at %s:%d: %s'
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:
104 151 args.append('/dARCH=x64')
105 152
106 153 if version:
107 154 args.append('/dVERSION=%s' % version)
108 155
109 156 args.append('/Odist')
110 157 args.append(str(inno_build_dir / 'mercurial.iss'))
111 158
112 159 subprocess.run(args, cwd=str(source_dir), check=True)
@@ -1,171 +1,213 b''
1 1 # py2exe.py - Functionality for performing py2exe builds.
2 2 #
3 3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # no-check-code because Python 3 native.
9 9
10 10 import os
11 11 import pathlib
12 12 import subprocess
13 13
14 14 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,
25 58 python_exe: pathlib.Path,
26 59 build_name: str,
27 60 venv_requirements_txt: pathlib.Path,
28 61 extra_packages=None,
29 62 extra_excludes=None,
30 63 extra_dll_excludes=None,
31 64 extra_packages_script=None,
32 65 ):
33 66 """Build Mercurial with py2exe.
34 67
35 68 Build files will be placed in ``build_dir``.
36 69
37 70 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
38 71 for finding the Python 2.7 toolchain. So, we require the environment
39 72 to already be configured with an active toolchain.
40 73 """
41 74 if 'VCINSTALLDIR' not in os.environ:
42 75 raise Exception(
43 76 'not running from a Visual C++ build environment; '
44 77 'execute the "Visual C++ <version> Command Prompt" '
45 78 'application shortcut or a vcsvarsall.bat file'
46 79 )
47 80
48 81 # Identity x86/x64 and validate the environment matches the Python
49 82 # architecture.
50 83 vc_x64 = r'\x64' in os.environ['LIB']
51 84
52 85 py_info = python_exe_info(python_exe)
53 86
54 87 if vc_x64:
55 88 if py_info['arch'] != '64bit':
56 89 raise Exception(
57 90 'architecture mismatch: Visual C++ environment '
58 91 'is configured for 64-bit but Python is 32-bit'
59 92 )
60 93 else:
61 94 if py_info['arch'] != '32bit':
62 95 raise Exception(
63 96 'architecture mismatch: Visual C++ environment '
64 97 'is configured for 32-bit but Python is 64-bit'
65 98 )
66 99
67 100 if py_info['py3']:
68 101 raise Exception('Only Python 2 is currently supported')
69 102
70 103 build_dir.mkdir(exist_ok=True)
71 104
72 105 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
73 106 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
74 107 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
75 108 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
76 109
77 110 venv_path = build_dir / (
78 111 'venv-%s-%s' % (build_name, 'x64' if vc_x64 else 'x86')
79 112 )
80 113
81 114 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
82 115
83 116 if not gettext_root.exists():
84 117 extract_zip_to_directory(gettext_pkg, gettext_root)
85 118 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
86 119
87 120 # This assumes Python 2. We don't need virtualenv on Python 3.
88 121 virtualenv_src_path = build_dir / (
89 122 'virtualenv-%s' % virtualenv_entry['version']
90 123 )
91 124 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
92 125
93 126 if not virtualenv_src_path.exists():
94 127 extract_tar_to_directory(virtualenv_pkg, build_dir)
95 128
96 129 py2exe_source_path = build_dir / ('py2exe-%s' % py2exe_entry['version'])
97 130
98 131 if not py2exe_source_path.exists():
99 132 extract_zip_to_directory(py2exe_pkg, build_dir)
100 133
101 134 if not venv_path.exists():
102 135 print('creating virtualenv with dependencies')
103 136 subprocess.run(
104 137 [str(python_exe), str(virtualenv_py), str(venv_path)], check=True
105 138 )
106 139
107 140 venv_python = venv_path / 'Scripts' / 'python.exe'
108 141 venv_pip = venv_path / 'Scripts' / 'pip.exe'
109 142
110 143 subprocess.run(
111 144 [str(venv_pip), 'install', '-r', str(venv_requirements_txt)], check=True
112 145 )
113 146
114 147 # Force distutils to use VC++ settings from environment, which was
115 148 # validated above.
116 149 env = dict(os.environ)
117 150 env['DISTUTILS_USE_SDK'] = '1'
118 151 env['MSSdk'] = '1'
119 152
120 153 if extra_packages_script:
121 154 more_packages = set(
122 155 subprocess.check_output(extra_packages_script, cwd=build_dir)
123 156 .split(b'\0')[-1]
124 157 .strip()
125 158 .decode('utf-8')
126 159 .splitlines()
127 160 )
128 161 if more_packages:
129 162 if not extra_packages:
130 163 extra_packages = more_packages
131 164 else:
132 165 extra_packages |= more_packages
133 166
134 167 if extra_packages:
135 168 env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages))
136 169 hgext3rd_extras = sorted(
137 170 e for e in extra_packages if e.startswith('hgext3rd.')
138 171 )
139 172 if hgext3rd_extras:
140 173 env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras)
141 174 if extra_excludes:
142 175 env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes))
143 176 if extra_dll_excludes:
144 177 env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join(
145 178 sorted(extra_dll_excludes)
146 179 )
147 180
148 181 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
149 182 if not py2exe_py_path.exists():
150 183 print('building py2exe')
151 184 subprocess.run(
152 185 [str(venv_python), 'setup.py', 'install'],
153 186 cwd=py2exe_source_path,
154 187 env=env,
155 188 check=True,
156 189 )
157 190
158 191 # Register location of msgfmt and other binaries.
159 192 env['PATH'] = '%s%s%s' % (
160 193 env['PATH'],
161 194 os.pathsep,
162 195 str(gettext_root / 'bin'),
163 196 )
164 197
165 198 print('building Mercurial')
166 199 subprocess.run(
167 200 [str(venv_python), 'setup.py', 'py2exe', 'build_doc', '--html'],
168 201 cwd=str(source_dir),
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)
@@ -1,166 +1,212 b''
1 1 # util.py - Common packaging utility code.
2 2 #
3 3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # no-check-code because Python 3 native.
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
17 19
18 20
19 21 def extract_tar_to_directory(source: pathlib.Path, dest: pathlib.Path):
20 22 with tarfile.open(source, 'r') as tf:
21 23 tf.extractall(dest)
22 24
23 25
24 26 def extract_zip_to_directory(source: pathlib.Path, dest: pathlib.Path):
25 27 with zipfile.ZipFile(source, 'r') as zf:
26 28 zf.extractall(dest)
27 29
28 30
29 31 def find_vc_runtime_files(x64=False):
30 32 """Finds Visual C++ Runtime DLLs to include in distribution."""
31 33 winsxs = pathlib.Path(os.environ['SYSTEMROOT']) / 'WinSxS'
32 34
33 35 prefix = 'amd64' if x64 else 'x86'
34 36
35 37 candidates = sorted(
36 38 p
37 39 for p in os.listdir(winsxs)
38 40 if p.lower().startswith('%s_microsoft.vc90.crt_' % prefix)
39 41 )
40 42
41 43 for p in candidates:
42 44 print('found candidate VC runtime: %s' % p)
43 45
44 46 # Take the newest version.
45 47 version = candidates[-1]
46 48
47 49 d = winsxs / version
48 50
49 51 return [
50 52 d / 'msvcm90.dll',
51 53 d / 'msvcp90.dll',
52 54 d / 'msvcr90.dll',
53 55 winsxs / 'Manifests' / ('%s.manifest' % version),
54 56 ]
55 57
56 58
57 59 def windows_10_sdk_info():
58 60 """Resolves information about the Windows 10 SDK."""
59 61
60 62 base = pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Windows Kits' / '10'
61 63
62 64 if not base.is_dir():
63 65 raise Exception('unable to find Windows 10 SDK at %s' % base)
64 66
65 67 # Find the latest version.
66 68 bin_base = base / 'bin'
67 69
68 70 versions = [v for v in os.listdir(bin_base) if v.startswith('10.')]
69 71 version = sorted(versions, reverse=True)[0]
70 72
71 73 bin_version = bin_base / version
72 74
73 75 return {
74 76 'root': base,
75 77 'version': version,
76 78 'bin_root': bin_version,
77 79 'bin_x86': bin_version / 'x86',
78 80 'bin_x64': bin_version / 'x64',
79 81 }
80 82
81 83
82 84 def find_signtool():
83 85 """Find signtool.exe from the Windows SDK."""
84 86 sdk = windows_10_sdk_info()
85 87
86 88 for key in ('bin_x64', 'bin_x86'):
87 89 p = sdk[key] / 'signtool.exe'
88 90
89 91 if p.exists():
90 92 return p
91 93
92 94 raise Exception('could not find signtool.exe in Windows 10 SDK')
93 95
94 96
95 97 def sign_with_signtool(
96 98 file_path,
97 99 description,
98 100 subject_name=None,
99 101 cert_path=None,
100 102 cert_password=None,
101 103 timestamp_url=None,
102 104 ):
103 105 """Digitally sign a file with signtool.exe.
104 106
105 107 ``file_path`` is file to sign.
106 108 ``description`` is text that goes in the signature.
107 109
108 110 The signing certificate can be specified by ``cert_path`` or
109 111 ``subject_name``. These correspond to the ``/f`` and ``/n`` arguments
110 112 to signtool.exe, respectively.
111 113
112 114 The certificate password can be specified via ``cert_password``. If
113 115 not provided, you will be prompted for the password.
114 116
115 117 ``timestamp_url`` is the URL of a RFC 3161 timestamp server (``/tr``
116 118 argument to signtool.exe).
117 119 """
118 120 if cert_path and subject_name:
119 121 raise ValueError('cannot specify both cert_path and subject_name')
120 122
121 123 while cert_path and not cert_password:
122 124 cert_password = getpass.getpass('password for %s: ' % cert_path)
123 125
124 126 args = [
125 127 str(find_signtool()),
126 128 'sign',
127 129 '/v',
128 130 '/fd',
129 131 'sha256',
130 132 '/d',
131 133 description,
132 134 ]
133 135
134 136 if cert_path:
135 137 args.extend(['/f', str(cert_path), '/p', cert_password])
136 138 elif subject_name:
137 139 args.extend(['/n', subject_name])
138 140
139 141 if timestamp_url:
140 142 args.extend(['/tr', timestamp_url, '/td', 'sha256'])
141 143
142 144 args.append(str(file_path))
143 145
144 146 print('signing %s' % file_path)
145 147 subprocess.run(args, check=True)
146 148
147 149
148 150 PRINT_PYTHON_INFO = '''
149 151 import platform; print("%s:%s" % (platform.architecture()[0], platform.python_version()))
150 152 '''.strip()
151 153
152 154
153 155 def python_exe_info(python_exe: pathlib.Path):
154 156 """Obtain information about a Python executable."""
155 157
156 158 res = subprocess.check_output([str(python_exe), '-c', PRINT_PYTHON_INFO])
157 159
158 160 arch, version = res.decode('utf-8').split(':')
159 161
160 162 version = distutils.version.LooseVersion(version)
161 163
162 164 return {
163 165 'arch': arch,
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))
@@ -1,125 +1,99 b''
1 1 ; Script generated by the Inno Setup Script Wizard.
2 2 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
3 3
4 4 #ifndef VERSION
5 5 #define FileHandle
6 6 #define FileLine
7 7 #define VERSION = "unknown"
8 8 #if FileHandle = FileOpen(SourcePath + "\..\..\mercurial\__version__.py")
9 9 #expr FileLine = FileRead(FileHandle)
10 10 #expr FileLine = FileRead(FileHandle)
11 11 #define VERSION = Copy(FileLine, Pos('"', FileLine)+1, Len(FileLine)-Pos('"', FileLine)-1)
12 12 #endif
13 13 #if FileHandle
14 14 #expr FileClose(FileHandle)
15 15 #endif
16 16 #pragma message "Detected Version: " + VERSION
17 17 #endif
18 18
19 19 #ifndef ARCH
20 20 #define ARCH = "x86"
21 21 #endif
22 22
23 23 [Setup]
24 24 AppCopyright=Copyright 2005-2019 Matt Mackall and others
25 25 AppName=Mercurial
26 26 AppVersion={#VERSION}
27 27 #if ARCH == "x64"
28 28 AppVerName=Mercurial {#VERSION} (64-bit)
29 29 OutputBaseFilename=Mercurial-{#VERSION}-x64
30 30 ArchitecturesAllowed=x64
31 31 ArchitecturesInstallIn64BitMode=x64
32 32 #else
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/
41 41 AppSupportURL=https://mercurial-scm.org/
42 42 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/
92 66 Filename: {app}\default.d\editor.rc; Section: ui; Key: editor; String: notepad
93 67
94 68 [UninstallDelete]
95 69 Type: files; Name: {app}\Mercurial.url
96 70 Type: filesandordirs; Name: {app}\default.d
97 71 Type: files; Name: "{app}\hg.exe.local"
98 72
99 73 [Icons]
100 74 Name: {group}\Uninstall Mercurial; Filename: {uninstallexe}
101 75 Name: {group}\Mercurial Command Reference; Filename: {app}\Docs\hg.1.html
102 76 Name: {group}\Mercurial Configuration Files; Filename: {app}\Docs\hgrc.5.html
103 77 Name: {group}\Mercurial Ignore Files; Filename: {app}\Docs\hgignore.5.html
104 78 Name: {group}\Mercurial Web Site; Filename: {app}\Mercurial.url
105 79
106 80 [Tasks]
107 81 Name: modifypath; Description: Add the installation path to the search path; Flags: unchecked
108 82
109 83 [Code]
110 84 procedure Touch(fn: String);
111 85 begin
112 86 SaveStringToFile(ExpandConstant(fn), '', False);
113 87 end;
114 88
115 89 const
116 90 ModPathName = 'modifypath';
117 91 ModPathType = 'user';
118 92
119 93 function ModPathDir(): TArrayOfString;
120 94 begin
121 95 setArrayLength(Result, 1)
122 96 Result[0] := ExpandConstant('{app}');
123 97 end;
124 98
125 99 {% include 'modpath.iss' %}
General Comments 0
You need to be logged in to leave comments. Login now