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