Installer: Make more use of AppDir instead of expanding {app}
[msysgit/mtrensch.git] / share / WinGit / install.iss
blob535ae0f677ea9dbf67e668061a13480ab3e37a61
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 Source: *; DestDir: {app}; Excludes: \*.bmp, gpl-2.0.rtf, \*.iss, \tmp.*, \bin\*install*; Flags: recursesubdirs replacesameversion
56 Source: ReleaseNotes.rtf; DestDir: {app}; Flags: isreadme replacesameversion
58 [Icons]
59 Name: {group}\Git GUI; Filename: {app}\bin\wish.exe; Parameters: """{app}\libexec\git-core\git-gui"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
60 Name: {group}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
61 Name: {group}\Uninstall Git; Filename: {uninstallexe}
62 Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico; Components: icons\quicklaunch
63 Name: {code:GetShellFolder|desktop}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico; Components: icons\desktop
65 ; 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.
66 Name: {app}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; IconFilename: {app}\etc\git.ico
68 [Messages]
69 BeveledLabel={#emit APP_URL}
70 SetupAppTitle={#emit APP_NAME} Setup
71 SetupWindowTitle={#emit APP_NAME} Setup
73 [Registry]
74 ; There is no "Console" key in HKLM.
75 Root: HKCU; Subkey: Console; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Components: consolefont
76 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Components: consolefont
77 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Components: consolefont
78 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Components: consolefont
80 Root: HKCU; Subkey: Console\Git Bash; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Flags: createvalueifdoesntexist
81 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Flags: createvalueifdoesntexist
82 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Flags: createvalueifdoesntexist
83 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Flags: createvalueifdoesntexist
85 ; File associations for configuration files that may be contained in a repository (so this does not include ".gitconfig").
86 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
87 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
88 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
89 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
90 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
91 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
93 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
94 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
95 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
96 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
97 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
98 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
100 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
101 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
102 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: IsAdminLoggedOn; Components: assoc
103 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
104 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
105 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist; Check: not IsAdminLoggedOn; Components: assoc
107 [UninstallDelete]
108 ; Delete the built-ins.
109 Type: files; Name: {app}\bin\git-*.exe
110 Type: files; Name: {app}\libexec\git-core\git-*.exe
111 Type: files; Name: {app}\libexec\git-core\git.exe
113 ; Delete any (temporary) git-cheetah files.
114 Type: files; Name: {app}\git-cheetah\*.*
116 ; Delete a home directory inside the msysGit directory.
117 Type: dirifempty; Name: {app}\home\{username}
118 Type: dirifempty; Name: {app}\home
120 [Code]
121 #include "helpers.inc.iss"
122 #include "putty.inc.iss"
123 #include "modules.inc.iss"
125 function CreateHardLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
126 #ifdef UNICODE
127 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
128 #else
129 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
130 #endif
132 function CreateSymbolicLink(lpSymlinkFileName,lpTargetFileName:String;dwFlags:DWORD):Boolean;
133 #ifdef UNICODE
134 external 'CreateSymbolicLinkW@Kernel32.dll stdcall delayload setuponly';
135 #else
136 external 'CreateSymbolicLinkA@Kernel32.dll stdcall delayload setuponly';
137 #endif
139 const
140 // Git Path options.
141 GP_BashOnly = 1;
142 GP_Cmd = 2;
143 GP_CmdTools = 3;
145 // Git SSH options.
146 GS_OpenSSH = 1;
147 GS_Plink = 2;
149 // Git line ending conversion options.
150 GC_LFOnly = 1;
151 GC_CRLFAlways = 2;
152 GC_CRLFCommitAsIs = 3;
155 // Wizard page and variables for the Path options.
156 PathPage:TWizardPage;
157 RdbPath:array[GP_BashOnly..GP_CmdTools] of TRadioButton;
159 // Wizard page and variables for the SSH options.
160 PuTTYPage:TWizardPage;
161 RdbSSH:array[GS_OpenSSH..GS_Plink] of TRadioButton;
162 EdtPlink:TEdit;
164 // Wizard page and variables for the line ending conversion options.
165 CRLFPage:TWizardPage;
166 RdbCRLF:array[GC_LFOnly..GC_CRLFCommitAsIs] of TRadioButton;
168 // Wizard page and variables for the processes page.
169 Processes:ProcessList;
170 ProcessesPage:TWizardPage;
171 ProcessesListBox:TListBox;
172 ProcessesRefresh:TButton;
174 procedure BrowseForPuTTYFolder(Sender:TObject);
176 Path:String;
177 begin
178 Path:=ExtractFilePath(EdtPlink.Text);
179 BrowseForFolder('Please select the PuTTY folder:',Path,False);
180 if FileExists(Path+'\TortoisePlink.exe') then begin
181 EdtPlink.Text:=Path+'\TortoisePlink.exe';
182 RdbSSH[GS_Plink].Checked:=True;
183 end else if FileExists(Path+'\plink.exe') then begin
184 EdtPlink.Text:=Path+'\plink.exe';
185 RdbSSH[GS_Plink].Checked:=True;
186 end else begin
187 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError,MB_OK);
188 end;
189 end;
191 procedure DeleteContextMenuEntries;
193 AppDir,Command,Msg:String;
194 RootKey:Integer;
195 begin
196 AppDir:=ExpandConstant('{app}');
198 if IsAdminLoggedOn then begin
199 RootKey:=HKEY_LOCAL_MACHINE;
200 end else begin
201 RootKey:=HKEY_CURRENT_USER;
202 end;
204 Command:='';
205 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command);
206 if Pos(AppDir,Command)>0 then begin
207 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
208 Msg:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
209 MsgBox(Msg,mbError,MB_OK);
210 Log(Msg);
211 // This is not a critical error, the user can probably fix it manually,
212 // so we continue.
213 end;
214 end;
216 Command:='';
217 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command);
218 if Pos(AppDir,Command)>0 then begin
219 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
220 Msg:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
221 MsgBox(Msg,mbError,MB_OK);
222 Log(Msg);
223 // This is not a critical error, the user can probably fix it manually,
224 // so we continue.
225 end;
226 end;
227 end;
229 procedure RefreshProcessList(Sender:TObject);
231 i:Longint;
232 Caption:String;
233 begin
234 ProcessesListBox.Items.Clear;
235 if (Sender=NIL) or (FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),Processes)) then begin
236 for i:=0 to GetArrayLength(Processes)-1 do begin
237 Caption:=Processes[i].Name+' (PID '+IntToStr(Processes[i].ID)+')';
238 ProcessesListBox.Items.Append(Caption);
239 end;
240 end;
241 end;
244 Installer code
247 procedure InitializeWizard;
249 i,PrevPageID:Integer;
250 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
251 LblOpenSSH,LblPlink:TLabel;
252 PuTTYSessions:TArrayOfString;
253 LblLFOnly,LblCRLFAlways,LblCRLFCommitAsIs:TLabel;
254 BtnPlink:TButton;
255 Data:String;
256 begin
257 // Until we have a 64-bit version of git-cheetah, disable it on 64-bit Windows.
258 if isWin64 then begin
259 for i:=0 to WizardForm.ComponentsList.Items.Count-1 do begin
260 Data:=LowerCase(WizardForm.ComponentsList.ItemCaption[i]);
261 if Pos('context',Data)>0 then begin
262 // Select the Registry-based context menu entries.
263 WizardForm.ComponentsList.Checked[i]:=True;
264 end else if Pos('cheetah',Data)>0 then begin
265 // Disable the git-cheetah shell extension.
266 WizardForm.ComponentsList.ItemEnabled[i]:=False;
267 end;
268 end;
269 end;
271 PrevPageID:=wpSelectProgramGroup;
274 * Create a custom page for modifying the environment.
277 PathPage:=CreateCustomPage(
278 PrevPageID,
279 'Adjusting your PATH environment',
280 'How would you like to use Git from the command line?'
282 PrevPageID:=PathPage.ID;
284 // 1st choice
285 RdbPath[GP_BashOnly]:=TRadioButton.Create(PathPage);
286 with RdbPath[GP_BashOnly] do begin
287 Parent:=PathPage.Surface;
288 Caption:='Use Git Bash only';
289 Left:=ScaleX(4);
290 Top:=ScaleY(8);
291 Width:=ScaleX(129);
292 Height:=ScaleY(17);
293 Font.Style:=[fsBold];
294 TabOrder:=0;
295 Checked:=True;
296 end;
297 LblGitBash:=TLabel.Create(PathPage);
298 with LblGitBash do begin
299 Parent:=PathPage.Surface;
300 Caption:=
301 'This is the most conservative choice if you are concerned about the stability' + #13 +
302 'of your system. Your PATH will not be modified.';
303 Left:=ScaleX(28);
304 Top:=ScaleY(32);
305 Width:=ScaleX(405);
306 Height:=ScaleY(26);
307 end;
309 // 2nd choice
310 RdbPath[GP_Cmd]:=TRadioButton.Create(PathPage);
311 with RdbPath[GP_Cmd] do begin
312 Parent:=PathPage.Surface;
313 Caption:='Run Git from the Windows Command Prompt';
314 Left:=ScaleX(4);
315 Top:=ScaleY(76);
316 Width:=ScaleX(281);
317 Height:=ScaleY(17);
318 Font.Style:=[fsBold];
319 TabOrder:=1;
320 end;
321 LblGitCmd:=TLabel.Create(PathPage);
322 with LblGitCmd do begin
323 Parent:=PathPage.Surface;
324 Caption:=
325 'This option is considered safe and no conflicts with other tools are known.' + #13 +
326 'Only Git will be added to your PATH. Use this option if you want to use Git' + #13 +
327 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
328 Left:=ScaleX(28);
329 Top:=ScaleY(100);
330 Width:=ScaleX(405);
331 Height:=ScaleY(39);
332 end;
334 // 3rd choice
335 RdbPath[GP_CmdTools]:=TRadioButton.Create(PathPage);
336 with RdbPath[GP_CmdTools] do begin
337 Parent:=PathPage.Surface;
338 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
339 Left:=ScaleX(4);
340 Top:=ScaleY(152);
341 Width:=ScaleX(405);
342 Height:=ScaleY(17);
343 Font.Style:=[fsBold];
344 TabOrder:=2;
345 end;
346 LblGitCmdTools:=TLabel.Create(PathPage);
347 with LblGitCmdTools do begin
348 Parent:=PathPage.Surface;
349 Caption:='Both Git and its accompanying Unix tools will be added to your PATH.';
350 Left:=ScaleX(28);
351 Top:=ScaleY(176);
352 Width:=ScaleX(405);
353 Height:=ScaleY(13);
354 end;
355 LblGitCmdToolsWarn:=TLabel.Create(PathPage);
356 with LblGitCmdToolsWarn do begin
357 Parent:=PathPage.Surface;
358 Caption:=
359 'Warning: This will override Windows tools like find.exe and' + #13 +
360 'sort.exe. Select this option only if you understand the implications.';
361 Left:=ScaleX(28);
362 Top:=ScaleY(192);
363 Width:=ScaleX(376);
364 Height:=ScaleY(26);
365 Font.Color:=255;
366 Font.Style:=[fsBold];
367 end;
369 // Restore the setting chosen during a previous install.
370 Data:=GetPreviousData('Path Option','BashOnly');
371 if Data='BashOnly' then begin
372 RdbPath[GP_BashOnly].Checked:=True;
373 end else if Data='Cmd' then begin
374 RdbPath[GP_Cmd].Checked:=True;
375 end else if Data='CmdTools' then begin
376 RdbPath[GP_CmdTools].Checked:=True;
377 end;
380 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
381 * if at least one PuTTY session is found in the Registry.
384 if RegGetSubkeyNames(HKEY_CURRENT_USER,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions) and (GetArrayLength(PuTTYSessions)>0) then begin
385 PuTTYPage:=CreateCustomPage(
386 PrevPageID,
387 'Choosing the SSH executable',
388 'Which Secure Shell client program would you like Git to use?'
390 PrevPageID:=PuTTYPage.ID;
392 // 1st choice
393 RdbSSH[GS_OpenSSH]:=TRadioButton.Create(PuTTYPage);
394 with RdbSSH[GS_OpenSSH] do begin
395 Parent:=PuTTYPage.Surface;
396 Caption:='Use OpenSSH';
397 Left:=ScaleX(4);
398 Top:=ScaleY(8);
399 Width:=ScaleX(129);
400 Height:=ScaleY(17);
401 Font.Style:=[fsBold];
402 TabOrder:=0;
403 Checked:=True;
404 end;
405 LblOpenSSH:=TLabel.Create(PuTTYPage);
406 with LblOpenSSH do begin
407 Parent:=PuTTYPage.Surface;
408 Caption:=
409 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #13 +
410 'environment variables will not be modified.';
411 Left:=ScaleX(28);
412 Top:=ScaleY(32);
413 Width:=ScaleX(324);
414 Height:=ScaleY(26);
415 end;
417 // 2nd choice
418 RdbSSH[GS_Plink]:=TRadioButton.Create(PuTTYPage);
419 with RdbSSH[GS_Plink] do begin
420 Parent:=PuTTYPage.Surface;
421 Caption:='Use (Tortoise)Plink';
422 Left:=ScaleX(4);
423 Top:=ScaleY(76);
424 Width:=ScaleX(281);
425 Height:=ScaleY(17);
426 Font.Style:=[fsBold];
427 TabOrder:=1;
428 end;
429 LblPlink:=TLabel.Create(PuTTYPage);
430 with LblPlink do begin
431 Parent:=PuTTYPage.Surface;
432 Caption:=
433 'PuTTY sessions were found in your Registry. You may specify the path' + #13 +
434 'to an existing copy of (Tortoise)Plink.exe from the TortoiseSVN/CVS' + #13 +
435 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #13 +
436 'variables will be adjusted to point to the following executable:';
437 Left:=ScaleX(28);
438 Top:=ScaleY(100);
439 Width:=ScaleX(340);
440 Height:=ScaleY(52);
441 end;
442 EdtPlink:=TEdit.Create(PuTTYPage);
443 with EdtPlink do begin
444 Parent:=PuTTYPage.Surface;
445 Text:=GetPuTTYLocation;
446 if not FileExists(Text) then begin
447 Text:='';
448 end;
449 Left:=ScaleX(28);
450 Top:=ScaleY(161);
451 Width:=ScaleX(316);
452 Height:=ScaleY(13);
453 end;
454 BtnPlink:=TButton.Create(PuTTYPage);
455 with BtnPlink do begin
456 Parent:=PuTTYPage.Surface;
457 Caption:='...';
458 OnClick:=@BrowseForPuTTYFolder;
459 Left:=ScaleX(348);
460 Top:=ScaleY(161);
461 Width:=ScaleX(21);
462 Height:=ScaleY(21);
463 end;
465 // Restore the setting chosen during a previous install.
466 Data:=GetPreviousData('SSH Option','OpenSSH');
467 if Data='OpenSSH' then begin
468 RdbSSH[GS_OpenSSH].Checked:=True;
469 end else if Data='Plink' then begin
470 RdbSSH[GS_Plink].Checked:=True;
471 end;
472 end else begin
473 PuTTYPage:=NIL;
474 end;
477 * Create a custom page for the core.autocrlf setting.
480 CRLFPage:=CreateCustomPage(
481 PrevPageID,
482 'Configuring the line ending conversions',
483 'How should Git treat line endings in text files?'
485 PrevPageID:=CRLFPage.ID;
487 // 1st choice
488 RdbCRLF[GC_CRLFAlways]:=TRadioButton.Create(CRLFPage);
489 with RdbCRLF[GC_CRLFAlways] do begin
490 Parent:=CRLFPage.Surface;
491 Caption:='Checkout Windows-style, commit Unix-style line endings';
492 Left:=ScaleX(4);
493 Top:=ScaleY(8);
494 Width:=ScaleX(340);
495 Height:=ScaleY(17);
496 Font.Style:=[fsBold];
497 TabOrder:=0;
498 Checked:=True;
499 end;
500 LblCRLFAlways:=TLabel.Create(CRLFPage);
501 with LblCRLFAlways do begin
502 Parent:=CRLFPage.Surface;
503 Caption:=
504 'Git will convert LF to CRLF when checking out text files. When committing' + #13 +
505 'text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
506 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
507 Left:=ScaleX(28);
508 Top:=ScaleY(32);
509 Width:=ScaleX(372);
510 Height:=ScaleY(47);
511 end;
513 // 2nd choice
514 RdbCRLF[GC_LFOnly]:=TRadioButton.Create(CRLFPage);
515 with RdbCRLF[GC_LFOnly] do begin
516 Parent:=CRLFPage.Surface;
517 Caption:='Checkout as-is, commit Unix-style line endings';
518 Left:=ScaleX(4);
519 Top:=ScaleY(80);
520 Width:=ScaleX(340);
521 Height:=ScaleY(17);
522 Font.Style:=[fsBold];
523 TabOrder:=1;
524 Checked:=False;
525 end;
526 LblLFOnly:=TLabel.Create(CRLFPage);
527 with LblLFOnly do begin
528 Parent:=CRLFPage.Surface;
529 Caption:=
530 'Git will not perform any conversion when checking out text files. When' + #13 +
531 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
532 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
533 Left:=ScaleX(28);
534 Top:=ScaleY(104);
535 Width:=ScaleX(372);
536 Height:=ScaleY(47);
537 end;
539 // 3rd choice
540 RdbCRLF[GC_CRLFCommitAsIs]:=TRadioButton.Create(CRLFPage);
541 with RdbCRLF[GC_CRLFCommitAsIs] do begin
542 Parent:=CRLFPage.Surface;
543 Caption:='Checkout as-is, commit as-is';
544 Left:=ScaleX(4);
545 Top:=ScaleY(152);
546 Width:=ScaleX(340);
547 Height:=ScaleY(17);
548 Font.Style:=[fsBold];
549 TabOrder:=2;
550 Checked:=False;
551 end;
552 LblCRLFCommitAsIs:=TLabel.Create(CRLFPage);
553 with LblCRLFCommitAsIs do begin
554 Parent:=CRLFPage.Surface;
555 Caption:=
556 'Git will not perform any conversions when checking out or committing' + #13 +
557 'text files. Choosing this option is not recommended for cross-platform' + #13 +
558 'projects ("core.autocrlf" is set to "false").';
559 Left:=ScaleX(28);
560 Top:=ScaleY(176);
561 Width:=ScaleX(372);
562 Height:=ScaleY(47);
563 end;
565 // Restore the setting chosen during a previous install.
566 Data:=GetPreviousData('CRLF Option','CRLFAlways');
567 if Data='LFOnly' then begin
568 RdbCRLF[GC_LFOnly].Checked:=True;
569 end else if Data='CRLFAlways' then begin
570 RdbCRLF[GC_CRLFAlways].Checked:=True;
571 end else if Data='CRLFCommitAsIs' then begin
572 RdbCRLF[GC_CRLFCommitAsIs].Checked:=True;
573 end;
576 * Create a custom page for finding the processes that lock a module.
579 ProcessesPage:=CreateCustomPage(
580 wpPreparing,
581 'Replacing in-use files',
582 'The following applications use files that need to be replaced, please close them.'
585 ProcessesListBox:=TListBox.Create(ProcessesPage);
586 with ProcessesListBox do begin
587 Parent:=ProcessesPage.Surface;
588 Width:=ProcessesPage.SurfaceWidth;
589 Height:=ProcessesPage.SurfaceHeight-ScaleY(8);
590 end;
592 ProcessesRefresh:=TNewButton.Create(WizardForm);
593 with ProcessesRefresh do begin
594 Parent:=WizardForm;
595 Width:=WizardForm.NextButton.Width;
596 Height:=WizardForm.NextButton.Height;
597 Top:=WizardForm.NextButton.Top;
598 Left:=WizardForm.ClientWidth-WizardForm.NextButton.Left-WizardForm.NextButton.Width;
599 Caption:='&Refresh';
600 OnClick:=@RefreshProcessList;
601 end;
603 // Initially hide the Refresh button, show it when the process page becomes current.
604 ProcessesRefresh.Hide;
605 end;
607 function ShouldSkipPage(PageID:Integer):Boolean;
608 begin
609 if (ProcessesPage<>NIL) and (PageID=ProcessesPage.ID) then begin
610 Result:=(not FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),Processes))
611 or (GetArrayLength(Processes)=0);
612 end else begin
613 Result:=False;
614 end;
615 end;
617 procedure CurPageChanged(CurPageID:Integer);
618 begin
619 if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
620 RefreshProcessList(NIL);
621 ProcessesRefresh.Show;
622 end else begin
623 ProcessesRefresh.Hide;
624 end;
625 end;
627 function NextButtonClick(CurPageID:Integer):Boolean;
628 begin
629 Result:=True;
631 if (PuTTYPage<>NIL) and (CurPageID=PuTTYPage.ID) then begin
632 Result:=RdbSSH[GS_OpenSSH].Checked or
633 (RdbSSH[GS_Plink].Checked and FileExists(EdtPlink.Text));
634 if not Result then begin
635 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError,MB_OK);
636 end;
637 end else if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
638 Result:=(ProcessesListBox.Items.Count=0);
639 if not Result then begin
640 Result:=(MsgBox(
641 'If you continue without closing the listed applications you need to log off and on again before changes take effect.' + #13 +
642 'Are you sure you want to continue anyway?',
643 mbConfirmation,
644 MB_YESNO
645 )=IDYES);
646 end;
647 end;
648 end;
650 // AfterInstall
652 // Even though the name of this procedure suggests otherwise most of the
653 // code below is only executed once after the regular installation code
654 // is finished. This happens because of the if-guard right in the
655 // beginning of this procedure.
656 procedure CurStepChanged(CurStep:TSetupStep);
658 AppDir,FileName,TempName,Cmd,Msg:String;
659 BuiltIns,EnvPath,EnvHome,EnvSSH:TArrayOfString;
660 Count,i:Longint;
661 LinkCreated:Boolean;
662 FindRec:TFindRec;
663 RootKey:Integer;
664 begin
665 if CurStep<>ssPostInstall then begin
666 Exit;
667 end;
669 AppDir:=ExpandConstant('{app}');
672 Create the built-ins
675 // Load the built-ins from a text file.
676 FileName:=ExpandConstant('{app}\{#emit APP_BUILTINS}');
677 if LoadStringsFromFile(FileName,BuiltIns) then begin
678 Count:=GetArrayLength(BuiltIns)-1;
680 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
681 for i:=0 to Count do begin
682 FileName:=AppDir+'\bin\'+ChangeFileExt(ExtractFileName(BuiltIns[i]),'');
683 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
684 Log('Line {#emit __LINE__}: Unable to delete script "'+FileName+'", ignoring.');
685 end;
686 end;
688 // Create built-ins as aliases for git.exe.
689 for i:=0 to Count do begin
690 FileName:=AppDir+'\'+BuiltIns[i];
692 // Delete any existing built-in.
693 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
694 Log('Line {#emit __LINE__}: Unable to delete existing built-in "'+FileName+'", skipping.');
695 continue;
696 end;
699 // This will throw an exception on pre-WinVista systems.
700 LinkCreated:=CreateSymbolicLink(FileName,AppDir+'\bin\git.exe',0);
701 except
702 LinkCreated:=False;
703 Log('Line {#emit __LINE__}: Creating symbolic link "'+FileName+'" failed, will try a hard link.');
704 end;
706 if not LinkCreated then begin
708 // This will throw an exception on pre-Win2k systems.
709 LinkCreated:=CreateHardLink(FileName,AppDir+'\bin\git.exe',0);
710 except
711 LinkCreated:=False;
712 Log('Line {#emit __LINE__}: Creating hardlink "'+FileName+'" failed, will try a copy.');
713 end;
714 end;
716 if not LinkCreated then begin
717 if not FileCopy(AppDir+'\bin\git.exe',FileName,False) then begin
718 Log('Line {#emit __LINE__}: Creating copy "'+FileName+'" failed, giving up.');
719 // This is not a critical error, Git could basically be used without the
720 // aliases for built-ins, so we continue.
721 end;
722 end;
723 end;
725 // Delete any duplicate files in case we are updating from a non-libexec to a libexec directory layout.
726 if FindFirst(AppDir+'\libexec\git-core\*',FindRec) then begin
727 repeat
728 if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0 then begin
729 FileName:=AppDir+'\bin\'+FindRec.name;
730 if (Pos(FindRec.name,'git.exe')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
731 Log('Line {#emit __LINE__}: Unable to delete dupe "'+FileName+'", ignoring.');
732 end;
733 end;
734 until not FindNext(FindRec);
735 FindClose(FindRec);
736 end;
737 end else begin
738 Msg:='Line {#emit __LINE__}: Unable to read file "{#emit APP_BUILTINS}".';
739 MsgBox(Msg,mbError,MB_OK);
740 Log(Msg);
741 // This is not a critical error, Git could basically be used without the
742 // aliases for built-ins, so we continue.
743 end;
746 Adapt core.autocrlf
749 if RdbCRLF[GC_LFOnly].checked then begin
750 Cmd:='core.autocrlf input';
751 end else if RdbCRLF[GC_CRLFAlways].checked then begin
752 Cmd:='core.autocrlf true';
753 end else begin
754 Cmd:='core.autocrlf false';
755 end;
756 if not Exec(AppDir + '\bin\git.exe', 'config -f gitconfig ' + Cmd,
757 AppDir + '\etc', SW_HIDE, ewWaitUntilTerminated, i) then begin
758 Msg:='Unable to configure the line ending conversion: ' + Cmd;
759 MsgBox(Msg,mbError,MB_OK);
760 Log(Msg);
761 // This is not a critical error, the user can probably fix it manually,
762 // so we continue.
763 end;
766 Modify the environment
768 This must happen no later than ssPostInstall to make
769 "ChangesEnvironment=yes" not happend before the change!
772 FileName:=AppDir+'\setup.ini';
774 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
775 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
776 if (GetArrayLength(EnvSSH)=1) and
777 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
778 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
779 Msg:='Line {#emit __LINE__}: Unable to reset GIT_SSH prior to install.';
780 MsgBox(Msg,mbError,MB_OK);
781 Log(Msg);
782 // This is not a critical error, the user can probably fix it manually,
783 // so we continue.
784 end;
785 end;
787 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
788 if (GetArrayLength(EnvSSH)=1) and
789 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
790 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
791 Msg:='Line {#emit __LINE__}: Unable to reset SVN_SSH prior to install.';
792 MsgBox(Msg,mbError,MB_OK);
793 Log(Msg);
794 // This is not a critical error, the user can probably fix it manually,
795 // so we continue.
796 end;
797 end;
799 if (PuTTYPage<>NIL) and RdbSSH[GS_Plink].Checked then begin
800 SetArrayLength(EnvSSH,1);
801 EnvSSH[0]:=EdtPlink.Text;
803 // Set GIT_SSH as specified by the user.
804 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
805 Msg:='Line {#emit __LINE__}: Unable to set the GIT_SSH environment variable.';
806 MsgBox(Msg,mbError,MB_OK);
807 Log(Msg);
808 // This is not a critical error, the user can probably fix it manually,
809 // so we continue.
810 end;
812 // Mark that we have changed GIT_SSH by writing its value to a file.
813 if not SetIniString('Environment','GIT_SSH',EnvSSH[0],FileName) then begin
814 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
815 MsgBox(Msg,mbError,MB_OK);
816 Log(Msg);
817 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
818 // so we continue.
819 end;
821 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
822 StringChangeEx(EnvSSH[0],'\','\\',True);
823 EnvSSH[0]:=AddQuotes(EnvSSH[0]);
825 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
826 Msg:='Line {#emit __LINE__}: Unable to set the SVN_SSH environment variable.';
827 MsgBox(Msg,mbError,MB_OK);
828 Log(Msg);
829 // This is not a critical error, the user can probably fix it manually,
830 // so we continue.
831 end;
833 // Mark that we have changed SVN_SSH by writing its value to a file.
834 if not SetIniString('Environment','SVN_SSH',EnvSSH[0],FileName) then begin
835 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
836 MsgBox(Msg,mbError,MB_OK);
837 Log(Msg);
838 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
839 // so we continue.
840 end;
841 end;
843 // Get the current user's directories in PATH.
844 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
846 // First, remove the installation directory from PATH in any case.
847 for i:=0 to GetArrayLength(EnvPath)-1 do begin
848 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
849 EnvPath[i]:='';
850 end;
851 end;
853 // Delete HOME if a previous installation modified it.
854 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
855 if (GetArrayLength(EnvHome)=1) and
856 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
857 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
858 Msg:='Line {#emit __LINE__}: Unable to reset HOME prior to install.';
859 MsgBox(Msg,mbError,MB_OK);
860 Log(Msg);
861 // This is not a critical error, the user can probably fix it manually,
862 // so we continue.
863 end;
864 end;
866 // Modify the PATH variable as requested by the user.
867 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
868 i:=GetArrayLength(EnvPath);
869 SetArrayLength(EnvPath,i+1);
871 // List \cmd before \bin so \cmd has higher priority and programs in
872 // there will be called in favor of those in \bin.
873 EnvPath[i]:=AppDir+'\cmd';
875 if RdbPath[GP_CmdTools].Checked then begin
876 SetArrayLength(EnvPath,i+2);
877 EnvPath[i+1]:=AppDir+'\bin';
879 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
880 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
881 i:=GetArrayLength(EnvHome);
882 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
883 SetArrayLength(EnvHome,1);
884 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
885 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,EnvHome) then begin
886 Msg:='Line {#emit __LINE__}: Unable to set the HOME environment variable.';
887 MsgBox(Msg,mbError,MB_OK);
888 Log(Msg);
889 // This is not a critical error, the user can probably fix it manually,
890 // so we continue.
891 end;
893 // Mark that we have changed HOME.
894 if not SetIniString('Environment','HOME',EnvHome[0],FileName) then begin
895 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
896 MsgBox(Msg,mbError,MB_OK);
897 Log(Msg);
898 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
899 // so we continue.
900 end;
901 end;
902 end;
903 end;
905 // Set the current user's PATH directories.
906 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
907 Msg:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
908 MsgBox(Msg,mbError,MB_OK);
909 Log(Msg);
910 // This is not a critical error, the user can probably fix it manually,
911 // so we continue.
912 end;
915 Create the Windows Explorer integrations
918 if IsAdminLoggedOn then begin
919 RootKey:=HKEY_LOCAL_MACHINE;
920 end else begin
921 RootKey:=HKEY_CURRENT_USER;
922 end;
924 if IsComponentSelected('ext\reg\shellhere') then begin
925 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
926 (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','','wscript "'+AppDir+'\Git Bash.vbs" "%1"')) then begin
927 Msg:='Line {#emit __LINE__}: Unable to create "Git Bash Here" shell extension.';
928 MsgBox(Msg,mbError,MB_OK);
929 Log(Msg);
930 // This is not a critical error, the user can probably fix it manually,
931 // so we continue.
932 end;
933 end;
935 if IsComponentSelected('ext\reg\guihere') then begin
936 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
937 (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
938 Msg:='Line {#emit __LINE__}: Unable to create "Git GUI Here" shell extension.';
939 MsgBox(Msg,mbError,MB_OK);
940 Log(Msg);
941 // This is not a critical error, the user can probably fix it manually,
942 // so we continue.
943 end;
944 end;
946 // It is either the Registry-based context menu entries, or the shell extension.
947 if IsComponentSelected('ext\cheetah') then begin
948 DeleteContextMenuEntries;
950 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
951 TempName:=GenerateUniqueName(ExtractFilePath(FileName),'.git_shell_ext');
953 // Try to delete any previously renamed old shell extension files.
954 DelTree(ExtractFilePath(FileName)+'\*.git_shell_ext',False,True,False);
956 if FileExists(FileName) then begin
957 if not UnregisterServer(Is64BitInstallMode,FileName,False) then begin
958 Msg:='Line {#emit __LINE__}: Unable to unregister "'+FileName+'".';
959 MsgBox(Msg,mbError,MB_OK);
960 Log(Msg);
961 // This is not a critical error, the user can probably fix it manually,
962 // so we continue.
963 end;
965 if (not DeleteFile(FileName)) and (not RenameFile(FileName,TempName)) then begin
966 Msg:='Line {#emit __LINE__}: Unable to delete or rename "'+FileName+'".';
967 MsgBox(Msg,mbError,MB_OK);
968 Log(Msg);
969 // This is pretty much critical, but will be catched below when
970 // renaming the new shell extension file fails.
971 end;
972 end;
974 if not RenameFile(FileName+'.new',FileName) then begin
975 Msg:='Line {#emit __LINE__}: Unable to install git-cheetah. Please do it manually by renaming' + #13 + #13 +
976 '"'+FileName+'.new" to "'+FileName+'"' + #13 + #13 +
977 'and registering the shell extension by typing' + #13 + #13 +
978 '"regsvr32 '+ExtractFileName(FileName)+'"' + #13 + #13 +
979 'at the command prompt in the git-cheetah directory.';
980 MsgBox(Msg,mbError,MB_OK);
981 Log(Msg);
982 end else begin
983 RegisterServer(Is64BitInstallMode,FileName,False);
984 end;
985 end;
986 end;
988 procedure RegisterPreviousData(PreviousDataKey:Integer);
990 Data:String;
991 begin
992 // Git Path options.
993 Data:='';
994 if RdbPath[GP_BashOnly].Checked then begin
995 Data:='BashOnly';
996 end else if RdbPath[GP_Cmd].Checked then begin
997 Data:='Cmd';
998 end else if RdbPath[GP_CmdTools].Checked then begin
999 Data:='CmdTools';
1000 end;
1001 SetPreviousData(PreviousDataKey,'Path Option',Data);
1003 // Git SSH options.
1004 Data:='';
1005 if (PuTTYPage=NIL) or RdbSSH[GS_OpenSSH].Checked then begin
1006 Data:='OpenSSH';
1007 end else if RdbSSH[GS_Plink].Checked then begin
1008 Data:='Plink';
1009 end;
1010 SetPreviousData(PreviousDataKey,'SSH Option',Data);
1012 // Line ending conversion options.
1013 Data:='';
1014 if RdbCRLF[GC_LFOnly].Checked then begin
1015 Data:='LFOnly';
1016 end else if RdbCRLF[GC_CRLFAlways].Checked then begin
1017 Data:='CRLFAlways';
1018 end else if RdbCRLF[GC_CRLFCommitAsIs].Checked then begin
1019 Data:='CRLFCommitAsIs';
1020 end;
1021 SetPreviousData(PreviousDataKey,'CRLF Option',Data);
1022 end;
1025 Uninstaller code
1028 function InitializeUninstall:Boolean;
1030 FileName,NewName,Msg:String;
1031 begin
1032 FileName:=ExpandConstant('{app}\bin\ssh-agent.exe');
1033 if FileExists(FileName) then begin
1034 // Create a temporary copy of the file we try to delete.
1035 NewName:=FileName+'.'+IntToStr(1000+Random(9000));
1036 Result:=FileCopy(FileName,NewName,True) and DeleteFile(FileName);
1038 if not Result then begin
1039 Msg:='Line {#emit __LINE__}: Please stop all ssh-agent processes and run uninstall again.';
1040 MsgBox(Msg,mbError,MB_OK);
1041 Log(Msg);
1043 // Clean-up the temporary copy (ignoring any errors).
1044 DeleteFile(NewName);
1045 end else begin
1046 // Clean-up the temporary copy (ignoring any errors).
1047 RenameFile(NewName,FileName);
1048 end;
1049 end else begin
1050 Result:=True;
1051 end;
1052 end;
1054 // PreUninstall
1056 // Even though the name of this function suggests otherwise most of the
1057 // code below is only executed right before the actual uninstallation.
1058 // This happens because of the if-guard right in the beginning of this
1059 // function.
1060 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
1062 AppDir,FileName,Msg:String;
1063 EnvPath,EnvHome,EnvSSH:TArrayOfString;
1064 i:Longint;
1065 begin
1066 if CurUninstallStep<>usUninstall then begin
1067 Exit;
1068 end;
1071 Modify the environment
1073 This must happen no later than usUninstall to make
1074 "ChangesEnvironment=yes" not happend before the change!
1077 AppDir:=ExpandConstant('{app}');
1078 FileName:=AppDir+'\setup.ini';
1080 // Delete the current user's GIT_SSH and SVN_SSH if we set it.
1081 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
1082 if (GetArrayLength(EnvSSH)=1) and
1083 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
1084 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
1085 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to GIT_SSH.';
1086 MsgBox(Msg,mbError,MB_OK);
1087 Log(Msg);
1088 // This is not a critical error, the user can probably fix it manually,
1089 // so we continue.
1090 end;
1091 end;
1093 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
1094 if (GetArrayLength(EnvSSH)=1) and
1095 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
1096 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
1097 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to SVN_SSH.';
1098 MsgBox(Msg,mbError,MB_OK);
1099 Log(Msg);
1100 // This is not a critical error, the user can probably fix it manually,
1101 // so we continue.
1102 end;
1103 end;
1105 // Get the current user's directories in PATH.
1106 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
1108 // Remove the installation directory from PATH in any case, even if it
1109 // was not added by the installer.
1110 for i:=0 to GetArrayLength(EnvPath)-1 do begin
1111 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
1112 EnvPath[i]:='';
1113 end;
1114 end;
1116 // Reset the current user's directories in PATH.
1117 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
1118 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to PATH.';
1119 MsgBox(Msg,mbError,MB_OK);
1120 Log(Msg);
1121 // This is not a critical error, the user can probably fix it manually,
1122 // so we continue.
1123 end;
1125 // Reset the current user's HOME if we modified it.
1126 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
1127 if (GetArrayLength(EnvHome)=1) and
1128 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
1129 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
1130 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
1131 MsgBox(Msg,mbError,MB_OK);
1132 Log(Msg);
1133 // This is not a critical error, the user can probably fix it manually,
1134 // so we continue.
1135 end;
1136 end;
1138 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
1139 Msg:='Line {#emit __LINE__}: Unable to delete file "'+FileName+'".';
1140 MsgBox(Msg,mbError,MB_OK);
1141 Log(Msg);
1142 // This is not a critical error, the user can probably fix it manually,
1143 // so we continue.
1144 end;
1147 Delete the Windows Explorer integrations
1150 DeleteContextMenuEntries;
1152 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
1153 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
1154 Msg:='Line {#emit __LINE__}: Unable to delete file "'+FileName+'". Please delete it manually after logging off and on again.';
1155 MsgBox(Msg,mbError,MB_OK);
1156 Log(Msg);
1157 end;
1158 end;