Installer: Check for msys-1.0.dll being in use, too (fixes issue 441)
[msysgit/mtrensch.git] / share / WinGit / install.iss
blobe1dfb498b8b5ebc5ae2d58ee3cdb15ad1fafe929
1 #define APP_NAME 'Git'
2 #define APP_VERSION '%APPVERSION%'
3 #define APP_URL 'http://msysgit.googlecode.com/'
4 #define APP_BUILTINS 'etc\fileList-builtins.txt'
6 [Setup]
7 ; Compiler-related
8 Compression=lzma2/ultra
9 LZMAUseSeparateProcess=yes
10 OutputBaseFilename={#emit APP_NAME+'-'+APP_VERSION}
11 OutputDir=%OUTPUTDIR%
12 SolidCompression=yes
14 ; Uncomment the line below to be able to compile the script from within the IDE.
15 ;SourceDir={#GetEnv('TEMP')}\WinGit
17 ; Installer-related
18 AllowNoIcons=yes
19 AppName={#emit APP_NAME}
20 AppPublisherURL={#emit APP_URL}
21 AppVersion={#emit APP_VERSION}
22 AppVerName={#emit APP_NAME+' '+APP_VERSION}
23 ChangesEnvironment=yes
24 DefaultDirName={pf}\{#emit APP_NAME}
25 DefaultGroupName={#emit APP_NAME}
26 DisableReadyPage=yes
27 InfoBeforeFile=gpl-2.0.rtf
28 PrivilegesRequired=none
29 UninstallDisplayIcon=etc\git.ico
31 ; Cosmetic
32 SetupIconFile=etc\git.ico
33 WizardImageBackColor=clWhite
34 WizardImageStretch=no
35 WizardImageFile=git.bmp
36 WizardSmallImageFile=gitsmall.bmp
38 [Types]
39 ; Define a dummy type to avoid getting the default ones.
40 Name: custom; Description: Custom installation; Flags: iscustom
42 [Components]
43 Name: icons; Description: Additional icons; Types: custom
44 Name: icons\quicklaunch; Description: In the Quick Launch; Types: custom
45 Name: icons\desktop; Description: On the Desktop; Types: custom
46 Name: ext; Description: Windows Explorer integration; Types: custom
47 Name: ext\reg; Description: Context menu entries; Flags: exclusive; Types: custom
48 Name: ext\reg\shellhere; Description: Git Bash Here; Types: custom
49 Name: ext\reg\guihere; Description: Git GUI Here; Types: custom
50 Name: ext\cheetah; Description: git-cheetah shell extension (32-bit only); Flags: exclusive; Types: custom
51 Name: assoc; Description: Associate .git* configuration files with the default text editor; Types: custom
52 Name: consolefont; Description: Use a TrueType font in the console (required for proper character encoding); Types: custom
54 [Files]
55 ; Install files that might be in use during setup under a different name.
56 Source: git-cheetah\git_shell_ext.dll; DestDir: {app}\git-cheetah; DestName: git_shell_ext.dll.new; Flags: replacesameversion
58 Source: *; DestDir: {app}; Excludes: \*.bmp, gpl-2.0.rtf, \*.iss, \tmp.*, \bin\*install*, \git-cheetah\git_shell_ext.dll; Flags: recursesubdirs replacesameversion
59 Source: ReleaseNotes.rtf; DestDir: {app}; Flags: isreadme replacesameversion
61 [Icons]
62 Name: {group}\Git GUI; Filename: {app}\bin\wish.exe; Parameters: """{app}\libexec\git-core\git-gui"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
63 Name: {group}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
64 Name: {group}\Uninstall Git; Filename: {uninstallexe}
66 [Messages]
67 BeveledLabel={#emit APP_URL}
68 SetupAppTitle={#emit APP_NAME} Setup
69 SetupWindowTitle={#emit APP_NAME} Setup
71 [Registry]
72 ; There is no "Console" key in HKLM.
73 Root: HKCU; Subkey: Console; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Components: consolefont
74 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Components: consolefont
75 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Components: consolefont
76 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Components: consolefont
78 Root: HKCU; Subkey: Console\Git Bash; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Flags: createvalueifdoesntexist
79 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Flags: createvalueifdoesntexist
80 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Flags: createvalueifdoesntexist
81 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Flags: createvalueifdoesntexist
83 ; File associations for configuration files that may be contained in a repository (so this does not include ".gitconfig").
84 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
85 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
86 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
87 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
88 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
89 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
91 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
92 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
93 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
94 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
95 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
96 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
98 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
99 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
100 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
101 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
102 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
103 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
105 [UninstallDelete]
106 ; Delete the built-ins.
107 Type: files; Name: {app}\bin\git-*.exe
108 Type: files; Name: {app}\libexec\git-core\git-*.exe
109 Type: files; Name: {app}\libexec\git-core\git.exe
111 ; Delete any (temporary) git-cheetah files.
112 Type: files; Name: {app}\git-cheetah\*.*
114 ; Delete a home directory inside the msysGit directory.
115 Type: dirifempty; Name: {app}\home\{username}
116 Type: dirifempty; Name: {app}\home
118 [Code]
119 #include "helpers.inc.iss"
120 #include "putty.inc.iss"
121 #include "modules.inc.iss"
123 function CreateHardLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
124 #ifdef UNICODE
125 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
126 #else
127 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
128 #endif
130 function CreateSymbolicLink(lpSymlinkFileName,lpTargetFileName:String;dwFlags:DWORD):Boolean;
131 #ifdef UNICODE
132 external 'CreateSymbolicLinkW@Kernel32.dll stdcall delayload setuponly';
133 #else
134 external 'CreateSymbolicLinkA@Kernel32.dll stdcall delayload setuponly';
135 #endif
137 const
138 // Git Path options.
139 GP_BashOnly = 1;
140 GP_Cmd = 2;
141 GP_CmdTools = 3;
143 // Git SSH options.
144 GS_OpenSSH = 1;
145 GS_Plink = 2;
147 // Git line ending conversion options.
148 GC_LFOnly = 1;
149 GC_CRLFAlways = 2;
150 GC_CRLFCommitAsIs = 3;
153 // Wizard page and variables for the Path options.
154 PathPage:TWizardPage;
155 RdbPath:array[GP_BashOnly..GP_CmdTools] of TRadioButton;
157 // Wizard page and variables for the SSH options.
158 PuTTYPage:TWizardPage;
159 RdbSSH:array[GS_OpenSSH..GS_Plink] of TRadioButton;
160 EdtPlink:TEdit;
162 // Wizard page and variables for the line ending conversion options.
163 CRLFPage:TWizardPage;
164 RdbCRLF:array[GC_LFOnly..GC_CRLFCommitAsIs] of TRadioButton;
166 // Wizard page and variables for the processes page.
167 Processes:ProcessList;
168 ProcessesPage:TWizardPage;
169 ProcessesListBox:TListBox;
170 ProcessesRefresh:TButton;
172 procedure BrowseForPuTTYFolder(Sender:TObject);
174 Path:String;
175 begin
176 Path:=ExtractFilePath(EdtPlink.Text);
177 BrowseForFolder('Please select the PuTTY folder:',Path,False);
178 if FileExists(Path+'\TortoisePlink.exe') then begin
179 EdtPlink.Text:=Path+'\TortoisePlink.exe';
180 RdbSSH[GS_Plink].Checked:=True;
181 end else if FileExists(Path+'\plink.exe') then begin
182 EdtPlink.Text:=Path+'\plink.exe';
183 RdbSSH[GS_Plink].Checked:=True;
184 end else begin
185 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError,MB_OK);
186 end;
187 end;
189 procedure DeleteContextMenuEntries;
191 AppDir,Command,Msg:String;
192 RootKey:Integer;
193 begin
194 AppDir:=ExpandConstant('{app}');
196 if IsAdminLoggedOn then begin
197 RootKey:=HKEY_LOCAL_MACHINE;
198 end else begin
199 RootKey:=HKEY_CURRENT_USER;
200 end;
202 Command:='';
203 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command);
204 if Pos(AppDir,Command)>0 then begin
205 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
206 Msg:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
207 MsgBox(Msg,mbError,MB_OK);
208 Log(Msg);
209 // This is not a critical error, the user can probably fix it manually,
210 // so we continue.
211 end;
212 end;
214 Command:='';
215 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command);
216 if Pos(AppDir,Command)>0 then begin
217 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
218 Msg:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
219 MsgBox(Msg,mbError,MB_OK);
220 Log(Msg);
221 // This is not a critical error, the user can probably fix it manually,
222 // so we continue.
223 end;
224 end;
225 end;
227 procedure RefreshProcessList(Sender:TObject);
229 ProcsCloseRequired,ProcsCloseRestart:ProcessList;
230 Found:Boolean;
231 i:Longint;
232 Caption:String;
233 begin
234 Found:=FindProcessesUsingModule(ExpandConstant('{app}\bin\msys-1.0.dll'),ProcsCloseRequired);
235 Found:=FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),ProcsCloseRestart) or Found;
237 // Misuse the "Restartable" flag to indicate which processes are required
238 // to be closed before setup can continue, and which just should be closed
239 // in order to make changes take effect immediately.
240 SetArrayLength(Processes,GetArrayLength(ProcsCloseRequired)+GetArrayLength(ProcsCloseRestart));
241 for i:=0 to GetArrayLength(ProcsCloseRequired)-1 do begin
242 Processes[i]:=ProcsCloseRequired[i];
243 Processes[i].Restartable:=False;
244 end;
245 for i:=0 to GetArrayLength(ProcsCloseRestart)-1 do begin
246 Processes[GetArrayLength(ProcsCloseRequired)+i]:=ProcsCloseRestart[i];
247 Processes[GetArrayLength(ProcsCloseRequired)+i].Restartable:=True;
248 end;
250 ProcessesListBox.Items.Clear;
251 if (Sender=NIL) or Found then begin
252 for i:=0 to GetArrayLength(Processes)-1 do begin
253 Caption:=Processes[i].Name+' (PID '+IntToStr(Processes[i].ID);
254 if not Processes[i].Restartable then begin
255 Caption:=Caption+', closing is required';
256 end;
257 Caption:=Caption+')';
258 ProcessesListBox.Items.Append(Caption);
259 end;
260 end;
261 end;
264 Installer code
267 procedure InitializeWizard;
269 i,PrevPageID:Integer;
270 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
271 LblOpenSSH,LblPlink:TLabel;
272 PuTTYSessions:TArrayOfString;
273 LblLFOnly,LblCRLFAlways,LblCRLFCommitAsIs:TLabel;
274 BtnPlink:TButton;
275 Data:String;
276 begin
277 // Until we have a 64-bit version of git-cheetah, disable it on 64-bit Windows.
278 if isWin64 then begin
279 for i:=0 to WizardForm.ComponentsList.Items.Count-1 do begin
280 Data:=LowerCase(WizardForm.ComponentsList.ItemCaption[i]);
281 if Pos('context',Data)>0 then begin
282 // Select the Registry-based context menu entries.
283 WizardForm.ComponentsList.Checked[i]:=True;
284 end else if Pos('cheetah',Data)>0 then begin
285 // Disable the git-cheetah shell extension.
286 WizardForm.ComponentsList.ItemEnabled[i]:=False;
287 end;
288 end;
289 end;
291 PrevPageID:=wpSelectProgramGroup;
294 * Create a custom page for modifying the environment.
297 PathPage:=CreateCustomPage(
298 PrevPageID,
299 'Adjusting your PATH environment',
300 'How would you like to use Git from the command line?'
302 PrevPageID:=PathPage.ID;
304 // 1st choice
305 RdbPath[GP_BashOnly]:=TRadioButton.Create(PathPage);
306 with RdbPath[GP_BashOnly] do begin
307 Parent:=PathPage.Surface;
308 Caption:='Use Git Bash only';
309 Left:=ScaleX(4);
310 Top:=ScaleY(8);
311 Width:=ScaleX(129);
312 Height:=ScaleY(17);
313 Font.Style:=[fsBold];
314 TabOrder:=0;
315 Checked:=True;
316 end;
317 LblGitBash:=TLabel.Create(PathPage);
318 with LblGitBash do begin
319 Parent:=PathPage.Surface;
320 Caption:=
321 'This is the most conservative choice if you are concerned about the stability' + #13 +
322 'of your system. Your PATH will not be modified.';
323 Left:=ScaleX(28);
324 Top:=ScaleY(32);
325 Width:=ScaleX(405);
326 Height:=ScaleY(26);
327 end;
329 // 2nd choice
330 RdbPath[GP_Cmd]:=TRadioButton.Create(PathPage);
331 with RdbPath[GP_Cmd] do begin
332 Parent:=PathPage.Surface;
333 Caption:='Run Git from the Windows Command Prompt';
334 Left:=ScaleX(4);
335 Top:=ScaleY(76);
336 Width:=ScaleX(281);
337 Height:=ScaleY(17);
338 Font.Style:=[fsBold];
339 TabOrder:=1;
340 end;
341 LblGitCmd:=TLabel.Create(PathPage);
342 with LblGitCmd do begin
343 Parent:=PathPage.Surface;
344 Caption:=
345 'This option is considered safe and no conflicts with other tools are known.' + #13 +
346 'Only Git will be added to your PATH. Use this option if you want to use Git' + #13 +
347 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
348 Left:=ScaleX(28);
349 Top:=ScaleY(100);
350 Width:=ScaleX(405);
351 Height:=ScaleY(39);
352 end;
354 // 3rd choice
355 RdbPath[GP_CmdTools]:=TRadioButton.Create(PathPage);
356 with RdbPath[GP_CmdTools] do begin
357 Parent:=PathPage.Surface;
358 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
359 Left:=ScaleX(4);
360 Top:=ScaleY(152);
361 Width:=ScaleX(405);
362 Height:=ScaleY(17);
363 Font.Style:=[fsBold];
364 TabOrder:=2;
365 end;
366 LblGitCmdTools:=TLabel.Create(PathPage);
367 with LblGitCmdTools do begin
368 Parent:=PathPage.Surface;
369 Caption:='Both Git and its accompanying Unix tools will be added to your PATH.';
370 Left:=ScaleX(28);
371 Top:=ScaleY(176);
372 Width:=ScaleX(405);
373 Height:=ScaleY(13);
374 end;
375 LblGitCmdToolsWarn:=TLabel.Create(PathPage);
376 with LblGitCmdToolsWarn do begin
377 Parent:=PathPage.Surface;
378 Caption:=
379 'Warning: This will override Windows tools like find.exe and' + #13 +
380 'sort.exe. Select this option only if you understand the implications.';
381 Left:=ScaleX(28);
382 Top:=ScaleY(192);
383 Width:=ScaleX(376);
384 Height:=ScaleY(26);
385 Font.Color:=255;
386 Font.Style:=[fsBold];
387 end;
389 // Restore the setting chosen during a previous install.
390 Data:=GetPreviousData('Path Option','BashOnly');
391 if Data='BashOnly' then begin
392 RdbPath[GP_BashOnly].Checked:=True;
393 end else if Data='Cmd' then begin
394 RdbPath[GP_Cmd].Checked:=True;
395 end else if Data='CmdTools' then begin
396 RdbPath[GP_CmdTools].Checked:=True;
397 end;
400 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
401 * if at least one PuTTY session is found in the Registry.
404 if RegGetSubkeyNames(HKEY_CURRENT_USER,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions) and (GetArrayLength(PuTTYSessions)>0) then begin
405 PuTTYPage:=CreateCustomPage(
406 PrevPageID,
407 'Choosing the SSH executable',
408 'Which Secure Shell client program would you like Git to use?'
410 PrevPageID:=PuTTYPage.ID;
412 // 1st choice
413 RdbSSH[GS_OpenSSH]:=TRadioButton.Create(PuTTYPage);
414 with RdbSSH[GS_OpenSSH] do begin
415 Parent:=PuTTYPage.Surface;
416 Caption:='Use OpenSSH';
417 Left:=ScaleX(4);
418 Top:=ScaleY(8);
419 Width:=ScaleX(129);
420 Height:=ScaleY(17);
421 Font.Style:=[fsBold];
422 TabOrder:=0;
423 Checked:=True;
424 end;
425 LblOpenSSH:=TLabel.Create(PuTTYPage);
426 with LblOpenSSH do begin
427 Parent:=PuTTYPage.Surface;
428 Caption:=
429 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #13 +
430 'environment variables will not be modified.';
431 Left:=ScaleX(28);
432 Top:=ScaleY(32);
433 Width:=ScaleX(324);
434 Height:=ScaleY(26);
435 end;
437 // 2nd choice
438 RdbSSH[GS_Plink]:=TRadioButton.Create(PuTTYPage);
439 with RdbSSH[GS_Plink] do begin
440 Parent:=PuTTYPage.Surface;
441 Caption:='Use (Tortoise)Plink';
442 Left:=ScaleX(4);
443 Top:=ScaleY(76);
444 Width:=ScaleX(281);
445 Height:=ScaleY(17);
446 Font.Style:=[fsBold];
447 TabOrder:=1;
448 end;
449 LblPlink:=TLabel.Create(PuTTYPage);
450 with LblPlink do begin
451 Parent:=PuTTYPage.Surface;
452 Caption:=
453 'PuTTY sessions were found in your Registry. You may specify the path' + #13 +
454 'to an existing copy of (Tortoise)Plink.exe from the TortoiseSVN/CVS' + #13 +
455 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #13 +
456 'variables will be adjusted to point to the following executable:';
457 Left:=ScaleX(28);
458 Top:=ScaleY(100);
459 Width:=ScaleX(340);
460 Height:=ScaleY(52);
461 end;
462 EdtPlink:=TEdit.Create(PuTTYPage);
463 with EdtPlink do begin
464 Parent:=PuTTYPage.Surface;
465 Text:=GetPuTTYLocation;
466 if not FileExists(Text) then begin
467 Text:='';
468 end;
469 Left:=ScaleX(28);
470 Top:=ScaleY(161);
471 Width:=ScaleX(316);
472 Height:=ScaleY(13);
473 end;
474 BtnPlink:=TButton.Create(PuTTYPage);
475 with BtnPlink do begin
476 Parent:=PuTTYPage.Surface;
477 Caption:='...';
478 OnClick:=@BrowseForPuTTYFolder;
479 Left:=ScaleX(348);
480 Top:=ScaleY(161);
481 Width:=ScaleX(21);
482 Height:=ScaleY(21);
483 end;
485 // Restore the setting chosen during a previous install.
486 Data:=GetPreviousData('SSH Option','OpenSSH');
487 if Data='OpenSSH' then begin
488 RdbSSH[GS_OpenSSH].Checked:=True;
489 end else if Data='Plink' then begin
490 RdbSSH[GS_Plink].Checked:=True;
491 end;
492 end else begin
493 PuTTYPage:=NIL;
494 end;
497 * Create a custom page for the core.autocrlf setting.
500 CRLFPage:=CreateCustomPage(
501 PrevPageID,
502 'Configuring the line ending conversions',
503 'How should Git treat line endings in text files?'
505 PrevPageID:=CRLFPage.ID;
507 // 1st choice
508 RdbCRLF[GC_CRLFAlways]:=TRadioButton.Create(CRLFPage);
509 with RdbCRLF[GC_CRLFAlways] do begin
510 Parent:=CRLFPage.Surface;
511 Caption:='Checkout Windows-style, commit Unix-style line endings';
512 Left:=ScaleX(4);
513 Top:=ScaleY(8);
514 Width:=ScaleX(340);
515 Height:=ScaleY(17);
516 Font.Style:=[fsBold];
517 TabOrder:=0;
518 Checked:=True;
519 end;
520 LblCRLFAlways:=TLabel.Create(CRLFPage);
521 with LblCRLFAlways do begin
522 Parent:=CRLFPage.Surface;
523 Caption:=
524 'Git will convert LF to CRLF when checking out text files. When committing' + #13 +
525 'text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
526 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
527 Left:=ScaleX(28);
528 Top:=ScaleY(32);
529 Width:=ScaleX(372);
530 Height:=ScaleY(47);
531 end;
533 // 2nd choice
534 RdbCRLF[GC_LFOnly]:=TRadioButton.Create(CRLFPage);
535 with RdbCRLF[GC_LFOnly] do begin
536 Parent:=CRLFPage.Surface;
537 Caption:='Checkout as-is, commit Unix-style line endings';
538 Left:=ScaleX(4);
539 Top:=ScaleY(80);
540 Width:=ScaleX(340);
541 Height:=ScaleY(17);
542 Font.Style:=[fsBold];
543 TabOrder:=1;
544 Checked:=False;
545 end;
546 LblLFOnly:=TLabel.Create(CRLFPage);
547 with LblLFOnly do begin
548 Parent:=CRLFPage.Surface;
549 Caption:=
550 'Git will not perform any conversion when checking out text files. When' + #13 +
551 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
552 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
553 Left:=ScaleX(28);
554 Top:=ScaleY(104);
555 Width:=ScaleX(372);
556 Height:=ScaleY(47);
557 end;
559 // 3rd choice
560 RdbCRLF[GC_CRLFCommitAsIs]:=TRadioButton.Create(CRLFPage);
561 with RdbCRLF[GC_CRLFCommitAsIs] do begin
562 Parent:=CRLFPage.Surface;
563 Caption:='Checkout as-is, commit as-is';
564 Left:=ScaleX(4);
565 Top:=ScaleY(152);
566 Width:=ScaleX(340);
567 Height:=ScaleY(17);
568 Font.Style:=[fsBold];
569 TabOrder:=2;
570 Checked:=False;
571 end;
572 LblCRLFCommitAsIs:=TLabel.Create(CRLFPage);
573 with LblCRLFCommitAsIs do begin
574 Parent:=CRLFPage.Surface;
575 Caption:=
576 'Git will not perform any conversions when checking out or committing' + #13 +
577 'text files. Choosing this option is not recommended for cross-platform' + #13 +
578 'projects ("core.autocrlf" is set to "false").';
579 Left:=ScaleX(28);
580 Top:=ScaleY(176);
581 Width:=ScaleX(372);
582 Height:=ScaleY(47);
583 end;
585 // Restore the setting chosen during a previous install.
586 Data:=GetPreviousData('CRLF Option','CRLFAlways');
587 if Data='LFOnly' then begin
588 RdbCRLF[GC_LFOnly].Checked:=True;
589 end else if Data='CRLFAlways' then begin
590 RdbCRLF[GC_CRLFAlways].Checked:=True;
591 end else if Data='CRLFCommitAsIs' then begin
592 RdbCRLF[GC_CRLFCommitAsIs].Checked:=True;
593 end;
596 * Create a custom page for finding the processes that lock a module.
599 ProcessesPage:=CreateCustomPage(
600 wpPreparing,
601 'Replacing in-use files',
602 'The following applications use files that need to be replaced, please close them.'
605 ProcessesListBox:=TListBox.Create(ProcessesPage);
606 with ProcessesListBox do begin
607 Parent:=ProcessesPage.Surface;
608 Width:=ProcessesPage.SurfaceWidth;
609 Height:=ProcessesPage.SurfaceHeight-ScaleY(8);
610 end;
612 ProcessesRefresh:=TNewButton.Create(WizardForm);
613 with ProcessesRefresh do begin
614 Parent:=WizardForm;
615 Width:=WizardForm.NextButton.Width;
616 Height:=WizardForm.NextButton.Height;
617 Top:=WizardForm.NextButton.Top;
618 Left:=WizardForm.ClientWidth-WizardForm.NextButton.Left-WizardForm.NextButton.Width;
619 Caption:='&Refresh';
620 OnClick:=@RefreshProcessList;
621 end;
623 // Initially hide the Refresh button, show it when the process page becomes current.
624 ProcessesRefresh.Hide;
625 end;
627 function ShouldSkipPage(PageID:Integer):Boolean;
628 begin
629 if (ProcessesPage<>NIL) and (PageID=ProcessesPage.ID) then begin
630 // This page is only reached forward (by pressing "Next", never by pressing "Back").
631 RefreshProcessList(NIL);
632 Result:=(GetArrayLength(Processes)=0);
633 end else begin
634 Result:=False;
635 end;
636 end;
638 procedure CurPageChanged(CurPageID:Integer);
639 begin
640 // Show the "Refresh" button only on the processes page.
641 if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
642 ProcessesRefresh.Show;
643 end else begin
644 ProcessesRefresh.Hide;
645 end;
646 end;
648 function NextButtonClick(CurPageID:Integer):Boolean;
650 i:Integer;
651 begin
652 Result:=True;
654 if (PuTTYPage<>NIL) and (CurPageID=PuTTYPage.ID) then begin
655 Result:=RdbSSH[GS_OpenSSH].Checked or
656 (RdbSSH[GS_Plink].Checked and FileExists(EdtPlink.Text));
657 if not Result then begin
658 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError,MB_OK);
659 end;
660 end else if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
661 // It would have been nicer to just disable the "Next" button, but the
662 // WizardForm exports the button just read-only.
663 for i:=0 to GetArrayLength(Processes)-1 do begin
664 if not Processes[i].Restartable then begin
665 MsgBox('Setup cannot continue until you close at least those applications in the list that are marked as "closing is required".',mbCriticalError,MB_OK);
666 Result:=False;
667 Exit;
668 end;
669 end;
671 Result:=(GetArrayLength(Processes)=0);
673 if not Result then begin
674 Result:=(MsgBox(
675 'If you continue without closing the listed applications, you will need to log off and on again before changes take effect.' + #13 + #13 +
676 'Are you sure you want to continue anyway?',
677 mbConfirmation,
678 MB_YESNO
679 )=IDYES);
680 end;
681 end;
682 end;
684 // AfterInstall
686 // Even though the name of this procedure suggests otherwise most of the
687 // code below is only executed once after the regular installation code
688 // is finished. This happens because of the if-guard right in the
689 // beginning of this procedure.
690 procedure CurStepChanged(CurStep:TSetupStep);
692 AppDir,FileName,TempName,Cmd,Msg:String;
693 BuiltIns,EnvPath,EnvHome,EnvSSH:TArrayOfString;
694 Count,i:Longint;
695 LinkCreated:Boolean;
696 FindRec:TFindRec;
697 RootKey:Integer;
698 begin
699 if CurStep<>ssPostInstall then begin
700 Exit;
701 end;
703 AppDir:=ExpandConstant('{app}');
706 Create the built-ins
709 // Load the built-ins from a text file.
710 FileName:=ExpandConstant('{app}\{#emit APP_BUILTINS}');
711 if LoadStringsFromFile(FileName,BuiltIns) then begin
712 Count:=GetArrayLength(BuiltIns)-1;
714 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
715 for i:=0 to Count do begin
716 FileName:=AppDir+'\bin\'+ChangeFileExt(ExtractFileName(BuiltIns[i]),'');
717 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
718 Log('Line {#emit __LINE__}: Unable to delete script "'+FileName+'", ignoring.');
719 end;
720 end;
722 // Create built-ins as aliases for git.exe.
723 for i:=0 to Count do begin
724 FileName:=AppDir+'\'+BuiltIns[i];
726 // Delete any existing built-in.
727 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
728 Log('Line {#emit __LINE__}: Unable to delete existing built-in "'+FileName+'", skipping.');
729 continue;
730 end;
733 // This will throw an exception on pre-WinVista systems.
734 LinkCreated:=CreateSymbolicLink(FileName,AppDir+'\bin\git.exe',0);
735 except
736 LinkCreated:=False;
737 Log('Line {#emit __LINE__}: Creating symbolic link "'+FileName+'" failed, will try a hard link.');
738 end;
740 if not LinkCreated then begin
742 // This will throw an exception on pre-Win2k systems.
743 LinkCreated:=CreateHardLink(FileName,AppDir+'\bin\git.exe',0);
744 except
745 LinkCreated:=False;
746 Log('Line {#emit __LINE__}: Creating hardlink "'+FileName+'" failed, will try a copy.');
747 end;
748 end;
750 if not LinkCreated then begin
751 if not FileCopy(AppDir+'\bin\git.exe',FileName,False) then begin
752 Log('Line {#emit __LINE__}: Creating copy "'+FileName+'" failed, giving up.');
753 // This is not a critical error, Git could basically be used without the
754 // aliases for built-ins, so we continue.
755 end;
756 end;
757 end;
759 // Delete any duplicate files in case we are updating from a non-libexec to a libexec directory layout.
760 if FindFirst(AppDir+'\libexec\git-core\*',FindRec) then begin
761 repeat
762 if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0 then begin
763 FileName:=AppDir+'\bin\'+FindRec.name;
764 if (Pos(FindRec.name,'git.exe')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
765 Log('Line {#emit __LINE__}: Unable to delete dupe "'+FileName+'", ignoring.');
766 end;
767 end;
768 until not FindNext(FindRec);
769 FindClose(FindRec);
770 end;
771 end else begin
772 Msg:='Line {#emit __LINE__}: Unable to read file "{#emit APP_BUILTINS}".';
773 MsgBox(Msg,mbError,MB_OK);
774 Log(Msg);
775 // This is not a critical error, Git could basically be used without the
776 // aliases for built-ins, so we continue.
777 end;
780 Adapt core.autocrlf
783 if RdbCRLF[GC_LFOnly].checked then begin
784 Cmd:='core.autocrlf input';
785 end else if RdbCRLF[GC_CRLFAlways].checked then begin
786 Cmd:='core.autocrlf true';
787 end else begin
788 Cmd:='core.autocrlf false';
789 end;
790 if not Exec(AppDir + '\bin\git.exe', 'config -f gitconfig ' + Cmd,
791 AppDir + '\etc', SW_HIDE, ewWaitUntilTerminated, i) then begin
792 Msg:='Unable to configure the line ending conversion: ' + Cmd;
793 MsgBox(Msg,mbError,MB_OK);
794 Log(Msg);
795 // This is not a critical error, the user can probably fix it manually,
796 // so we continue.
797 end;
800 Modify the environment
802 This must happen no later than ssPostInstall to make
803 "ChangesEnvironment=yes" not happend before the change!
806 FileName:=AppDir+'\setup.ini';
808 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
809 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
810 if (GetArrayLength(EnvSSH)=1) and
811 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
812 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
813 Msg:='Line {#emit __LINE__}: Unable to reset GIT_SSH prior to install.';
814 MsgBox(Msg,mbError,MB_OK);
815 Log(Msg);
816 // This is not a critical error, the user can probably fix it manually,
817 // so we continue.
818 end;
819 end;
821 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
822 if (GetArrayLength(EnvSSH)=1) and
823 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
824 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
825 Msg:='Line {#emit __LINE__}: Unable to reset SVN_SSH prior to install.';
826 MsgBox(Msg,mbError,MB_OK);
827 Log(Msg);
828 // This is not a critical error, the user can probably fix it manually,
829 // so we continue.
830 end;
831 end;
833 if (PuTTYPage<>NIL) and RdbSSH[GS_Plink].Checked then begin
834 SetArrayLength(EnvSSH,1);
835 EnvSSH[0]:=EdtPlink.Text;
837 // Set GIT_SSH as specified by the user.
838 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
839 Msg:='Line {#emit __LINE__}: Unable to set the GIT_SSH environment variable.';
840 MsgBox(Msg,mbError,MB_OK);
841 Log(Msg);
842 // This is not a critical error, the user can probably fix it manually,
843 // so we continue.
844 end;
846 // Mark that we have changed GIT_SSH by writing its value to a file.
847 if not SetIniString('Environment','GIT_SSH',EnvSSH[0],FileName) then begin
848 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
849 MsgBox(Msg,mbError,MB_OK);
850 Log(Msg);
851 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
852 // so we continue.
853 end;
855 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
856 StringChangeEx(EnvSSH[0],'\','\\',True);
857 EnvSSH[0]:=AddQuotes(EnvSSH[0]);
859 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
860 Msg:='Line {#emit __LINE__}: Unable to set the SVN_SSH environment variable.';
861 MsgBox(Msg,mbError,MB_OK);
862 Log(Msg);
863 // This is not a critical error, the user can probably fix it manually,
864 // so we continue.
865 end;
867 // Mark that we have changed SVN_SSH by writing its value to a file.
868 if not SetIniString('Environment','SVN_SSH',EnvSSH[0],FileName) then begin
869 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
870 MsgBox(Msg,mbError,MB_OK);
871 Log(Msg);
872 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
873 // so we continue.
874 end;
875 end;
877 // Get the current user's directories in PATH.
878 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
880 // First, remove the installation directory from PATH in any case.
881 for i:=0 to GetArrayLength(EnvPath)-1 do begin
882 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
883 EnvPath[i]:='';
884 end;
885 end;
887 // Delete HOME if a previous installation modified it.
888 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
889 if (GetArrayLength(EnvHome)=1) and
890 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
891 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
892 Msg:='Line {#emit __LINE__}: Unable to reset HOME prior to install.';
893 MsgBox(Msg,mbError,MB_OK);
894 Log(Msg);
895 // This is not a critical error, the user can probably fix it manually,
896 // so we continue.
897 end;
898 end;
900 // Modify the PATH variable as requested by the user.
901 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
902 i:=GetArrayLength(EnvPath);
903 SetArrayLength(EnvPath,i+1);
905 // List \cmd before \bin so \cmd has higher priority and programs in
906 // there will be called in favor of those in \bin.
907 EnvPath[i]:=AppDir+'\cmd';
909 if RdbPath[GP_CmdTools].Checked then begin
910 SetArrayLength(EnvPath,i+2);
911 EnvPath[i+1]:=AppDir+'\bin';
913 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
914 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
915 i:=GetArrayLength(EnvHome);
916 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
917 SetArrayLength(EnvHome,1);
918 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
919 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,EnvHome) then begin
920 Msg:='Line {#emit __LINE__}: Unable to set the HOME environment variable.';
921 MsgBox(Msg,mbError,MB_OK);
922 Log(Msg);
923 // This is not a critical error, the user can probably fix it manually,
924 // so we continue.
925 end;
927 // Mark that we have changed HOME.
928 if not SetIniString('Environment','HOME',EnvHome[0],FileName) then begin
929 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
930 MsgBox(Msg,mbError,MB_OK);
931 Log(Msg);
932 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
933 // so we continue.
934 end;
935 end;
936 end;
937 end;
939 // Set the current user's PATH directories.
940 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
941 Msg:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
942 MsgBox(Msg,mbError,MB_OK);
943 Log(Msg);
944 // This is not a critical error, the user can probably fix it manually,
945 // so we continue.
946 end;
949 Create shortcuts that need to be created regardless of the "Don't create a Start Menu folder" toggle
952 Cmd:=ExpandConstant('{syswow64}\cmd.exe');
953 TempName:='/c ""'+AppDir+'\bin\sh.exe" --login -i"';
954 FileName:=AppDir+'\etc\git.ico';
956 if isComponentSelected('icons\quicklaunch') then begin
957 CreateShellLink(
958 ExpandConstant('{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash.lnk')
959 , 'Git Bash'
960 , Cmd
961 , TempName
962 , '%HOMEDRIVE%%HOMEPATH%'
963 , FileName
965 , SW_SHOWNORMAL
967 end;
968 if isComponentSelected('icons\desktop') then begin
969 CreateShellLink(
970 GetShellFolder('desktop')+'\Git Bash.lnk'
971 , 'Git Bash'
972 , Cmd
973 , TempName
974 , '%HOMEDRIVE%%HOMEPATH%'
975 , FileName
977 , SW_SHOWNORMAL
979 end;
981 // Create a special shortcut that does not set a working directory. This is used by "Git Bash.vbs", which in turn is run by the "Git Bash Here" shell extension.
982 CreateShellLink(
983 AppDir+'\Git Bash.lnk'
984 , 'Git Bash'
985 , Cmd
986 , TempName
987 , ''
988 , FileName
990 , SW_SHOWNORMAL
994 Create the Windows Explorer integrations
997 if IsAdminLoggedOn then begin
998 RootKey:=HKEY_LOCAL_MACHINE;
999 end else begin
1000 RootKey:=HKEY_CURRENT_USER;
1001 end;
1003 if IsComponentSelected('ext\reg\shellhere') then begin
1004 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
1005 (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','','wscript "'+AppDir+'\Git Bash.vbs" "%1"')) then begin
1006 Msg:='Line {#emit __LINE__}: Unable to create "Git Bash Here" shell extension.';
1007 MsgBox(Msg,mbError,MB_OK);
1008 Log(Msg);
1009 // This is not a critical error, the user can probably fix it manually,
1010 // so we continue.
1011 end;
1012 end;
1014 if IsComponentSelected('ext\reg\guihere') then begin
1015 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
1016 (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','','"'+AppDir+'\bin\wish.exe" "'+AppDir+'\libexec\git-core\git-gui" "--working-dir" "%1"')) then begin
1017 Msg:='Line {#emit __LINE__}: Unable to create "Git GUI Here" shell extension.';
1018 MsgBox(Msg,mbError,MB_OK);
1019 Log(Msg);
1020 // This is not a critical error, the user can probably fix it manually,
1021 // so we continue.
1022 end;
1023 end;
1025 // It is either the Registry-based context menu entries, or the shell extension.
1026 if IsComponentSelected('ext\cheetah') then begin
1027 DeleteContextMenuEntries;
1029 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
1030 if not ReplaceInUseFile(FileName,FileName+'.new',True) then begin
1031 Log('Line {#emit __LINE__}: Replacing file "'+FileName+'" failed.');
1032 end;
1033 end;
1034 end;
1036 procedure RegisterPreviousData(PreviousDataKey:Integer);
1038 Data:String;
1039 begin
1040 // Git Path options.
1041 Data:='';
1042 if RdbPath[GP_BashOnly].Checked then begin
1043 Data:='BashOnly';
1044 end else if RdbPath[GP_Cmd].Checked then begin
1045 Data:='Cmd';
1046 end else if RdbPath[GP_CmdTools].Checked then begin
1047 Data:='CmdTools';
1048 end;
1049 SetPreviousData(PreviousDataKey,'Path Option',Data);
1051 // Git SSH options.
1052 Data:='';
1053 if (PuTTYPage=NIL) or RdbSSH[GS_OpenSSH].Checked then begin
1054 Data:='OpenSSH';
1055 end else if RdbSSH[GS_Plink].Checked then begin
1056 Data:='Plink';
1057 end;
1058 SetPreviousData(PreviousDataKey,'SSH Option',Data);
1060 // Line ending conversion options.
1061 Data:='';
1062 if RdbCRLF[GC_LFOnly].Checked then begin
1063 Data:='LFOnly';
1064 end else if RdbCRLF[GC_CRLFAlways].Checked then begin
1065 Data:='CRLFAlways';
1066 end else if RdbCRLF[GC_CRLFCommitAsIs].Checked then begin
1067 Data:='CRLFCommitAsIs';
1068 end;
1069 SetPreviousData(PreviousDataKey,'CRLF Option',Data);
1070 end;
1073 Uninstaller code
1076 function InitializeUninstall:Boolean;
1078 FileName,NewName,Msg:String;
1079 begin
1080 FileName:=ExpandConstant('{app}\bin\ssh-agent.exe');
1081 if FileExists(FileName) then begin
1082 // Create a temporary copy of the file we try to delete.
1083 NewName:=FileName+'.'+IntToStr(1000+Random(9000));
1084 Result:=FileCopy(FileName,NewName,True) and DeleteFile(FileName);
1086 if not Result then begin
1087 Msg:='Line {#emit __LINE__}: Please stop all ssh-agent processes and run uninstall again.';
1088 MsgBox(Msg,mbError,MB_OK);
1089 Log(Msg);
1091 // Clean-up the temporary copy (ignoring any errors).
1092 DeleteFile(NewName);
1093 end else begin
1094 // Clean-up the temporary copy (ignoring any errors).
1095 RenameFile(NewName,FileName);
1096 end;
1097 end else begin
1098 Result:=True;
1099 end;
1100 end;
1102 // PreUninstall
1104 // Even though the name of this function suggests otherwise most of the
1105 // code below is only executed right before the actual uninstallation.
1106 // This happens because of the if-guard right in the beginning of this
1107 // function.
1108 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
1110 AppDir,FileName,Msg:String;
1111 EnvPath,EnvHome,EnvSSH:TArrayOfString;
1112 i:Longint;
1113 begin
1114 if CurUninstallStep<>usUninstall then begin
1115 Exit;
1116 end;
1119 Modify the environment
1121 This must happen no later than usUninstall to make
1122 "ChangesEnvironment=yes" not happend before the change!
1125 AppDir:=ExpandConstant('{app}');
1126 FileName:=AppDir+'\setup.ini';
1128 // Delete the current user's GIT_SSH and SVN_SSH if we set it.
1129 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
1130 if (GetArrayLength(EnvSSH)=1) and
1131 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
1132 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
1133 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to GIT_SSH.';
1134 MsgBox(Msg,mbError,MB_OK);
1135 Log(Msg);
1136 // This is not a critical error, the user can probably fix it manually,
1137 // so we continue.
1138 end;
1139 end;
1141 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
1142 if (GetArrayLength(EnvSSH)=1) and
1143 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
1144 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
1145 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to SVN_SSH.';
1146 MsgBox(Msg,mbError,MB_OK);
1147 Log(Msg);
1148 // This is not a critical error, the user can probably fix it manually,
1149 // so we continue.
1150 end;
1151 end;
1153 // Get the current user's directories in PATH.
1154 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
1156 // Remove the installation directory from PATH in any case, even if it
1157 // was not added by the installer.
1158 for i:=0 to GetArrayLength(EnvPath)-1 do begin
1159 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
1160 EnvPath[i]:='';
1161 end;
1162 end;
1164 // Reset the current user's directories in PATH.
1165 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
1166 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to PATH.';
1167 MsgBox(Msg,mbError,MB_OK);
1168 Log(Msg);
1169 // This is not a critical error, the user can probably fix it manually,
1170 // so we continue.
1171 end;
1173 // Reset the current user's HOME if we modified it.
1174 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
1175 if (GetArrayLength(EnvHome)=1) and
1176 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
1177 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
1178 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
1179 MsgBox(Msg,mbError,MB_OK);
1180 Log(Msg);
1181 // This is not a critical error, the user can probably fix it manually,
1182 // so we continue.
1183 end;
1184 end;
1186 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
1187 Msg:='Line {#emit __LINE__}: Unable to delete file "'+FileName+'".';
1188 MsgBox(Msg,mbError,MB_OK);
1189 Log(Msg);
1190 // This is not a critical error, the user can probably fix it manually,
1191 // so we continue.
1192 end;
1195 Delete the Windows Explorer integrations
1198 DeleteContextMenuEntries;
1200 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
1201 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
1202 Msg:='Line {#emit __LINE__}: Unable to delete file "'+FileName+'". Please delete it manually after logging off and on again.';
1203 MsgBox(Msg,mbError,MB_OK);
1204 Log(Msg);
1205 end;
1206 end;