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