win32: Update installer script to use 'git-cola'
[git-cola.git] / win32 / install.iss
blob30d459142197f4ca83e4f51fe3eeae968cf9c196
1 #define APP_NAME 'git-cola'
2 #define APP_LONGNAME 'git-cola: A highly caffeinated git GUI'
3 #define APP_VERSION '%APPVERSION%'
4 #define APP_URL 'http://cola.tuxfamily.org/'
6 [Setup]
7 ; Compiler-related
8 InternalCompressLevel=max
9 OutputBaseFilename={#emit APP_NAME+'-'+APP_VERSION}
10 OutputDir=%OUTPUTDIR%
11 SolidCompression=yes
13 ; Installer-related
14 AllowNoIcons=yes
15 AppName={#emit APP_LONGNAME}
16 AppPublisherURL={#emit APP_URL}
17 AppVersion={#emit APP_VERSION}
18 AppVerName={#emit APP_LONGNAME+' '+APP_VERSION}
19 ChangesEnvironment=yes
20 DefaultDirName={pf}\{#emit APP_NAME}
21 DefaultGroupName={#emit APP_LONGNAME}
22 DisableReadyPage=yes
23 InfoBeforeFile=etc\gpl-2.0.rtf
24 PrivilegesRequired=none
25 UninstallDisplayIcon=etc\git.ico
27 ; Cosmetic
28 SetupIconFile=etc\git.ico
29 WizardSmallImageFile=etc\git.bmp
31 [Tasks]
32 Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
33 Name: desktopicon; Description: "Create a &Desktop icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
34 Name: guiextension; Description: "Add ""Git &Cola Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce
36 [Files]
37 Source: "*"; DestDir: "{app}"; Excludes: "\*.bmp, \install.*, \tmp.*, \bin\*install*"; Flags: recursesubdirs
38 Source: "etc\ReleaseNotes.txt"; DestDir: "{app}\etc"; Flags: isreadme
40 [Icons]
41 Name: "{group}\Git Cola"; Filename: "{app}\bin\git-cola.pyw"; Parameters: "--git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"
42 Name: "{group}\License"; Filename: "{app}\etc\gpl-2.0.rtf"; WorkingDir: "%USERPROFILE%";
43 Name: "{group}\Release Notes"; Filename: "{app}\etc\ReleaseNotes.txt"; WorkingDir: "%USERPROFILE%";
44 Name: "{group}\Git Cola Homepage"; Filename: "{#emit APP_URL}"; WorkingDir: "%USERPROFILE%";
45 Name: "{group}\Uninstall Git Cola"; Filename: "{uninstallexe}"
46 Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Cola"; Filename: "{app}\bin\git-cola.pyw"; Parameters: "--git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: quicklaunchicon
47 Name: "{code:GetShellFolder|desktop}\Git Cola"; Filename: "{app}\bin\git-cola.pyw"; Parameters: "--git-path ""{code:GetGitExe}"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: desktopicon
49 [Messages]
50 BeveledLabel={#emit APP_URL}
51 SetupAppTitle={#emit APP_NAME} Setup
52 SetupWindowTitle={#emit APP_NAME} Setup
54 [UninstallDelete]
55 Type: files; Name: "{app}\bin\*"
56 Type: files; Name: "{app}\etc\*"
57 Type: files; Name: "{app}\libexec\git-cola\*"
58 Type: files; Name: "{app}\share\git-cola\lib\cola\*"
59 Type: files; Name: "{app}\share\git-cola\lib\cola\models\*"
60 Type: files; Name: "{app}\share\git-cola\lib\cola\controllers\*"
61 Type: files; Name: "{app}\share\git-cola\lib\cola\views\*"
62 Type: files; Name: "{app}\share\git-cola\lib\jsonpickle\*"
63 Type: files; Name: "{app}\share\git-cola\lib\simplejson\*"
64 Type: dirifempty; Name: "{app}\share\git-cola\lib\cola\models"
65 Type: dirifempty; Name: "{app}\share\git-cola\lib\cola\controllers"
66 Type: dirifempty; Name: "{app}\share\git-cola\lib\cola\views"
67 Type: dirifempty; Name: "{app}\share\git-cola\lib\cola"
68 Type: dirifempty; Name: "{app}\share\git-cola\lib\simplejson"
69 Type: dirifempty; Name: "{app}\share\git-cola\lib\jsonpickle"
70 Type: dirifempty; Name: "{app}\share\git-cola\lib"
71 Type: dirifempty; Name: "{app}\libexec\git-cola"
72 Type: dirifempty; Name: "{app}\etc"
73 Type: dirifempty; Name: "{app}\bin"
75 [Code]
77 Helper methods
80 var
81 PythonPage:TWizardPage;
82 GitPage:TWizardPage;
83 EdtPython:TEdit;
84 EdtGit:TEdit;
86 function GetEnvStrings(VarName:string;AllUsers:Boolean):TArrayOfString;
87 var
88 Path:string;
89 i:Longint;
90 p:Integer;
91 begin
92 Path:='';
94 // See http://www.jrsoftware.org/isfaq.php#env
95 if AllUsers then begin
96 // We ignore errors here. The resulting array of strings will be empty.
97 RegQueryStringValue(HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName,Path);
98 end else begin
99 // We ignore errors here. The resulting array of strings will be empty.
100 RegQueryStringValue(HKEY_CURRENT_USER,'Environment',VarName,Path);
101 end;
103 // Make sure we have at least one semicolon.
104 Path:=Path+';';
106 // Split the directories in PATH into an array of strings.
107 i:=0;
108 SetArrayLength(Result,0);
110 p:=Pos(';',Path);
111 while p>0 do begin
112 SetArrayLength(Result,i+1);
113 if p>1 then begin
114 Result[i]:=Copy(Path,1,p-1);
115 i:=i+1;
116 end;
117 Path:=Copy(Path,p+1,Length(Path));
118 p:=Pos(';',Path);
119 end;
120 end;
122 function SetEnvStrings(VarName:string;AllUsers,DeleteIfEmpty:Boolean;DirStrings:TArrayOfString):Boolean;
124 Path,KeyName:string;
125 i:Longint;
126 begin
127 // Merge all non-empty directory strings into a PATH variable.
128 Path:='';
129 for i:=0 to GetArrayLength(DirStrings)-1 do begin
130 if Length(DirStrings[i])>0 then begin
131 if Length(Path)>0 then begin
132 Path:=Path+';'+DirStrings[i];
133 end else begin
134 Path:=DirStrings[i];
135 end;
136 end;
137 end;
139 // See http://www.jrsoftware.org/isfaq.php#env
140 if AllUsers then begin
141 KeyName:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
142 if DeleteIfEmpty and (Length(Path)=0) then begin
143 Result:=(not RegValueExists(HKEY_LOCAL_MACHINE,KeyName,VarName))
144 or RegDeleteValue(HKEY_LOCAL_MACHINE,KeyName,VarName);
145 end else begin
146 Result:=RegWriteStringValue(HKEY_LOCAL_MACHINE,KeyName,VarName,Path);
147 end;
148 end else begin
149 KeyName:='Environment';
150 if DeleteIfEmpty and (Length(Path)=0) then begin
151 Result:=(not RegValueExists(HKEY_CURRENT_USER,KeyName,VarName))
152 or RegDeleteValue(HKEY_CURRENT_USER,KeyName,VarName);
153 end else begin
154 Result:=RegWriteStringValue(HKEY_CURRENT_USER,KeyName,VarName,Path);
155 end;
156 end;
157 end;
160 procedure BrowseForPythonFolder(Sender:TObject);
162 Path:string;
163 begin
164 Path:=GetPreviousData('PythonPath', 'C:\Python26');
165 EdtPython.Text:=Path;
166 Path:=ExtractFilePath(EdtPython.Text);
167 BrowseForFolder('Please select the Python folder:',Path,False);
168 Path:=Path+'\pythonw.exe';
169 if FileExists(Path) then begin
170 EdtPython.Text:=Path;
171 end else begin
172 MsgBox('Please enter a valid path to pythonw.exe.',mbError,MB_OK);
173 end;
174 end;
176 function GetPythonExe(Param: String): String;
177 begin
178 Result:=EdtPython.Text;
179 end;
181 procedure BrowseForGitFolder(Sender:TObject);
183 Path:string;
184 OldPath:string;
185 begin
186 Path:=GetPreviousData('GitPath', 'C:\Program Files\Git');
187 EdtGit.Text:=Path;
188 Path:=ExtractFilePath(EdtGit.Text);
189 BrowseForFolder('Please select the Git folder:',Path,False);
190 OldPath:=Path;
193 Check for both $DIR\git.exe and $DIR\bin\git.exe
196 Path:=OldPath+'\bin\git.exe';
197 if FileExists(Path) then begin
198 EdtGit.Text:=Path;
199 Exit;
200 end;
202 Path:=OldPath+'\git.exe';
203 if FileExists(Path) then begin
204 EdtGit.Text:=Path;
205 end else begin
206 MsgBox('Please enter a valid path to git.exe.',mbError,MB_OK);
207 end;
208 end;
211 function GetGitExe(Param: String): String;
212 begin
213 Result:=EdtGit.Text;
214 end;
216 procedure RegisterPreviousData(PreviousDataKey:Integer);
218 Path:string;
219 begin
220 Path:=ExtractFilePath(EdtPython.Text);
221 SetPreviousData(PreviousDataKey, 'PythonPath', Path);
223 Path:=ExtractFilePath(ExtractFilePath(EdtGit.Text));
224 SetPreviousData(PreviousDataKey, 'GitPath', Path);
225 end;
228 Installer code
232 procedure InitializeWizard;
234 BtnPython:TButton;
235 BtnGit:TButton;
236 LblPython:TLabel;
237 LblGit:TLabel;
238 begin
239 // Create a custom page for finding Python
240 PythonPage:=CreateCustomPage(
241 wpSelectTasks,
242 'Setup Python',
243 'Where is your Python folder?'
246 LblPython:=TLabel.Create(PythonPage);
247 with LblPython do begin
248 Parent:=PythonPage.Surface;
249 Caption:= 'Please provide the path to pythonw.exe.';
250 Left:=ScaleX(28);
251 Top:=ScaleY(100);
252 Width:=ScaleX(316);
253 Height:=ScaleY(39);
254 end;
256 EdtPython:=TEdit.Create(PythonPage);
257 with EdtPython do begin
258 Parent:=PythonPage.Surface;
259 Text:='C:\Python26\pythonw.exe';
260 if not FileExists(Text) then begin
261 Text:='';
262 end;
263 Left:=ScaleX(28);
264 Top:=ScaleY(148);
265 Width:=ScaleX(316);
266 Height:=ScaleY(13);
267 end;
269 BtnPython:=TButton.Create(PythonPage);
270 with BtnPython do begin
271 Parent:=PythonPage.Surface;
272 Caption:='...';
273 OnClick:=@BrowseForPythonFolder;
274 Left:=ScaleX(348);
275 Top:=ScaleY(148);
276 Width:=ScaleX(21);
277 Height:=ScaleY(21);
278 end;
280 // Create a custom page for finding Git
281 GitPage:=CreateCustomPage(
282 wpSelectTasks,
283 'Setup Git',
284 'Where is your Git folder?'
287 LblGit:=TLabel.Create(GitPage);
288 with LblGit do begin
289 Parent:=GitPage.Surface;
290 Caption:= 'Please provide the path to git.exe.';
291 Left:=ScaleX(28);
292 Top:=ScaleY(100);
293 Width:=ScaleX(316);
294 Height:=ScaleY(39);
295 end;
297 EdtGit:=TEdit.Create(GitPage);
298 with EdtGit do begin
299 Parent:=GitPage.Surface;
300 Text:='C:\Program Files\Git\bin\git.exe';
301 if not FileExists(Text) then begin
302 Text:='';
303 end;
304 Left:=ScaleX(28);
305 Top:=ScaleY(148);
306 Width:=ScaleX(316);
307 Height:=ScaleY(13);
308 end;
310 BtnGit:=TButton.Create(GitPage);
311 with BtnGit do begin
312 Parent:=GitPage.Surface;
313 Caption:='...';
314 OnClick:=@BrowseForGitFolder;
315 Left:=ScaleX(348);
316 Top:=ScaleY(148);
317 Width:=ScaleX(21);
318 Height:=ScaleY(21);
319 end;
320 end;
322 function NextButtonClick(CurPageID:Integer):Boolean;
323 begin
324 if CurPageID = PythonPage.ID then begin
325 Result:=FileExists(EdtPython.Text);
327 if not Result then begin
328 MsgBox('Please enter a valid path to pythonw.exe.',mbError,MB_OK);
329 end;
330 Exit;
331 end;
333 if CurPageID = GitPage.ID then begin
334 Result:=FileExists(EdtGit.Text);
336 if not Result then begin
337 MsgBox('Please enter a valid path to git.exe.',mbError,MB_OK);
338 end;
339 Exit;
340 end;
342 Result:=True;
343 end;
345 procedure CurStepChanged(CurStep:TSetupStep);
347 AppDir,BinDir,Msg:string;
348 EnvPath:TArrayOfString;
349 i:Longint;
350 RootKey:Integer;
351 begin
352 if CurStep<>ssPostInstall then begin
353 Exit;
354 end;
356 AppDir:=ExpandConstant('{app}');
357 BinDir:=ExpandConstant('{app}\bin');
360 Modify the environment
362 This must happen no later than ssPostInstall to make
363 "ChangesEnvironment=yes" not happend before the change!
366 // Get the current user's directories in PATH.
367 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
369 // First, remove the installation directory from PATH in any case.
370 for i:=0 to GetArrayLength(EnvPath)-1 do begin
371 if Pos(AppDir,EnvPath[i])=1 then begin
372 EnvPath[i]:='';
373 end;
374 end;
376 // Modify the PATH variable as requested by the user.
377 i:=GetArrayLength(EnvPath);
378 SetArrayLength(EnvPath,i+1);
380 // Add \bin to the path
381 EnvPath[i]:=BinDir
383 // Set the current user's PATH directories.
384 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
385 Msg:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
386 MsgBox(Msg,mbError,MB_OK);
387 Log(Msg);
388 // This is not a critical error, the user can probably fix it manually,
389 // so we continue.
390 end;
393 Create the Windows Explorer shell extensions
396 if IsAdminLoggedOn then begin
397 RootKey:=HKEY_LOCAL_MACHINE;
398 end else begin
399 RootKey:=HKEY_CURRENT_USER;
400 end;
402 if IsTaskSelected('guiextension') then begin
403 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola','','Git &Cola Here'))
404 or (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola\command','','"'+EdtPython.Text+'" "'+AppDir+'\bin\git-cola.pyw" "--repo" "%1" "--git-path" "'+EdtGit.Text+'"')) then begin
405 Msg:='Line {#emit __LINE__}: Unable to create "Git Cola Here" shell extension.';
406 MsgBox(Msg,mbError,MB_OK);
407 Log(Msg);
408 // This is not a critical error, the user can probably fix it manually,
409 // so we continue.
410 end;
411 end;
412 end;
415 Uninstaller code
418 function InitializeUninstall:Boolean;
419 begin
420 Result:=True;
421 end;
423 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
425 AppDir,Command,Msg:string;
426 EnvPath:TArrayOfString;
427 i:Longint;
428 RootKey:Integer;
429 begin
430 if CurUninstallStep<>usUninstall then begin
431 Exit;
432 end;
435 Modify the environment
437 This must happen no later than usUninstall to make
438 "ChangesEnvironment=yes" not happend before the change!
441 AppDir:=ExpandConstant('{app}');
442 Command:=AppDir+'\setup.ini';
444 // Get the current user's directories in PATH.
445 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
447 // Remove the installation directory from PATH in any case, even if it
448 // was not added by the installer.
449 for i:=0 to GetArrayLength(EnvPath)-1 do begin
450 if Pos(AppDir,EnvPath[i])=1 then begin
451 EnvPath[i]:='';
452 end;
453 end;
455 // Reset the current user's directories in PATH.
456 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
457 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to PATH.';
458 MsgBox(Msg,mbError,MB_OK);
459 Log(Msg);
460 // This is not a critical error, the user can probably fix it manually,
461 // so we continue.
462 end;
464 if (FileExists(Command) and (not DeleteFile(Command))) then begin
465 Msg:='Line {#emit __LINE__}: Unable to delete file "'+Command+'".';
466 MsgBox(Msg,mbError,MB_OK);
467 Log(Msg);
468 // This is not a critical error, the user can probably fix it manually,
469 // so we continue.
470 end;
473 Delete the Windows Explorer shell extensions
476 if IsAdminLoggedOn then begin
477 RootKey:=HKEY_LOCAL_MACHINE;
478 end else begin
479 RootKey:=HKEY_CURRENT_USER;
480 end;
482 Command:='';
483 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola\command','',Command);
484 if Pos(AppDir,Command)>0 then begin
485 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_cola') then begin
486 Msg:='Line {#emit __LINE__}: Unable to remove "Git Cola Here" shell extension.';
487 MsgBox(Msg,mbError,MB_OK);
488 Log(Msg);
489 // This is not a critical error, the user can probably fix it manually,
490 // so we continue.
491 end;
492 end;
493 end;
495 function GetShellFolder(Param:string):string;
496 begin
497 if IsAdminLoggedOn then begin
498 Param:='{common'+Param+'}';
499 end else begin
500 Param:='{user'+Param+'}';
501 end;
502 Result:=ExpandConstant(Param);
503 end;