1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
|
; Script for Inno Setup installer
; [[[cog cog.outl('; This script created by Cog from bzr.iss.cog source') ]]]
; [[[end]]]
; Cog is http://www.nedbatchelder.com/code/cog/
[Setup]
AppName=Bazaar
; [[[cog
; # Python 2.5 compatibility code
; import os
; import sys
; cwd = os.getcwd()
; if cwd not in sys.path:
; sys.path.insert(0, cwd)
; #/Python 2.5 compatibility code
;
; import bzrlib
; try:
; VERSION = bzrlib.__version__
; AppVerName = 'Bazaar %s' % VERSION
; OutputBaseFilename = 'bzr-%s-setup' % VERSION
; except:
; VERSION = ''
; AppVerName = 'Bazaar'
; OutputBaseFilename = 'bzr-setup'
;
; cog.outl('AppVerName=%s' % AppVerName)
; cog.outl('OutputBaseFilename=%s' % OutputBaseFilename)
; ]]]
AppVerName=Bazaar
OutputBaseFilename=bzr-setup
; [[[end]]]
DefaultDirName={pf}\Bazaar
DefaultGroupName=Bazaar
SolidCompression=yes
OutputDir="..\"
SourceDir="..\..\win32_bzr.exe"
SetupIconFile="..\bzr.ico"
InfoBeforeFile="..\tools\win32\info.txt"
VersionInfoCompany="Canonical Ltd."
VersionInfoCopyright="Canonical Ltd., 2005-2008"
VersionInfoDescription="Windows installer for Bazaar"
; [[[cog
; import bzrlib
; version_number = []
; for i in bzrlib.version_info[:3]:
; try:
; i = int(i)
; except ValueError:
; i = 0
; version_number.append(i)
; # incremental build number
; from tools.win32.file_version import *
; try:
; version_prev = get_file_version(OutputBaseFilename + '.exe')
; except (FileNotFound, VersionNotAvailable):
; pass
; else:
; if version_number == list(version_prev[:3]):
; version_number.append((version_prev[-1]+1) % 65536)
; version_str = '.'.join(str(i) for i in version_number)
; cog.outl('VersionInfoVersion="%s"' % version_str)
; ]]]
; [[[end]]]
AppComments="Bazaar: Friendly distributed version control system"
AppPublisher="Canonical Ltd."
AppPublisherURL="http://bazaar.canonical.com"
AppSupportURL="http://wiki.bazaar.canonical.com/BzrSupport"
AppUpdatesURL="http://wiki.bazaar.canonical.com/WindowsDownloads"
; [[[cog cog.outl('AppVersion=%s' % VERSION) ]]]
; [[[end]]]
ChangesEnvironment=yes
; MARKH: PrivilegesRequired=none means it can't be installed by a non-admin
; user - but sadly we still need admin - eg, tortoise overlays, installing
; into "\Program Files", installing COM objects etc all must be done by an
; admin.
PrivilegesRequired=admin
[Files]
; Tortoise files - these are at the top as we use 'ExtractTemporaryFile' on
; the TortoiseOverlays MSI, and inno documents such files should be at the
; start for best performance.
; [[[cog
; if "TBZR" in os.environ: # we need a more formal way of controlling this...
; tovmsi32 = os.environ["TORTOISE_OVERLAYS_MSI_WIN32"] # point at the 32bit TortoiseOverlays .msi
; tovmsi64 = os.environ["TORTOISE_OVERLAYS_MSI_X64"] # point at the 64bit TortoiseOverlays .msi
; cog.outl('Source: "%s"; Flags: dontcopy ignoreversion ; Components: tortoise' % tovmsi32)
; cog.outl('Source: "%s"; Flags: dontcopy ignoreversion ; Components: tortoise' % tovmsi64)
; cog.outl('Source: "tbzrcache.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrcachew.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrcommand.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrcommandw.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrtrace.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: debug')
; # Note 'regserver' here appears to run regsvr32 without elevation, which
; # is no good for us - so we have a [run] entry below.
; cog.outl('Source: "tbzr_old.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrshellext_x86.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
; cog.outl('Source: "tbzrshellext_x64.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise; Check: IsWin64;')
; cog.outl(r'Source: "plugins\qbzr\*"; DestDir: "{app}\plugins\qbzr"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete; Components: tortoise')
;
; cog.outl('Source: "%s\\doc\\*.html"; DestDir: "{app}\\doc\\tbzr"; Flags: ignoreversion; Components: tortoise' % os.environ['TBZR'])
; ]]]
; [[[end]]]
; We can't say '*.*' due to optional components.
Source: "plugins\*.*"; DestDir: "{app}\\plugins"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete; Components: plugins
Source: "*.bat"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
Source: "*.url"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
Source: "msvc*.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
Source: "bz*.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
Source: "Python*.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
Source: "lib\*.*"; DestDir: "{app}\lib"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete;
Source: "doc\*.*"; DestDir: "{app}\doc"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete;
; [[[cog
; try:
; import pycurl
; except ImportError:
; ca_path = None
; else:
; supported = pycurl.version_info()[8]
; if 'https' in supported:
; from bzrlib.transport.http.ca_bundle import get_ca_path
; ca_path = get_ca_path()
; if ca_path:
; cog.outl('Source: "%s"; DestDir: "{app}"; Components: cabundle' % ca_path)
; else:
; cog.msg('You have pycurl with SSL support, '
; 'but CA Bundle (curl-ca-bundle.crt) not found!')
; ]]]
; [[[end]]]
; imageformats plugins for PyQt4
; [[[cog
; plug_dir = os.path.join(os.path.dirname(cog.inFile), # $(bzr_src_root)/tools/win32
; '..', '..', 'win32_bzr.exe', 'imageformats')
; if os.path.isdir(plug_dir):
; cog.outl('Source: "imageformats\\*.*"; DestDir: "{app}\\imageformats"; '
; 'Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete;')
; else:
; cog.msg('imageformats plugins for PyQt4 not found')
; ]]]
; [[[end]]]
[Types]
Name: "typical"; Description: "A typical installation"
Name: "full"; Description: "Full Installation (typical installation plus test utilities)"
Name: "compact"; Description: "Compact installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom
[Components]
Name: "main"; Description: "Main Files"; Types: full typical compact custom; Flags: fixed
Name: "plugins"; Description: "Default plugins"; Types: full typical custom;
; [[[cog
; if ca_path:
; cog.outl('Name: "cabundle"; '
; 'Description: "CA certificates for SSL support"; '
; 'Types: full typical custom')
; if "TBZR" in os.environ: # we need a more formal way of controlling this...
; cog.outl('Name: "tortoise"; Description: "Windows Shell Extensions (TortoiseBZR)"; Types: full typical custom;')
; cog.outl('Name: "debug"; Description: "Test, diagnostic and debugging utilities"; Types: full custom;')
;
; ]]]
; [[[end]]]
[Dirs]
Name: "{userappdata}\bazaar\2.0"
Name: "{app}\plugins"; Flags: uninsalwaysuninstall
[Icons]
Name: "{group}\Documentation index"; Filename: "{app}\doc\index.html"; WorkingDir: "{app}\doc";
Name: "{group}\Bazaar Home Page"; Filename: "{app}\bazaar.url"; Comment: "http://bazaar.canonical.com";
Name: "{group}\Start Bzr in cmd shell"; Filename: "{cmd}"; Parameters: "/K start_bzr.bat"; WorkingDir: "{app}"; IconFilename: "{app}\bzr.exe"; Comment: "Open new Bzr session";
; NOTE: Intent is to change the log file location - the line below will need to change to reflect that.
Name: "{group}\Open Bzr log file"; Filename: "notepad.exe"; Parameters: "{userdocs}\.bzr.log"; Comment: "Launch notepad to view the bzr log file";
; [[[cog
; if "TBZR" in os.environ:
; cog.outl(r'Name: "{group}\TortoiseBZR documentation"; Filename: "{app}\doc\tbzr\index.html"; Comment: "Launch TortoiseBZR documentation";')
; ]]]
; [[[end]]]
; No Uninstall here - Control Panel will do
[Tasks]
Name: Path; Description: "Add {app} directory to PATH environment variable"
; [[[cog
; if "TBZR" in os.environ:
; cog.outl('Name: TBZRReadme; Description: "View the TortoiseBZR Readme"; Components: tortoise')
; ]]]
; [[[end]]]
[Registry]
Root: HKLM; Subkey: "SOFTWARE\Bazaar"; Flags: noerror uninsdeletekey
Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "InstallPath"; ValueType: string; ValueData: "{app}"; Flags: noerror
; Don't write stuff that can be implied
;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "BzrlibPath"; ValueType: string; ValueData: "{app}\lib\library.zip\bzrlib"; Flags: noerror
;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PluginsPath"; ValueType: string; ValueData: "{app}\plugins"; Flags: noerror
;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PythonPath"; ValueType: string; ValueData: "{app}\lib\library.zip"; Flags: noerror
; [[[cog cog.outl('Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "Version"; ValueType: string; ValueData: "%s"; Flags: noerror' % VERSION) ]]]
; [[[end]]]
[Run]
Filename: "{app}\bzr_postinstall.exe"; Parameters: "--start-bzr"; Flags: skipifdoesntexist runhidden;
Filename: "{app}\bzr_postinstall.exe"; Parameters: "--add-path"; Tasks: Path; Flags: skipifdoesntexist skipifsilent runhidden;
; [[[cog
; if "TBZR" in os.environ:
; cog.outl('Filename: "regsvr32.exe"; Parameters: "/s /i: /n tbzrshellext_x86.dll"; WorkingDir: "{app}"; Components: tortoise; Description: "Registering Tortoise"; StatusMsg: "Registering Tortoise"')
; cog.outl('Filename: "regsvr32.exe"; Parameters: "/s /i: /n tbzrshellext_x64.dll"; WorkingDir: "{app}"; Components: tortoise; Description: "Registering Tortoise"; StatusMsg: "Registering Tortoise"; Check: IsWin64')
; cog.outl(r'Filename: "{app}\doc\tbzr\index.html"; Tasks: TBZRReadme; Flags: shellexec')
; ]]]
; [[[end]]]
[UninstallRun]
Filename: "{app}\bzr_postinstall.exe"; Parameters: "--delete-path --delete-shell-menu --silent"; Flags: skipifdoesntexist runhidden;
; [[[cog
; if "TBZR" in os.environ:
; cog.outl('Filename: "regsvr32.exe"; Parameters: "/u /s /i: tbzrshellext_x86.dll"; WorkingDir: "{app}"; Components: tortoise; StatusMsg: "Unregistering Tortoise"; Flags: skipifdoesntexist')
; cog.outl('Filename: "regsvr32.exe"; Parameters: "/u /s /i: tbzrshellext_x64.dll"; WorkingDir: "{app}"; Components: tortoise; StatusMsg: "Unregistering Tortoise"; Flags: skipifdoesntexist; Check: IsWin64')
; ]]]
; [[[end]]]
[Code]
const
SHCNF_IDLIST = $0000;
SHCNE_ASSOCCHANGED = $08000000;
WM_QUIT = 18;
MOVEFILE_DELAY_UNTIL_REBOOT = 4;
procedure SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2: Integer);
external 'SHChangeNotify@shell32.dll stdcall';
function MoveFileEx(lpExistingFileName, lpNewFileName: String; dwFlags: Cardinal): Integer;
external 'MoveFileExA@kernel32.dll stdcall';
procedure DeleteFileNowOrLater(filename: string);
var
rc : Integer;
begin
if FileExists(filename) and not DeleteFile(filename) then
// can't work out to pass NULL to the API, but an empty string
// seems to work OK.
MoveFileEx(filename, '', MOVEFILE_DELAY_UNTIL_REBOOT);
end;
procedure ShutdownTBZR;
var
hwnd: HWND;
begin
// [[[cog
// if "TBZR" not in os.environ:
// cog.outl(' Exit; // No TSVN set - exit this procedure.')
// ]]]
// [[[end]]]
// ask the cache process to shut-down.
hwnd := FindWindowByClassName('TBZRCache_Taskbar');
if hwnd <> 0 then
PostMessage(hwnd, WM_QUIT, 1, 0);
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
S, tovmsi, fqtovmsi, params: String;
ErrorCode: Integer;
begin
if CurStep=ssInstall then begin
ShutdownTBZR;
// In case the user hasn't uninstalled the old version before
// upgrading, we unregister and delete some obsolete files
// (regsvr32 remains silent even if the file doesn't exist)
Exec('regsvr32.exe', '/s /u "' + ExpandConstant('{app}\tbzr.dll') + '"',
'', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
DeleteFileNowOrLater(ExpandConstant('{app}\tbzr.dll'));
DeleteFileNowOrLater(ExpandConstant('{app}\tbzrtest.exe'));
DeleteFileNowOrLater(ExpandConstant('{app}\tbzr_tracer.exe'));
end;
if CurStep=ssPostInstall then begin
// a couple of post-install tasks
if IsComponentSelected('tortoise') then begin
// Need to execute:
// msiexec /i TortoiseOverlays-1.X.X.XXXX-win32.msi /qn /norestart
// 64bit notes:
// We are still primarily a 32bit application - the only 64bit binary is the
// shell extension, but even then, we need to install the 32bit version too.
// Thus, we keep tortoise in 32bit "install mode" - meaning we are installed
// to "\Program Files (x86)". We don't bother trying to install our single
// 64bit DLL into "\Program Files" - we use a different DLL name for 32 and
// 64 bit versions, so nothing will conflict.
// Note however that on a 64bit OS, we only need the 64bit TortoiseOverlays -
// the 32bit apps using shell extensions still work fine with that.
// [[[cog
// if "TBZR" in os.environ:
// import os
// cog.outl("if IsWin64 then")
// cog.outl(" tovmsi := '%s'" % os.path.basename(os.environ["TORTOISE_OVERLAYS_MSI_X64"]))
// cog.outl("else")
// cog.outl(" tovmsi := '%s'" % os.path.basename(os.environ["TORTOISE_OVERLAYS_MSI_WIN32"]))
// else:
// cog.outl("tovmsi := '';")
// ]]]
// [[[end]]]
ExtractTemporaryFile(tovmsi);
fqtovmsi := AddBackslash(ExpandConstant('{tmp}')) + tovmsi;
params := '/i "' + fqtovmsi + '" /qn /norestart';
if not ShellExec('', 'msiexec.exe', params, '', SW_HIDE,
ewWaitUntilTerminated, ErrorCode) then
MsgBox('Failed to install TortoiseOverlays: ' + SysErrorMessage(ErrorCode),
mbInformation, MB_OK);
// Ideally we could be bzr_postinstall.exe this way too, but
// its needed at uninstall time.
end;
// cause explorer to re-fetch handlers.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
end;
end;
function InitializeUninstall(): Boolean;
begin
ShutdownTBZR;
result := True;
end;
|