Wine: avoid problems with inherited LS_COLORS
[msysgit.git] / share / WinGit / install.iss
blob7743921d33d9b48213277966129ee720cf9c820d
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 #define COMP_CONSOLE_FONT 'Use a TrueType font in all console windows (not only for Git Bash)'
8 [Setup]
9 ; Compiler-related
10 Compression=lzma2/ultra
11 LZMAUseSeparateProcess=yes
12 OutputBaseFilename={#APP_NAME+'-'+APP_VERSION}
13 OutputDir={#GetEnv('USERPROFILE')}
14 SolidCompression=yes
16 ; Uncomment the line below to be able to compile the script from within the IDE.
17 ;SourceDir={#GetEnv('TEMP')}\WinGit
19 ; Installer-related
20 AllowNoIcons=yes
21 AppName={#APP_NAME}
22 AppPublisherURL={#APP_URL}
23 AppVersion={#APP_VERSION}
24 ChangesEnvironment=yes
25 DefaultDirName={pf}\{#APP_NAME}
26 DefaultGroupName={#APP_NAME}
27 DisableReadyPage=yes
28 InfoBeforeFile=gpl-2.0.rtf
29 PrivilegesRequired=none
30 UninstallDisplayIcon=etc\git.ico
32 ; Cosmetic
33 SetupIconFile=etc\git.ico
34 WizardImageBackColor=clWhite
35 WizardImageStretch=no
36 WizardImageFile=git.bmp
37 WizardSmallImageFile=gitsmall.bmp
39 [Types]
40 ; Define a dummy type to avoid getting the default ones.
41 Name: custom; Description: Custom installation; Flags: iscustom
43 [Components]
44 Name: icons; Description: Additional icons; Types: custom
45 Name: icons\quicklaunch; Description: In the Quick Launch; Types: custom
46 Name: icons\desktop; Description: On the Desktop; Types: custom
47 Name: ext; Description: Windows Explorer integration; Types: custom
48 Name: ext\reg; Description: Context menu entries; Flags: exclusive; Types: custom
49 Name: ext\reg\shellhere; Description: Git Bash Here; Types: custom
50 Name: ext\reg\guihere; Description: Git GUI Here; Types: custom
51 Name: ext\cheetah; Description: git-cheetah shell extension (32-bit only); Flags: exclusive; Types: custom
52 Name: assoc; Description: Associate .git* configuration files with the default text editor; Types: custom
53 Name: consolefont; Description: {#COMP_CONSOLE_FONT}; Types: custom
55 [Files]
56 ; Install files that might be in use during setup under a different name.
57 Source: git-cheetah\git_shell_ext.dll; DestDir: {app}\git-cheetah; DestName: git_shell_ext.dll.new; Flags: replacesameversion
59 Source: *; DestDir: {app}; Excludes: \*.bmp, gpl-2.0.rtf, \*.iss, \tmp.*, \bin\*install*, \git-cheetah\git_shell_ext.dll; Flags: recursesubdirs replacesameversion
60 Source: ReleaseNotes.rtf; DestDir: {app}; Flags: isreadme replacesameversion
62 [Icons]
63 Name: {group}\Git GUI; Filename: {app}\bin\wish.exe; Parameters: """{app}\libexec\git-core\git-gui"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
64 Name: {group}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
66 [Messages]
67 BeveledLabel={#APP_URL}
68 SetupAppTitle={#APP_NAME} Setup
69 SetupWindowTitle={#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; Flags: uninsclearvalue; 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 uninsdeletevalue uninsdeletekeyifempty
79 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
80 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
81 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
83 ; Note that we write the Registry values below either to HKLM or to HKCU depending on whether the user running the installer
84 ; is a member of the local Administrators group or not (see the "Check" argument).
86 ; File associations for configuration files that may be contained in a repository (so this does not include ".gitconfig").
87 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
88 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
89 Root: HKLM; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
90 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
91 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
92 Root: HKCU; Subkey: Software\Classes\.gitattributes; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
94 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
95 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
96 Root: HKLM; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
97 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
98 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
99 Root: HKCU; Subkey: Software\Classes\.gitignore; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
101 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
102 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
103 Root: HKLM; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: IsAdminLoggedOn; Components: assoc
104 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueData: txtfile; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
105 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
106 Root: HKCU; Subkey: Software\Classes\.gitmodules; ValueType: string; ValueName: PerceivedType; ValueData: text; Flags: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check: not IsAdminLoggedOn; Components: assoc
108 [UninstallDelete]
109 ; Delete the built-ins.
110 Type: files; Name: {app}\bin\git-*.exe
111 Type: files; Name: {app}\libexec\git-core\git-*.exe
112 Type: files; Name: {app}\libexec\git-core\git.exe
114 ; Delete any (temporary) git-cheetah files.
115 Type: files; Name: {app}\git-cheetah\*.*
117 ; Delete any manually created shortcuts.
118 Type: files; Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash.lnk
119 Type: files; Name: {code:GetShellFolder|desktop}\Git Bash.lnk
120 Type: files; Name: {app}\Git Bash.lnk
122 ; Delete a home directory inside the msysGit directory.
123 Type: dirifempty; Name: {app}\home\{username}
124 Type: dirifempty; Name: {app}\home
126 [Code]
127 #include "helpers.inc.iss"
128 #include "putty.inc.iss"
129 #include "modules.inc.iss"
131 function CreateHardLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
132 #ifdef UNICODE
133 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
134 #else
135 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
136 #endif
138 function CreateSymbolicLink(lpSymlinkFileName,lpTargetFileName:String;dwFlags:DWORD):Boolean;
139 #ifdef UNICODE
140 external 'CreateSymbolicLinkW@Kernel32.dll stdcall delayload setuponly';
141 #else
142 external 'CreateSymbolicLinkA@Kernel32.dll stdcall delayload setuponly';
143 #endif
145 const
146 // Git Path options.
147 GP_BashOnly = 1;
148 GP_Cmd = 2;
149 GP_CmdTools = 3;
151 // Git SSH options.
152 GS_OpenSSH = 1;
153 GS_Plink = 2;
155 // Git line ending conversion options.
156 GC_LFOnly = 1;
157 GC_CRLFAlways = 2;
158 GC_CRLFCommitAsIs = 3;
161 // Wizard page and variables for the Path options.
162 PathPage:TWizardPage;
163 RdbPath:array[GP_BashOnly..GP_CmdTools] of TRadioButton;
165 // Wizard page and variables for the SSH options.
166 PuTTYPage:TWizardPage;
167 RdbSSH:array[GS_OpenSSH..GS_Plink] of TRadioButton;
168 EdtPlink:TEdit;
170 // Wizard page and variables for the line ending conversion options.
171 CRLFPage:TWizardPage;
172 RdbCRLF:array[GC_LFOnly..GC_CRLFCommitAsIs] of TRadioButton;
174 // Wizard page and variables for the processes page.
175 Processes:ProcessList;
176 ProcessesPage:TWizardPage;
177 ProcessesListBox:TListBox;
178 ProcessesRefresh,ContinueButton:TButton;
180 procedure BrowseForPuTTYFolder(Sender:TObject);
182 Path:String;
183 begin
184 Path:=ExtractFilePath(EdtPlink.Text);
185 BrowseForFolder('Please select the PuTTY folder:',Path,False);
186 if FileExists(Path+'\TortoisePlink.exe') then begin
187 EdtPlink.Text:=Path+'\TortoisePlink.exe';
188 RdbSSH[GS_Plink].Checked:=True;
189 end else if FileExists(Path+'\plink.exe') then begin
190 EdtPlink.Text:=Path+'\plink.exe';
191 RdbSSH[GS_Plink].Checked:=True;
192 end else begin
193 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError,MB_OK);
194 end;
195 end;
197 procedure DeleteContextMenuEntries;
199 AppDir,Command,Msg:String;
200 RootKey:Integer;
201 begin
202 AppDir:=ExpandConstant('{app}');
204 if IsAdminLoggedOn then begin
205 RootKey:=HKEY_LOCAL_MACHINE;
206 end else begin
207 RootKey:=HKEY_CURRENT_USER;
208 end;
210 Command:='';
211 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command);
212 if Pos(AppDir,Command)>0 then begin
213 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
214 Msg:='Line {#__LINE__}: Unable to remove "Git Bash Here" shell extension.';
215 MsgBox(Msg,mbError,MB_OK);
216 Log(Msg);
217 // This is not a critical error, the user can probably fix it manually,
218 // so we continue.
219 end;
220 end;
222 Command:='';
223 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command);
224 if Pos(AppDir,Command)>0 then begin
225 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
226 Msg:='Line {#__LINE__}: Unable to remove "Git GUI Here" shell extension.';
227 MsgBox(Msg,mbError,MB_OK);
228 Log(Msg);
229 // This is not a critical error, the user can probably fix it manually,
230 // so we continue.
231 end;
232 end;
233 end;
235 procedure RefreshProcessList(Sender:TObject);
237 Modules:TArrayOfString;
238 ProcsCloseRequired,ProcsCloseRestart:ProcessList;
239 Found:Boolean;
240 i:Longint;
241 Caption:String;
242 begin
243 SetArrayLength(Modules,2);
244 Modules[0]:=ExpandConstant('{app}\bin\msys-1.0.dll');
245 Modules[1]:=ExpandConstant('{app}\bin\tcl85.dll');
246 Found:=FindProcessesUsingModules(Modules,ProcsCloseRequired);
248 Found:=FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),ProcsCloseRestart) or Found;
250 // Misuse the "Restartable" flag to indicate which processes are required
251 // to be closed before setup can continue, and which just should be closed
252 // in order to make changes take effect immediately.
253 SetArrayLength(Processes,GetArrayLength(ProcsCloseRequired)+GetArrayLength(ProcsCloseRestart));
254 for i:=0 to GetArrayLength(ProcsCloseRequired)-1 do begin
255 Processes[i]:=ProcsCloseRequired[i];
256 Processes[i].Restartable:=False;
257 end;
258 for i:=0 to GetArrayLength(ProcsCloseRestart)-1 do begin
259 Processes[GetArrayLength(ProcsCloseRequired)+i]:=ProcsCloseRestart[i];
260 Processes[GetArrayLength(ProcsCloseRequired)+i].Restartable:=True;
261 end;
263 ProcessesListBox.Items.Clear;
264 if (Sender=NIL) or Found then begin
265 for i:=0 to GetArrayLength(Processes)-1 do begin
266 Caption:=Processes[i].Name+' (PID '+IntToStr(Processes[i].ID);
267 if not Processes[i].Restartable then begin
268 Caption:=Caption+', closing is required';
269 end;
270 Caption:=Caption+')';
271 ProcessesListBox.Items.Append(Caption);
272 end;
273 end;
275 if ContinueButton<>NIL then begin
276 ContinueButton.Enabled:=(GetArrayLength(ProcsCloseRequired)=0);
277 end;
278 end;
281 Installer code
284 procedure InitializeWizard;
286 i,PrevPageID:Integer;
287 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
288 LblOpenSSH,LblPlink:TLabel;
289 PuTTYSessions:TArrayOfString;
290 LblLFOnly,LblCRLFAlways,LblCRLFCommitAsIs:TLabel;
291 BtnPlink:TButton;
292 Data:String;
293 begin
294 // Until we have a 64-bit version of git-cheetah, disable it on 64-bit Windows.
295 if isWin64 then begin
296 for i:=0 to WizardForm.ComponentsList.Items.Count-1 do begin
297 Data:=LowerCase(WizardForm.ComponentsList.ItemCaption[i]);
298 if Pos('context',Data)>0 then begin
299 // Select the Registry-based context menu entries.
300 WizardForm.ComponentsList.Checked[i]:=True;
301 end else if Pos('cheetah',Data)>0 then begin
302 // Disable the git-cheetah shell extension.
303 WizardForm.ComponentsList.ItemEnabled[i]:=False;
304 end;
305 end;
306 end;
308 PrevPageID:=wpSelectProgramGroup;
311 * Create a custom page for modifying the environment.
314 PathPage:=CreateCustomPage(
315 PrevPageID,
316 'Adjusting your PATH environment',
317 'How would you like to use Git from the command line?'
319 PrevPageID:=PathPage.ID;
321 // 1st choice
322 RdbPath[GP_BashOnly]:=TRadioButton.Create(PathPage);
323 with RdbPath[GP_BashOnly] do begin
324 Parent:=PathPage.Surface;
325 Caption:='Use Git Bash only';
326 Left:=ScaleX(4);
327 Top:=ScaleY(8);
328 Width:=ScaleX(129);
329 Height:=ScaleY(17);
330 Font.Style:=[fsBold];
331 TabOrder:=0;
332 Checked:=True;
333 end;
334 LblGitBash:=TLabel.Create(PathPage);
335 with LblGitBash do begin
336 Parent:=PathPage.Surface;
337 Caption:=
338 'This is the most conservative choice if you are concerned about the stability' + #13 +
339 'of your system. Your PATH will not be modified.';
340 Left:=ScaleX(28);
341 Top:=ScaleY(32);
342 Width:=ScaleX(405);
343 Height:=ScaleY(26);
344 end;
346 // 2nd choice
347 RdbPath[GP_Cmd]:=TRadioButton.Create(PathPage);
348 with RdbPath[GP_Cmd] do begin
349 Parent:=PathPage.Surface;
350 Caption:='Run Git from the Windows Command Prompt';
351 Left:=ScaleX(4);
352 Top:=ScaleY(76);
353 Width:=ScaleX(281);
354 Height:=ScaleY(17);
355 Font.Style:=[fsBold];
356 TabOrder:=1;
357 end;
358 LblGitCmd:=TLabel.Create(PathPage);
359 with LblGitCmd do begin
360 Parent:=PathPage.Surface;
361 Caption:=
362 'This option is considered safe and no conflicts with other tools are known.' + #13 +
363 'Only Git will be added to your PATH. Use this option if you want to use Git' + #13 +
364 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
365 Left:=ScaleX(28);
366 Top:=ScaleY(100);
367 Width:=ScaleX(405);
368 Height:=ScaleY(39);
369 end;
371 // 3rd choice
372 RdbPath[GP_CmdTools]:=TRadioButton.Create(PathPage);
373 with RdbPath[GP_CmdTools] do begin
374 Parent:=PathPage.Surface;
375 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
376 Left:=ScaleX(4);
377 Top:=ScaleY(152);
378 Width:=ScaleX(405);
379 Height:=ScaleY(17);
380 Font.Style:=[fsBold];
381 TabOrder:=2;
382 end;
383 LblGitCmdTools:=TLabel.Create(PathPage);
384 with LblGitCmdTools do begin
385 Parent:=PathPage.Surface;
386 Caption:='Both Git and its accompanying Unix tools will be added to your PATH.';
387 Left:=ScaleX(28);
388 Top:=ScaleY(176);
389 Width:=ScaleX(405);
390 Height:=ScaleY(13);
391 end;
392 LblGitCmdToolsWarn:=TLabel.Create(PathPage);
393 with LblGitCmdToolsWarn do begin
394 Parent:=PathPage.Surface;
395 Caption:=
396 'Warning: This will override Windows tools like find.exe and' + #13 +
397 'sort.exe. Select this option only if you understand the implications.';
398 Left:=ScaleX(28);
399 Top:=ScaleY(192);
400 Width:=ScaleX(376);
401 Height:=ScaleY(26);
402 Font.Color:=255;
403 Font.Style:=[fsBold];
404 end;
406 // Restore the setting chosen during a previous install.
407 Data:=GetPreviousData('Path Option','BashOnly');
408 if Data='BashOnly' then begin
409 RdbPath[GP_BashOnly].Checked:=True;
410 end else if Data='Cmd' then begin
411 RdbPath[GP_Cmd].Checked:=True;
412 end else if Data='CmdTools' then begin
413 RdbPath[GP_CmdTools].Checked:=True;
414 end;
417 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
418 * if at least one PuTTY session is found in the Registry.
421 if RegGetSubkeyNames(HKEY_CURRENT_USER,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions) and (GetArrayLength(PuTTYSessions)>0) then begin
422 PuTTYPage:=CreateCustomPage(
423 PrevPageID,
424 'Choosing the SSH executable',
425 'Which Secure Shell client program would you like Git to use?'
427 PrevPageID:=PuTTYPage.ID;
429 // 1st choice
430 RdbSSH[GS_OpenSSH]:=TRadioButton.Create(PuTTYPage);
431 with RdbSSH[GS_OpenSSH] do begin
432 Parent:=PuTTYPage.Surface;
433 Caption:='Use OpenSSH';
434 Left:=ScaleX(4);
435 Top:=ScaleY(8);
436 Width:=ScaleX(129);
437 Height:=ScaleY(17);
438 Font.Style:=[fsBold];
439 TabOrder:=0;
440 Checked:=True;
441 end;
442 LblOpenSSH:=TLabel.Create(PuTTYPage);
443 with LblOpenSSH do begin
444 Parent:=PuTTYPage.Surface;
445 Caption:=
446 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #13 +
447 'environment variables will not be modified.';
448 Left:=ScaleX(28);
449 Top:=ScaleY(32);
450 Width:=ScaleX(324);
451 Height:=ScaleY(26);
452 end;
454 // 2nd choice
455 RdbSSH[GS_Plink]:=TRadioButton.Create(PuTTYPage);
456 with RdbSSH[GS_Plink] do begin
457 Parent:=PuTTYPage.Surface;
458 Caption:='Use (Tortoise)Plink';
459 Left:=ScaleX(4);
460 Top:=ScaleY(76);
461 Width:=ScaleX(281);
462 Height:=ScaleY(17);
463 Font.Style:=[fsBold];
464 TabOrder:=1;
465 end;
466 LblPlink:=TLabel.Create(PuTTYPage);
467 with LblPlink do begin
468 Parent:=PuTTYPage.Surface;
469 Caption:=
470 'PuTTY sessions were found in your Registry. You may specify the path' + #13 +
471 'to an existing copy of (Tortoise)Plink.exe from the TortoiseSVN/CVS' + #13 +
472 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #13 +
473 'variables will be adjusted to point to the following executable:';
474 Left:=ScaleX(28);
475 Top:=ScaleY(100);
476 Width:=ScaleX(340);
477 Height:=ScaleY(52);
478 end;
479 EdtPlink:=TEdit.Create(PuTTYPage);
480 with EdtPlink do begin
481 Parent:=PuTTYPage.Surface;
482 Text:=GetPuTTYLocation;
483 if not FileExists(Text) then begin
484 Text:='';
485 end;
486 Left:=ScaleX(28);
487 Top:=ScaleY(161);
488 Width:=ScaleX(316);
489 Height:=ScaleY(13);
490 end;
491 BtnPlink:=TButton.Create(PuTTYPage);
492 with BtnPlink do begin
493 Parent:=PuTTYPage.Surface;
494 Caption:='...';
495 OnClick:=@BrowseForPuTTYFolder;
496 Left:=ScaleX(348);
497 Top:=ScaleY(161);
498 Width:=ScaleX(21);
499 Height:=ScaleY(21);
500 end;
502 // Restore the setting chosen during a previous install.
503 Data:=GetPreviousData('SSH Option','OpenSSH');
504 if Data='OpenSSH' then begin
505 RdbSSH[GS_OpenSSH].Checked:=True;
506 end else if Data='Plink' then begin
507 RdbSSH[GS_Plink].Checked:=True;
508 end;
509 end else begin
510 PuTTYPage:=NIL;
511 end;
514 * Create a custom page for the core.autocrlf setting.
517 CRLFPage:=CreateCustomPage(
518 PrevPageID,
519 'Configuring the line ending conversions',
520 'How should Git treat line endings in text files?'
522 PrevPageID:=CRLFPage.ID;
524 // 1st choice
525 RdbCRLF[GC_CRLFAlways]:=TRadioButton.Create(CRLFPage);
526 with RdbCRLF[GC_CRLFAlways] do begin
527 Parent:=CRLFPage.Surface;
528 Caption:='Checkout Windows-style, commit Unix-style line endings';
529 Left:=ScaleX(4);
530 Top:=ScaleY(8);
531 Width:=ScaleX(340);
532 Height:=ScaleY(17);
533 Font.Style:=[fsBold];
534 TabOrder:=0;
535 Checked:=True;
536 end;
537 LblCRLFAlways:=TLabel.Create(CRLFPage);
538 with LblCRLFAlways do begin
539 Parent:=CRLFPage.Surface;
540 Caption:=
541 'Git will convert LF to CRLF when checking out text files. When committing' + #13 +
542 'text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
543 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
544 Left:=ScaleX(28);
545 Top:=ScaleY(32);
546 Width:=ScaleX(372);
547 Height:=ScaleY(47);
548 end;
550 // 2nd choice
551 RdbCRLF[GC_LFOnly]:=TRadioButton.Create(CRLFPage);
552 with RdbCRLF[GC_LFOnly] do begin
553 Parent:=CRLFPage.Surface;
554 Caption:='Checkout as-is, commit Unix-style line endings';
555 Left:=ScaleX(4);
556 Top:=ScaleY(80);
557 Width:=ScaleX(340);
558 Height:=ScaleY(17);
559 Font.Style:=[fsBold];
560 TabOrder:=1;
561 Checked:=False;
562 end;
563 LblLFOnly:=TLabel.Create(CRLFPage);
564 with LblLFOnly do begin
565 Parent:=CRLFPage.Surface;
566 Caption:=
567 'Git will not perform any conversion when checking out text files. When' + #13 +
568 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
569 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
570 Left:=ScaleX(28);
571 Top:=ScaleY(104);
572 Width:=ScaleX(372);
573 Height:=ScaleY(47);
574 end;
576 // 3rd choice
577 RdbCRLF[GC_CRLFCommitAsIs]:=TRadioButton.Create(CRLFPage);
578 with RdbCRLF[GC_CRLFCommitAsIs] do begin
579 Parent:=CRLFPage.Surface;
580 Caption:='Checkout as-is, commit as-is';
581 Left:=ScaleX(4);
582 Top:=ScaleY(152);
583 Width:=ScaleX(340);
584 Height:=ScaleY(17);
585 Font.Style:=[fsBold];
586 TabOrder:=2;
587 Checked:=False;
588 end;
589 LblCRLFCommitAsIs:=TLabel.Create(CRLFPage);
590 with LblCRLFCommitAsIs do begin
591 Parent:=CRLFPage.Surface;
592 Caption:=
593 'Git will not perform any conversions when checking out or committing' + #13 +
594 'text files. Choosing this option is not recommended for cross-platform' + #13 +
595 'projects ("core.autocrlf" is set to "false").';
596 Left:=ScaleX(28);
597 Top:=ScaleY(176);
598 Width:=ScaleX(372);
599 Height:=ScaleY(47);
600 end;
602 // Restore the setting chosen during a previous install.
603 Data:=GetPreviousData('CRLF Option','CRLFAlways');
604 if Data='LFOnly' then begin
605 RdbCRLF[GC_LFOnly].Checked:=True;
606 end else if Data='CRLFAlways' then begin
607 RdbCRLF[GC_CRLFAlways].Checked:=True;
608 end else if Data='CRLFCommitAsIs' then begin
609 RdbCRLF[GC_CRLFCommitAsIs].Checked:=True;
610 end;
613 * Create a custom page for finding the processes that lock a module.
616 ProcessesPage:=CreateCustomPage(
617 wpPreparing,
618 'Replacing in-use files',
619 'The following applications use files that need to be replaced, please close them.'
622 ProcessesListBox:=TListBox.Create(ProcessesPage);
623 with ProcessesListBox do begin
624 Parent:=ProcessesPage.Surface;
625 Width:=ProcessesPage.SurfaceWidth;
626 Height:=ProcessesPage.SurfaceHeight-ScaleY(8);
627 end;
629 ProcessesRefresh:=TNewButton.Create(WizardForm);
630 with ProcessesRefresh do begin
631 Parent:=WizardForm;
632 Width:=WizardForm.NextButton.Width;
633 Height:=WizardForm.NextButton.Height;
634 Top:=WizardForm.NextButton.Top;
635 Left:=WizardForm.ClientWidth-WizardForm.NextButton.Left-WizardForm.NextButton.Width;
636 Caption:='&Refresh';
637 OnClick:=@RefreshProcessList;
638 end;
640 // This button is only used by the uninstaller.
641 ContinueButton:=NIL;
643 // Initially hide the Refresh button, show it when the process page becomes current.
644 ProcessesRefresh.Hide;
645 end;
647 function ShouldSkipPage(PageID:Integer):Boolean;
648 begin
649 if (ProcessesPage<>NIL) and (PageID=ProcessesPage.ID) then begin
650 // This page is only reached forward (by pressing "Next", never by pressing "Back").
651 RefreshProcessList(NIL);
652 Result:=(GetArrayLength(Processes)=0);
653 end else begin
654 Result:=False;
655 end;
656 end;
658 procedure CurPageChanged(CurPageID:Integer);
660 i:Integer;
661 begin
662 // Uncheck the console font option by default.
663 if CurPageID=wpSelectComponents then begin
664 for i:=0 to WizardForm.ComponentsList.Items.Count-1 do begin
665 if WizardForm.ComponentsList.ItemCaption[i]='{#COMP_CONSOLE_FONT}' then begin
666 WizardForm.ComponentsList.Checked[i]:=False;
667 Break;
668 end;
669 end;
670 end;
672 // Show the "Refresh" button only on the processes page.
673 if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
674 ProcessesRefresh.Show;
675 end else begin
676 ProcessesRefresh.Hide;
677 end;
678 end;
680 function NextButtonClick(CurPageID:Integer):Boolean;
682 i:Integer;
683 begin
684 Result:=True;
686 if (PuTTYPage<>NIL) and (CurPageID=PuTTYPage.ID) then begin
687 Result:=RdbSSH[GS_OpenSSH].Checked or
688 (RdbSSH[GS_Plink].Checked and FileExists(EdtPlink.Text));
689 if not Result then begin
690 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError,MB_OK);
691 end;
692 end else if (ProcessesPage<>NIL) and (CurPageID=ProcessesPage.ID) then begin
693 // It would have been nicer to just disable the "Next" button, but the
694 // WizardForm exports the button just read-only.
695 for i:=0 to GetArrayLength(Processes)-1 do begin
696 if not Processes[i].Restartable then begin
697 MsgBox('Setup cannot continue until you close at least those applications in the list that are marked as "closing is required".',mbCriticalError,MB_OK);
698 Result:=False;
699 Exit;
700 end;
701 end;
703 Result:=(GetArrayLength(Processes)=0);
705 if not Result then begin
706 Result:=(MsgBox(
707 'If you continue without closing the listed applications, you will need to log off and on again before changes take effect.' + #13 + #13 +
708 'Are you sure you want to continue anyway?',
709 mbConfirmation,
710 MB_YESNO
711 )=IDYES);
712 end;
713 end;
714 end;
716 // AfterInstall
718 // Even though the name of this procedure suggests otherwise most of the
719 // code below is only executed once after the regular installation code
720 // is finished. This happens because of the if-guard right in the
721 // beginning of this procedure.
722 procedure CurStepChanged(CurStep:TSetupStep);
724 AppDir,FileName,TempName,Cmd,Msg:String;
725 BuiltIns,EnvPath,EnvHome,EnvSSH:TArrayOfString;
726 Count,i:Longint;
727 LinkCreated:Boolean;
728 FindRec:TFindRec;
729 RootKey:Integer;
730 begin
731 if CurStep<>ssPostInstall then begin
732 Exit;
733 end;
735 AppDir:=ExpandConstant('{app}');
738 Create the built-ins
741 // Load the built-ins from a text file.
742 FileName:=ExpandConstant('{app}\{#APP_BUILTINS}');
743 if LoadStringsFromFile(FileName,BuiltIns) then begin
744 Count:=GetArrayLength(BuiltIns)-1;
746 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
747 for i:=0 to Count do begin
748 FileName:=AppDir+'\bin\'+ChangeFileExt(ExtractFileName(BuiltIns[i]),'');
749 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
750 Log('Line {#__LINE__}: Unable to delete script "'+FileName+'", ignoring.');
751 end;
752 end;
754 // Create built-ins as aliases for git.exe.
755 for i:=0 to Count do begin
756 FileName:=AppDir+'\'+BuiltIns[i];
758 // Delete any existing built-in.
759 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
760 Log('Line {#__LINE__}: Unable to delete existing built-in "'+FileName+'", skipping.');
761 continue;
762 end;
765 // This will throw an exception on pre-WinVista systems.
766 LinkCreated:=CreateSymbolicLink(FileName,AppDir+'\bin\git.exe',0);
767 except
768 LinkCreated:=False;
769 Log('Line {#__LINE__}: Creating symbolic link "'+FileName+'" failed, will try a hard link.');
770 end;
772 if not LinkCreated then begin
774 // This will throw an exception on pre-Win2k systems.
775 LinkCreated:=CreateHardLink(FileName,AppDir+'\bin\git.exe',0);
776 except
777 LinkCreated:=False;
778 Log('Line {#__LINE__}: Creating hardlink "'+FileName+'" failed, will try a copy.');
779 end;
780 end;
782 if not LinkCreated then begin
783 if not FileCopy(AppDir+'\bin\git.exe',FileName,False) then begin
784 Log('Line {#__LINE__}: Creating copy "'+FileName+'" failed, giving up.');
785 // This is not a critical error, Git could basically be used without the
786 // aliases for built-ins, so we continue.
787 end;
788 end;
789 end;
791 // Delete any duplicate files in case we are updating from a non-libexec to a libexec directory layout.
792 if FindFirst(AppDir+'\libexec\git-core\*',FindRec) then begin
793 repeat
794 if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0 then begin
795 FileName:=AppDir+'\bin\'+FindRec.name;
796 if (Pos(FindRec.name,'git.exe')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
797 Log('Line {#__LINE__}: Unable to delete dupe "'+FileName+'", ignoring.');
798 end;
799 end;
800 until not FindNext(FindRec);
801 FindClose(FindRec);
802 end;
803 end else begin
804 Msg:='Line {#__LINE__}: Unable to read file "{#APP_BUILTINS}".';
805 MsgBox(Msg,mbError,MB_OK);
806 Log(Msg);
807 // This is not a critical error, Git could basically be used without the
808 // aliases for built-ins, so we continue.
809 end;
812 Adapt core.autocrlf
815 if RdbCRLF[GC_LFOnly].checked then begin
816 Cmd:='core.autocrlf input';
817 end else if RdbCRLF[GC_CRLFAlways].checked then begin
818 Cmd:='core.autocrlf true';
819 end else begin
820 Cmd:='core.autocrlf false';
821 end;
822 if not Exec(AppDir + '\bin\git.exe', 'config -f gitconfig ' + Cmd,
823 AppDir + '\etc', SW_HIDE, ewWaitUntilTerminated, i) then begin
824 Msg:='Unable to configure the line ending conversion: ' + Cmd;
825 MsgBox(Msg,mbError,MB_OK);
826 Log(Msg);
827 // This is not a critical error, the user can probably fix it manually,
828 // so we continue.
829 end;
832 Modify the environment
834 This must happen no later than ssPostInstall to make
835 "ChangesEnvironment=yes" not happend before the change!
838 FileName:=AppDir+'\setup.ini';
840 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
841 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
842 if (GetArrayLength(EnvSSH)=1) and
843 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
844 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
845 Msg:='Line {#__LINE__}: Unable to reset GIT_SSH prior to install.';
846 MsgBox(Msg,mbError,MB_OK);
847 Log(Msg);
848 // This is not a critical error, the user can probably fix it manually,
849 // so we continue.
850 end;
851 end;
853 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
854 if (GetArrayLength(EnvSSH)=1) and
855 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
856 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
857 Msg:='Line {#__LINE__}: Unable to reset SVN_SSH prior to install.';
858 MsgBox(Msg,mbError,MB_OK);
859 Log(Msg);
860 // This is not a critical error, the user can probably fix it manually,
861 // so we continue.
862 end;
863 end;
865 if (PuTTYPage<>NIL) and RdbSSH[GS_Plink].Checked then begin
866 SetArrayLength(EnvSSH,1);
867 EnvSSH[0]:=EdtPlink.Text;
869 // Set GIT_SSH as specified by the user.
870 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
871 Msg:='Line {#__LINE__}: Unable to set the GIT_SSH environment variable.';
872 MsgBox(Msg,mbError,MB_OK);
873 Log(Msg);
874 // This is not a critical error, the user can probably fix it manually,
875 // so we continue.
876 end;
878 // Mark that we have changed GIT_SSH by writing its value to a file.
879 if not SetIniString('Environment','GIT_SSH',EnvSSH[0],FileName) then begin
880 Msg:='Line {#__LINE__}: Unable to write to file "'+FileName+'".';
881 MsgBox(Msg,mbError,MB_OK);
882 Log(Msg);
883 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
884 // so we continue.
885 end;
887 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
888 StringChangeEx(EnvSSH[0],'\','\\',True);
889 EnvSSH[0]:=AddQuotes(EnvSSH[0]);
891 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
892 Msg:='Line {#__LINE__}: Unable to set the SVN_SSH environment variable.';
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;
899 // Mark that we have changed SVN_SSH by writing its value to a file.
900 if not SetIniString('Environment','SVN_SSH',EnvSSH[0],FileName) then begin
901 Msg:='Line {#__LINE__}: Unable to write to file "'+FileName+'".';
902 MsgBox(Msg,mbError,MB_OK);
903 Log(Msg);
904 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
905 // so we continue.
906 end;
907 end;
909 // Get the current user's directories in PATH.
910 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
912 // First, remove the installation directory from PATH in any case.
913 for i:=0 to GetArrayLength(EnvPath)-1 do begin
914 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
915 EnvPath[i]:='';
916 end;
917 end;
919 // Delete HOME if a previous installation modified it.
920 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
921 if (GetArrayLength(EnvHome)=1) and
922 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
923 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
924 Msg:='Line {#__LINE__}: Unable to reset HOME prior to install.';
925 MsgBox(Msg,mbError,MB_OK);
926 Log(Msg);
927 // This is not a critical error, the user can probably fix it manually,
928 // so we continue.
929 end;
930 end;
932 // Modify the PATH variable as requested by the user.
933 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
934 i:=GetArrayLength(EnvPath);
935 SetArrayLength(EnvPath,i+1);
937 // List \cmd before \bin so \cmd has higher priority and programs in
938 // there will be called in favor of those in \bin.
939 EnvPath[i]:=AppDir+'\cmd';
941 if RdbPath[GP_CmdTools].Checked then begin
942 SetArrayLength(EnvPath,i+2);
943 EnvPath[i+1]:=AppDir+'\bin';
945 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
946 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
947 i:=GetArrayLength(EnvHome);
948 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
949 SetArrayLength(EnvHome,1);
950 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
951 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,EnvHome) then begin
952 Msg:='Line {#__LINE__}: Unable to set the HOME environment variable.';
953 MsgBox(Msg,mbError,MB_OK);
954 Log(Msg);
955 // This is not a critical error, the user can probably fix it manually,
956 // so we continue.
957 end;
959 // Mark that we have changed HOME.
960 if not SetIniString('Environment','HOME',EnvHome[0],FileName) then begin
961 Msg:='Line {#__LINE__}: Unable to write to file "'+FileName+'".';
962 MsgBox(Msg,mbError,MB_OK);
963 Log(Msg);
964 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
965 // so we continue.
966 end;
967 end;
968 end;
969 end;
971 // Set the current user's PATH directories.
972 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
973 Msg:='Line {#__LINE__}: Unable to set the PATH environment variable.';
974 MsgBox(Msg,mbError,MB_OK);
975 Log(Msg);
976 // This is not a critical error, the user can probably fix it manually,
977 // so we continue.
978 end;
981 Create shortcuts that need to be created regardless of the "Don't create a Start Menu folder" toggle
984 Cmd:=ExpandConstant('{syswow64}\cmd.exe');
985 TempName:='/c ""'+AppDir+'\bin\sh.exe" --login -i"';
986 FileName:=AppDir+'\etc\git.ico';
988 if IsComponentSelected('icons\quicklaunch') then begin
989 CreateShellLink(
990 ExpandConstant('{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash.lnk')
991 , 'Git Bash'
992 , Cmd
993 , TempName
994 , '%HOMEDRIVE%%HOMEPATH%'
995 , FileName
997 , SW_SHOWNORMAL
999 end;
1000 if IsComponentSelected('icons\desktop') then begin
1001 CreateShellLink(
1002 GetShellFolder('desktop')+'\Git Bash.lnk'
1003 , 'Git Bash'
1004 , Cmd
1005 , TempName
1006 , '%HOMEDRIVE%%HOMEPATH%'
1007 , FileName
1009 , SW_SHOWNORMAL
1011 end;
1013 // Create a special shortcut that does not set a working directory (Note: Since Inno Setup 5.3.11,
1014 // passing an empty WorkingDir gets replaced with {sys}, so use '.' instead).
1015 // This shortcut is used by "Git Bash.vbs", which in turn is run by the "Git Bash Here" shell extension.
1016 CreateShellLink(
1017 AppDir+'\Git Bash.lnk'
1018 , 'Git Bash'
1019 , Cmd
1020 , TempName
1021 , '.'
1022 , FileName
1024 , SW_SHOWNORMAL
1028 Create the Windows Explorer integrations
1031 if IsAdminLoggedOn then begin
1032 RootKey:=HKEY_LOCAL_MACHINE;
1033 end else begin
1034 RootKey:=HKEY_CURRENT_USER;
1035 end;
1037 if IsComponentSelected('ext\reg\shellhere') then begin
1038 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
1039 (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','','wscript "'+AppDir+'\Git Bash.vbs" "%1"')) then begin
1040 Msg:='Line {#__LINE__}: Unable to create "Git Bash Here" shell extension.';
1041 MsgBox(Msg,mbError,MB_OK);
1042 Log(Msg);
1043 // This is not a critical error, the user can probably fix it manually,
1044 // so we continue.
1045 end;
1046 end;
1048 if IsComponentSelected('ext\reg\guihere') then begin
1049 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
1050 (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
1051 Msg:='Line {#__LINE__}: Unable to create "Git GUI Here" shell extension.';
1052 MsgBox(Msg,mbError,MB_OK);
1053 Log(Msg);
1054 // This is not a critical error, the user can probably fix it manually,
1055 // so we continue.
1056 end;
1057 end;
1059 // It is either the Registry-based context menu entries, or the shell extension.
1060 if IsComponentSelected('ext\cheetah') then begin
1061 DeleteContextMenuEntries;
1063 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
1064 if not ReplaceInUseFile(FileName,FileName+'.new',True) then begin
1065 Log('Line {#__LINE__}: Replacing file "'+FileName+'" failed.');
1066 end;
1067 end;
1068 end;
1070 procedure RegisterPreviousData(PreviousDataKey:Integer);
1072 Data:String;
1073 begin
1074 // Git Path options.
1075 Data:='';
1076 if RdbPath[GP_BashOnly].Checked then begin
1077 Data:='BashOnly';
1078 end else if RdbPath[GP_Cmd].Checked then begin
1079 Data:='Cmd';
1080 end else if RdbPath[GP_CmdTools].Checked then begin
1081 Data:='CmdTools';
1082 end;
1083 SetPreviousData(PreviousDataKey,'Path Option',Data);
1085 // Git SSH options.
1086 Data:='';
1087 if (PuTTYPage=NIL) or RdbSSH[GS_OpenSSH].Checked then begin
1088 Data:='OpenSSH';
1089 end else if RdbSSH[GS_Plink].Checked then begin
1090 Data:='Plink';
1091 end;
1092 SetPreviousData(PreviousDataKey,'SSH Option',Data);
1094 // Line ending conversion options.
1095 Data:='';
1096 if RdbCRLF[GC_LFOnly].Checked then begin
1097 Data:='LFOnly';
1098 end else if RdbCRLF[GC_CRLFAlways].Checked then begin
1099 Data:='CRLFAlways';
1100 end else if RdbCRLF[GC_CRLFCommitAsIs].Checked then begin
1101 Data:='CRLFCommitAsIs';
1102 end;
1103 SetPreviousData(PreviousDataKey,'CRLF Option',Data);
1104 end;
1107 Uninstaller code
1110 function InitializeUninstall:Boolean;
1112 Form:TSetupForm;
1113 Info:TLabel;
1114 ExitButton,RefreshButton:TButton;
1115 begin
1116 Result:=True;
1118 Form:=CreateCustomForm;
1120 Form.Caption:='Git Uninstall: Removing in-use files';
1121 Form.ClientWidth:=ScaleX(500);
1122 Form.ClientHeight:=ScaleY(256);
1123 Form.Center;
1125 Info:=TLabel.Create(Form);
1126 with Info do begin
1127 Parent:=Form;
1128 Left:=ScaleX(11);
1129 Top:=ScaleY(11);
1130 AutoSize:=True;
1131 Caption:='The following applications use files that need to be removed, please close them.';
1132 end;
1134 ContinueButton:=TButton.Create(Form);
1135 with ContinueButton do begin
1136 Parent:=Form;
1137 Left:=Form.ClientWidth-ScaleX(75+10);
1138 Top:=Form.ClientHeight-ScaleY(23+10);
1139 Width:=ScaleX(75);
1140 Height:=ScaleY(23);
1141 Caption:='Continue';
1142 ModalResult:=mrOk;
1143 end;
1145 ExitButton:=TButton.Create(Form);
1146 with ExitButton do begin
1147 Parent:=Form;
1148 Left:=ContinueButton.Left-ScaleX(75+6);
1149 Top:=ContinueButton.Top;
1150 Width:=ScaleX(75);
1151 Height:=ScaleY(23);
1152 Caption:='Exit';
1153 ModalResult:=mrCancel;
1154 Cancel:=True;
1155 end;
1157 RefreshButton:=TButton.Create(Form);
1158 with RefreshButton do begin
1159 Parent:=Form;
1160 Left:=ScaleX(10);
1161 Top:=ExitButton.Top;
1162 Width:=ScaleX(75);
1163 Height:=ScaleY(23);
1164 Caption:='Refresh';
1165 OnClick:=@RefreshProcessList;
1166 end;
1168 ProcessesListBox:=TListBox.Create(Form);
1169 with ProcessesListBox do begin
1170 Parent:=Form;
1171 Left:=ScaleX(11);
1172 Top:=Info.Top+Info.Height+11;
1173 Width:=Form.ClientWidth-ScaleX(11*2);
1174 Height:=ContinueButton.Top-ScaleY(11*4);
1175 end;
1177 Form.ActiveControl:=ContinueButton;
1179 RefreshProcessList(NIL);
1180 if GetArrayLength(Processes)>0 then begin
1181 // Now that these dialogs are going to be shown, we should probably
1182 // disable the "Are you sure to remove Git?" confirmation dialog, but
1183 // unfortunately that is not possible with Inno Setup currently.
1184 Result:=(Form.ShowModal()=mrOk);
1186 // Note: The number of processes might have changed during a refresh.
1187 if Result and (GetArrayLength(Processes)>0) then begin
1188 Result:=(MsgBox(
1189 'If you continue without closing the listed applications, you will need to log off and on again to remove some files manually.' + #13 + #13 +
1190 'Are you sure you want to continue anyway?',
1191 mbConfirmation,
1192 MB_YESNO
1193 )=IDYES);
1194 end;
1195 end;
1196 finally
1197 Form.free;
1198 end;
1199 end;
1201 // PreUninstall
1203 // Even though the name of this function suggests otherwise most of the
1204 // code below is only executed right before the actual uninstallation.
1205 // This happens because of the if-guard right in the beginning of this
1206 // function.
1207 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
1209 AppDir,FileName,Msg:String;
1210 EnvPath,EnvHome,EnvSSH:TArrayOfString;
1211 i:Longint;
1212 begin
1213 if CurUninstallStep<>usUninstall then begin
1214 Exit;
1215 end;
1217 // Reset the console font (the FontType is reset in the Registry section).
1218 if IsComponentInstalled('consolefont') then begin
1219 if MsgBox('Do you want to revert the TrueType font setting for all console windows?',mbConfirmation,MB_YESNO)=IDYES then begin
1220 RegWriteDWordValue(HKEY_CURRENT_USER,'Console','FontFamily',0);
1221 RegWriteDWordValue(HKEY_CURRENT_USER,'Console','FontSize',0);
1222 RegWriteDWordValue(HKEY_CURRENT_USER,'Console','FontWeight',0);
1223 end;
1224 end;
1227 Modify the environment
1229 This must happen no later than usUninstall to make
1230 "ChangesEnvironment=yes" not happend before the change!
1233 AppDir:=ExpandConstant('{app}');
1234 FileName:=AppDir+'\setup.ini';
1236 // Delete the current user's GIT_SSH and SVN_SSH if we set it.
1237 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
1238 if (GetArrayLength(EnvSSH)=1) and
1239 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
1240 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
1241 Msg:='Line {#__LINE__}: Unable to revert any possible changes to GIT_SSH.';
1242 MsgBox(Msg,mbError,MB_OK);
1243 Log(Msg);
1244 // This is not a critical error, the user can probably fix it manually,
1245 // so we continue.
1246 end;
1247 end;
1249 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
1250 if (GetArrayLength(EnvSSH)=1) and
1251 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
1252 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
1253 Msg:='Line {#__LINE__}: Unable to revert any possible changes to SVN_SSH.';
1254 MsgBox(Msg,mbError,MB_OK);
1255 Log(Msg);
1256 // This is not a critical error, the user can probably fix it manually,
1257 // so we continue.
1258 end;
1259 end;
1261 // Get the current user's directories in PATH.
1262 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
1264 // Remove the installation directory from PATH in any case, even if it
1265 // was not added by the installer.
1266 for i:=0 to GetArrayLength(EnvPath)-1 do begin
1267 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
1268 EnvPath[i]:='';
1269 end;
1270 end;
1272 // Reset the current user's directories in PATH.
1273 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
1274 Msg:='Line {#__LINE__}: Unable to revert any possible changes to PATH.';
1275 MsgBox(Msg,mbError,MB_OK);
1276 Log(Msg);
1277 // This is not a critical error, the user can probably fix it manually,
1278 // so we continue.
1279 end;
1281 // Reset the current user's HOME if we modified it.
1282 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
1283 if (GetArrayLength(EnvHome)=1) and
1284 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment','HOME','',FileName))=0) then begin
1285 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
1286 Msg:='Line {#__LINE__}: Unable to revert any possible changes to HOME.';
1287 MsgBox(Msg,mbError,MB_OK);
1288 Log(Msg);
1289 // This is not a critical error, the user can probably fix it manually,
1290 // so we continue.
1291 end;
1292 end;
1294 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
1295 Msg:='Line {#__LINE__}: Unable to delete file "'+FileName+'".';
1296 MsgBox(Msg,mbError,MB_OK);
1297 Log(Msg);
1298 // This is not a critical error, the user can probably fix it manually,
1299 // so we continue.
1300 end;
1303 Delete the Windows Explorer integrations
1306 DeleteContextMenuEntries;
1308 FileName:=AppDir+'\git-cheetah\git_shell_ext.dll';
1309 if FileExists(FileName) then begin
1310 if not UnregisterServer(Is64BitInstallMode,FileName,False) then begin
1311 Msg:='Line {#__LINE__}: Unable to unregister file "'+FileName+'". Please do it manually by running "regsvr32 /u '+ExtractFileName(FileName)+'".';
1312 MsgBox(Msg,mbError,MB_OK);
1313 Log(Msg);
1314 end;
1316 if not DeleteFile(FileName) then begin
1317 Msg:='Line {#__LINE__}: Unable to delete file "'+FileName+'". Please do it manually after logging off and on again.';
1318 MsgBox(Msg,mbError,MB_OK);
1319 Log(Msg);
1320 end;
1321 end;
1322 end;