Installer: Always create the special "Git Bash.lnk" in the install directory
[msysgit/kirr.git] / share / WinGit / install.iss
blob907bffd717b2ddb36d2a9f0e97a426be03cf642c
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 InternalCompressLevel=max
9 OutputBaseFilename={#emit APP_NAME+'-'+APP_VERSION}
10 OutputDir=%OUTPUTDIR%
11 SolidCompression=yes
13 ; Installer-related
14 AllowNoIcons=yes
15 AppName={#emit APP_NAME}
16 AppPublisherURL={#emit APP_URL}
17 AppVersion={#emit APP_VERSION}
18 AppVerName={#emit APP_NAME+' '+APP_VERSION}
19 ChangesEnvironment=yes
20 DefaultDirName={pf}\{#emit APP_NAME}
21 DefaultGroupName={#emit APP_NAME}
22 DisableReadyPage=yes
23 InfoBeforeFile=gpl-2.0.rtf
24 PrivilegesRequired=none
25 UninstallDisplayIcon=etc\git.ico
27 ; Cosmetic
28 SetupIconFile=etc\git.ico
29 WizardImageBackColor=clWhite
30 WizardImageStretch=no
31 WizardImageFile=git.bmp
32 WizardSmallImageFile=gitsmall.bmp
34 [Tasks]
35 Name: quicklaunchicon; Description: Create a &Quick Launch icon; GroupDescription: Additional icons:; Flags: checkedonce
36 Name: desktopicon; Description: Create a &Desktop icon; GroupDescription: Additional icons:; Flags: checkedonce
37 Name: shellextension; Description: "Add ""Git Ba&sh Here"""; GroupDescription: Windows Explorer integration:; Flags: checkedonce
38 Name: guiextension; Description: "Add ""Git &GUI Here"""; GroupDescription: Windows Explorer integration:; Flags: checkedonce
39 Name: consolefont; Description: Use TrueType font (required for proper character encoding); GroupDescription: Console properties:; Flags: checkedonce
41 [Files]
42 Source: *; DestDir: {app}; Excludes: \*.bmp, gpl-2.0.rtf, \*.iss, \tmp.*, \bin\*install*; Flags: recursesubdirs replacesameversion
43 Source: ReleaseNotes.rtf; DestDir: {app}; Flags: isreadme replacesameversion
45 [Icons]
46 Name: {group}\Git GUI; Filename: {app}\bin\wish.exe; Parameters: """{app}\libexec\git-core\git-gui"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
47 Name: {group}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico
48 Name: {group}\Uninstall Git; Filename: {uninstallexe}
49 Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico; Tasks: quicklaunchicon
50 Name: {code:GetShellFolder|desktop}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir: %HOMEDRIVE%%HOMEPATH%; IconFilename: {app}\etc\git.ico; Tasks: desktopicon
52 ; 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.
53 Name: {app}\Git Bash; Filename: {syswow64}\cmd.exe; Parameters: "/c """"{app}\bin\sh.exe"" --login -i"""; IconFilename: {app}\etc\git.ico
55 [Messages]
56 BeveledLabel={#emit APP_URL}
57 SetupAppTitle={#emit APP_NAME} Setup
58 SetupWindowTitle={#emit APP_NAME} Setup
60 [Registry]
61 Root: HKCU; Subkey: Console; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Tasks: consolefont
62 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Tasks: consolefont
63 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Tasks: consolefont
64 Root: HKCU; Subkey: Console; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Tasks: consolefont
66 Root: HKCU; Subkey: Console\Git Bash; ValueType: string; ValueName: FaceName; ValueData: Lucida Console; Flags: createvalueifdoesntexist
67 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontFamily; ValueData: $00000036; Flags: createvalueifdoesntexist
68 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontSize; ValueData: $000e0000; Flags: createvalueifdoesntexist
69 Root: HKCU; Subkey: Console\Git Bash; ValueType: dword; ValueName: FontWeight; ValueData: $00000190; Flags: createvalueifdoesntexist
71 [UninstallDelete]
72 Type: files; Name: {app}\bin\git-*.exe
73 Type: files; Name: {app}\libexec\git-core\git-*.exe
74 Type: dirifempty; Name: {app}\home\{username}
75 Type: dirifempty; Name: {app}\home
77 [Code]
78 #include "helpers.inc.iss"
79 #include "putty.inc.iss"
81 function CreateHardLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
82 #ifdef UNICODE
83 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
84 #else
85 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
86 #endif
88 const
89 // Git Path options.
90 GP_BashOnly = 1;
91 GP_Cmd = 2;
92 GP_CmdTools = 3;
94 // Git SSH options.
95 GS_OpenSSH = 1;
96 GS_Plink = 2;
98 // Git line ending conversion options.
99 GC_LFOnly = 1;
100 GC_CRLFAlways = 2;
101 GC_CRLFCommitAsIs = 3;
104 // Wizard page and variables for the Path options.
105 PathPage:TWizardPage;
106 RdbPath:array[GP_BashOnly..GP_CmdTools] of TRadioButton;
108 // Wizard page and variables for the SSH options.
109 PuTTYPage:TWizardPage;
110 RdbSSH:array[GS_OpenSSH..GS_Plink] of TRadioButton;
111 EdtPlink:TEdit;
113 // Wizard page and variables for the line ending conversion options.
114 CRLFPage:TWizardPage;
115 RdbCRLF:array[GC_LFOnly..GC_CRLFCommitAsIs] of TRadioButton;
117 procedure BrowseForPuTTYFolder(Sender:TObject);
119 Path:String;
120 begin
121 Path:=ExtractFilePath(EdtPlink.Text);
122 BrowseForFolder('Please select the PuTTY folder:',Path,False);
123 if FileExists(Path+'\TortoisePlink.exe') then begin
124 EdtPlink.Text:=Path+'\TortoisePlink.exe';
125 RdbSSH[GS_Plink].Checked:=True;
126 end else if FileExists(Path+'\plink.exe') then begin
127 EdtPlink.Text:=Path+'\plink.exe';
128 RdbSSH[GS_Plink].Checked:=True;
129 end else begin
130 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError,MB_OK);
131 end;
132 end;
135 Installer code
138 procedure InitializeWizard;
140 PrevPageID:Integer;
141 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
142 LblOpenSSH,LblPlink:TLabel;
143 PuTTYSessions:TArrayOfString;
144 LblLFOnly,LblCRLFAlways,LblCRLFCommitAsIs:TLabel;
145 BtnPlink:TButton;
146 Data:String;
147 begin
148 PrevPageID:=wpSelectTasks;
151 * Create a custom page for modifying the environment.
154 PathPage:=CreateCustomPage(
155 PrevPageID,
156 'Adjusting your PATH environment',
157 'How would you like to use Git from the command line?'
159 PrevPageID:=PathPage.ID;
161 // 1st choice
162 RdbPath[GP_BashOnly]:=TRadioButton.Create(PathPage);
163 with RdbPath[GP_BashOnly] do begin
164 Parent:=PathPage.Surface;
165 Caption:='Use Git Bash only';
166 Left:=ScaleX(4);
167 Top:=ScaleY(8);
168 Width:=ScaleX(129);
169 Height:=ScaleY(17);
170 Font.Style:=[fsBold];
171 TabOrder:=0;
172 Checked:=True;
173 end;
174 LblGitBash:=TLabel.Create(PathPage);
175 with LblGitBash do begin
176 Parent:=PathPage.Surface;
177 Caption:=
178 'This is the most conservative choice if you are concerned about the stability' + #13 +
179 'of your system. Your PATH will not be modified.';
180 Left:=ScaleX(28);
181 Top:=ScaleY(32);
182 Width:=ScaleX(405);
183 Height:=ScaleY(26);
184 end;
186 // 2nd choice
187 RdbPath[GP_Cmd]:=TRadioButton.Create(PathPage);
188 with RdbPath[GP_Cmd] do begin
189 Parent:=PathPage.Surface;
190 Caption:='Run Git from the Windows Command Prompt';
191 Left:=ScaleX(4);
192 Top:=ScaleY(76);
193 Width:=ScaleX(281);
194 Height:=ScaleY(17);
195 Font.Style:=[fsBold];
196 TabOrder:=1;
197 end;
198 LblGitCmd:=TLabel.Create(PathPage);
199 with LblGitCmd do begin
200 Parent:=PathPage.Surface;
201 Caption:=
202 'This option is considered safe and no conflicts with other tools are known.' + #13 +
203 'Only Git will be added to your PATH. Use this option if you want to use Git' + #13 +
204 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
205 Left:=ScaleX(28);
206 Top:=ScaleY(100);
207 Width:=ScaleX(405);
208 Height:=ScaleY(39);
209 end;
211 // 3rd choice
212 RdbPath[GP_CmdTools]:=TRadioButton.Create(PathPage);
213 with RdbPath[GP_CmdTools] do begin
214 Parent:=PathPage.Surface;
215 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
216 Left:=ScaleX(4);
217 Top:=ScaleY(152);
218 Width:=ScaleX(405);
219 Height:=ScaleY(17);
220 Font.Style:=[fsBold];
221 TabOrder:=2;
222 end;
223 LblGitCmdTools:=TLabel.Create(PathPage);
224 with LblGitCmdTools do begin
225 Parent:=PathPage.Surface;
226 Caption:='Both Git and its accompanying Unix tools will be added to your PATH.';
227 Left:=ScaleX(28);
228 Top:=ScaleY(176);
229 Width:=ScaleX(405);
230 Height:=ScaleY(13);
231 end;
232 LblGitCmdToolsWarn:=TLabel.Create(PathPage);
233 with LblGitCmdToolsWarn do begin
234 Parent:=PathPage.Surface;
235 Caption:=
236 'Warning: This will override Windows tools like find.exe and' + #13 +
237 'sort.exe. Select this option only if you understand the implications.';
238 Left:=ScaleX(28);
239 Top:=ScaleY(192);
240 Width:=ScaleX(376);
241 Height:=ScaleY(26);
242 Font.Color:=255;
243 Font.Style:=[fsBold];
244 end;
246 // Restore the setting chosen during a previous install.
247 Data:=GetPreviousData('Path Option','BashOnly');
248 if Data='BashOnly' then begin
249 RdbPath[GP_BashOnly].Checked:=True;
250 end else if Data='Cmd' then begin
251 RdbPath[GP_Cmd].Checked:=True;
252 end else if Data='CmdTools' then begin
253 RdbPath[GP_CmdTools].Checked:=True;
254 end;
257 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
258 * if at least one PuTTY session is found in the Registry.
261 if RegGetSubkeyNames(HKEY_CURRENT_USER,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions) and (GetArrayLength(PuTTYSessions)>0) then begin
262 PuTTYPage:=CreateCustomPage(
263 PrevPageID,
264 'Choosing the SSH executable',
265 'Which Secure Shell client program would you like Git to use?'
267 PrevPageID:=PuTTYPage.ID;
269 // 1st choice
270 RdbSSH[GS_OpenSSH]:=TRadioButton.Create(PuTTYPage);
271 with RdbSSH[GS_OpenSSH] do begin
272 Parent:=PuTTYPage.Surface;
273 Caption:='Use OpenSSH';
274 Left:=ScaleX(4);
275 Top:=ScaleY(8);
276 Width:=ScaleX(129);
277 Height:=ScaleY(17);
278 Font.Style:=[fsBold];
279 TabOrder:=0;
280 Checked:=True;
281 end;
282 LblOpenSSH:=TLabel.Create(PuTTYPage);
283 with LblOpenSSH do begin
284 Parent:=PuTTYPage.Surface;
285 Caption:=
286 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #13 +
287 'environment variables will not be modified.';
288 Left:=ScaleX(28);
289 Top:=ScaleY(32);
290 Width:=ScaleX(324);
291 Height:=ScaleY(26);
292 end;
294 // 2nd choice
295 RdbSSH[GS_Plink]:=TRadioButton.Create(PuTTYPage);
296 with RdbSSH[GS_Plink] do begin
297 Parent:=PuTTYPage.Surface;
298 Caption:='Use (Tortoise)Plink';
299 Left:=ScaleX(4);
300 Top:=ScaleY(76);
301 Width:=ScaleX(281);
302 Height:=ScaleY(17);
303 Font.Style:=[fsBold];
304 TabOrder:=1;
305 end;
306 LblPlink:=TLabel.Create(PuTTYPage);
307 with LblPlink do begin
308 Parent:=PuTTYPage.Surface;
309 Caption:=
310 'PuTTY sessions were found in your Registry. You may specify the path' + #13 +
311 'to an existing copy of (Tortoise)Plink.exe from the TortoiseSVN/CVS' + #13 +
312 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #13 +
313 'variables will be adjusted to point to the following executable:';
314 Left:=ScaleX(28);
315 Top:=ScaleY(100);
316 Width:=ScaleX(340);
317 Height:=ScaleY(52);
318 end;
319 EdtPlink:=TEdit.Create(PuTTYPage);
320 with EdtPlink do begin
321 Parent:=PuTTYPage.Surface;
322 Text:=GetPuTTYLocation;
323 if not FileExists(Text) then begin
324 Text:='';
325 end;
326 Left:=ScaleX(28);
327 Top:=ScaleY(161);
328 Width:=ScaleX(316);
329 Height:=ScaleY(13);
330 end;
331 BtnPlink:=TButton.Create(PuTTYPage);
332 with BtnPlink do begin
333 Parent:=PuTTYPage.Surface;
334 Caption:='...';
335 OnClick:=@BrowseForPuTTYFolder;
336 Left:=ScaleX(348);
337 Top:=ScaleY(161);
338 Width:=ScaleX(21);
339 Height:=ScaleY(21);
340 end;
342 // Restore the setting chosen during a previous install.
343 Data:=GetPreviousData('SSH Option','OpenSSH');
344 if Data='OpenSSH' then begin
345 RdbSSH[GS_OpenSSH].Checked:=True;
346 end else if Data='Plink' then begin
347 RdbSSH[GS_Plink].Checked:=True;
348 end;
349 end else begin
350 PuTTYPage:=NIL;
351 end;
354 * Create a custom page for the core.autocrlf setting.
357 CRLFPage:=CreateCustomPage(
358 PrevPageID,
359 'Configuring the line ending conversions',
360 'How should Git treat line endings in text files?'
362 PrevPageID:=CRLFPage.ID;
364 // 1st choice
365 RdbCRLF[GC_CRLFAlways]:=TRadioButton.Create(CRLFPage);
366 with RdbCRLF[GC_CRLFAlways] do begin
367 Parent:=CRLFPage.Surface;
368 Caption:='Checkout Windows-style, commit Unix-style line endings';
369 Left:=ScaleX(4);
370 Top:=ScaleY(8);
371 Width:=ScaleX(340);
372 Height:=ScaleY(17);
373 Font.Style:=[fsBold];
374 TabOrder:=0;
375 Checked:=True;
376 end;
377 LblCRLFAlways:=TLabel.Create(CRLFPage);
378 with LblCRLFAlways do begin
379 Parent:=CRLFPage.Surface;
380 Caption:=
381 'Git will convert LF to CRLF when checking out text files. When committing' + #13 +
382 'text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
383 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
384 Left:=ScaleX(28);
385 Top:=ScaleY(32);
386 Width:=ScaleX(372);
387 Height:=ScaleY(47);
388 end;
390 // 2nd choice
391 RdbCRLF[GC_LFOnly]:=TRadioButton.Create(CRLFPage);
392 with RdbCRLF[GC_LFOnly] do begin
393 Parent:=CRLFPage.Surface;
394 Caption:='Checkout as-is, commit Unix-style line endings';
395 Left:=ScaleX(4);
396 Top:=ScaleY(80);
397 Width:=ScaleX(340);
398 Height:=ScaleY(17);
399 Font.Style:=[fsBold];
400 TabOrder:=1;
401 Checked:=False;
402 end;
403 LblLFOnly:=TLabel.Create(CRLFPage);
404 with LblLFOnly do begin
405 Parent:=CRLFPage.Surface;
406 Caption:=
407 'Git will not perform any conversion when checking out text files. When' + #13 +
408 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #13 +
409 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
410 Left:=ScaleX(28);
411 Top:=ScaleY(104);
412 Width:=ScaleX(372);
413 Height:=ScaleY(47);
414 end;
416 // 3rd choice
417 RdbCRLF[GC_CRLFCommitAsIs]:=TRadioButton.Create(CRLFPage);
418 with RdbCRLF[GC_CRLFCommitAsIs] do begin
419 Parent:=CRLFPage.Surface;
420 Caption:='Checkout as-is, commit as-is';
421 Left:=ScaleX(4);
422 Top:=ScaleY(152);
423 Width:=ScaleX(340);
424 Height:=ScaleY(17);
425 Font.Style:=[fsBold];
426 TabOrder:=2;
427 Checked:=False;
428 end;
429 LblCRLFCommitAsIs:=TLabel.Create(CRLFPage);
430 with LblCRLFCommitAsIs do begin
431 Parent:=CRLFPage.Surface;
432 Caption:=
433 'Git will not perform any conversions when checking out or committing' + #13 +
434 'text files. Choosing this option is not recommended for cross-platform' + #13 +
435 'projects ("core.autocrlf" is set to "false").';
436 Left:=ScaleX(28);
437 Top:=ScaleY(176);
438 Width:=ScaleX(372);
439 Height:=ScaleY(47);
440 end;
442 // Restore the setting chosen during a previous install.
443 Data:=GetPreviousData('CRLF Option','CRLFAlways');
444 if Data='LFOnly' then begin
445 RdbCRLF[GC_LFOnly].Checked:=True;
446 end else if Data='CRLFAlways' then begin
447 RdbCRLF[GC_CRLFAlways].Checked:=True;
448 end else if Data='CRLFCommitAsIs' then begin
449 RdbCRLF[GC_CRLFCommitAsIs].Checked:=True;
450 end;
451 end;
453 function NextButtonClick(CurPageID:Integer):Boolean;
454 begin
455 if (PuTTYPage=NIL) or (CurPageID<>PuTTYPage.ID) then begin
456 Result:=True;
457 Exit;
458 end;
460 Result:=RdbSSH[GS_OpenSSH].Checked or
461 (RdbSSH[GS_Plink].Checked and FileExists(EdtPlink.Text));
463 if not Result then begin
464 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError,MB_OK);
465 end;
466 end;
468 procedure CurStepChanged(CurStep:TSetupStep);
470 AppDir,FileName,Cmd,Msg:String;
471 BuiltIns,EnvPath,EnvHome,EnvSSH:TArrayOfString;
472 Count,i:Longint;
473 IsNTFS:Boolean;
474 FindRec:TFindRec;
475 RootKey:Integer;
476 begin
477 if CurStep<>ssPostInstall then begin
478 Exit;
479 end;
481 AppDir:=ExpandConstant('{app}');
484 Create the built-ins
487 // Load the built-ins from a text file.
488 FileName:=ExpandConstant('{app}\{#emit APP_BUILTINS}');
489 if LoadStringsFromFile(FileName,BuiltIns) then begin
490 // Check if we are running on NTFS.
491 IsNTFS:=False;
492 if SetNTFSCompression(AppDir+'\bin\git.exe',true) then begin
493 IsNTFS:=SetNTFSCompression(AppDir+'\bin\git.exe',false);
494 end;
496 Count:=GetArrayLength(BuiltIns)-1;
498 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
499 for i:=0 to Count do begin
500 FileName:=AppDir+'\bin\'+ChangeFileExt(ExtractFileName(BuiltIns[i]),'');
501 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
502 Log('Line {#emit __LINE__}: Unable to delete script "'+FileName+'", ignoring.');
503 end;
504 end;
506 // Map the built-ins to git.exe.
507 if IsNTFS then begin
508 Log('Line {#emit __LINE__}: Partition seems to be NTFS, trying to create built-in aliases as hard links.');
510 for i:=0 to Count do begin
511 FileName:=AppDir+'\'+BuiltIns[i];
513 // On non-NTFS partitions, create hard links.
514 if (FileExists(FileName) and (not DeleteFile(FileName))) or
515 (not CreateHardLink(FileName,AppDir+'\bin\git.exe',0)) then begin
516 Log('Line {#emit __LINE__}: Unable to create hard link "'+FileName+'", will try to copy files.');
517 IsNTFS:=False;
518 Break;
519 end;
520 end;
522 Log('Line {#emit __LINE__}: Successfully created built-in aliases as hard links.');
523 end;
525 // The fallback is to copy the files.
526 if not IsNTFS then begin
527 Log('Line {#emit __LINE__}: Trying to create built-in aliases as file copies.');
529 for i:=0 to Count do begin
530 FileName:=AppDir+'\'+BuiltIns[i];
532 // On non-NTFS partitions, copy simply the files (overwriting existing ones).
533 if not FileCopy(AppDir+'\bin\git.exe',FileName,false) then begin
534 Msg:='Line {#emit __LINE__}: Unable to create file copy "'+FileName+'".';
535 MsgBox(Msg,mbError,MB_OK);
536 Log(Msg);
537 // This is not a critical error, Git could basically be used without the
538 // aliases for built-ins, so we continue.
539 end;
540 end;
542 Log('Line {#emit __LINE__}: Successfully created built-in aliases as file copies.');
543 end;
545 // Delete any duplicate files in case we are updating from a non-libexec to a libexec directory layout.
546 if FindFirst(AppDir+'\libexec\git-core\*',FindRec) then begin
547 repeat
548 if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0 then begin
549 FileName:=AppDir+'\bin\'+FindRec.name;
550 if (Pos(FindRec.name,'git.exe')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
551 Log('Line {#emit __LINE__}: Unable to delete dupe "'+FileName+'", ignoring.');
552 end;
553 end;
554 until not FindNext(FindRec);
555 FindClose(FindRec);
556 end;
557 end else begin
558 Msg:='Line {#emit __LINE__}: Unable to read file "{#emit APP_BUILTINS}".';
559 MsgBox(Msg,mbError,MB_OK);
560 Log(Msg);
561 // This is not a critical error, Git could basically be used without the
562 // aliases for built-ins, so we continue.
563 end;
566 Adapt core.autocrlf
569 if RdbCRLF[GC_LFOnly].checked then begin
570 Cmd:='core.autocrlf input';
571 end else if RdbCRLF[GC_CRLFAlways].checked then begin
572 Cmd:='core.autocrlf true';
573 end else begin
574 Cmd:='core.autocrlf false';
575 end;
576 if not Exec(AppDir + '\bin\git.exe', 'config -f gitconfig ' + Cmd,
577 AppDir + '\etc', SW_HIDE, ewWaitUntilTerminated, i) then begin
578 Msg:='Unable to configure the line ending conversion: ' + Cmd;
579 MsgBox(Msg,mbError,MB_OK);
580 Log(Msg);
581 end;
584 Modify the environment
586 This must happen no later than ssPostInstall to make
587 "ChangesEnvironment=yes" not happend before the change!
590 FileName:=AppDir+'\setup.ini';
592 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
593 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
594 if (GetArrayLength(EnvSSH)=1) and
595 (CompareStr(EnvSSH[0],GetIniString('Environment','GIT_SSH','',FileName))=0) then begin
596 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
597 Msg:='Line {#emit __LINE__}: Unable to reset GIT_SSH prior to install.';
598 MsgBox(Msg,mbError,MB_OK);
599 Log(Msg);
600 // This is not a critical error, the user can probably fix it manually,
601 // so we continue.
602 end;
603 end;
605 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
606 if (GetArrayLength(EnvSSH)=1) and
607 (CompareStr(EnvSSH[0],GetIniString('Environment','SVN_SSH','',FileName))=0) then begin
608 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
609 Msg:='Line {#emit __LINE__}: Unable to reset SVN_SSH prior to install.';
610 MsgBox(Msg,mbError,MB_OK);
611 Log(Msg);
612 // This is not a critical error, the user can probably fix it manually,
613 // so we continue.
614 end;
615 end;
617 if (PuTTYPage<>NIL) and RdbSSH[GS_Plink].Checked then begin
618 SetArrayLength(EnvSSH,1);
619 EnvSSH[0]:=EdtPlink.Text;
621 // Set GIT_SSH as specified by the user.
622 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
623 Msg:='Line {#emit __LINE__}: Unable to set the GIT_SSH environment variable.';
624 MsgBox(Msg,mbError,MB_OK);
625 Log(Msg);
626 // This is not a critical error, the user can probably fix it manually,
627 // so we continue.
628 end;
630 // Mark that we have changed GIT_SSH by writing its value to a file.
631 if not SetIniString('Environment','GIT_SSH',EnvSSH[0],FileName) then begin
632 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
633 MsgBox(Msg,mbError,MB_OK);
634 Log(Msg);
635 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
636 // so we continue.
637 end;
639 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
640 StringChangeEx(EnvSSH[0],'\','\\',True);
641 EnvSSH[0]:=AddQuotes(EnvSSH[0]);
643 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,EnvSSH) then begin
644 Msg:='Line {#emit __LINE__}: Unable to set the SVN_SSH environment variable.';
645 MsgBox(Msg,mbError,MB_OK);
646 Log(Msg);
647 // This is not a critical error, the user can probably fix it manually,
648 // so we continue.
649 end;
651 // Mark that we have changed SVN_SSH by writing its value to a file.
652 if not SetIniString('Environment','SVN_SSH',EnvSSH[0],FileName) then begin
653 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
654 MsgBox(Msg,mbError,MB_OK);
655 Log(Msg);
656 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
657 // so we continue.
658 end;
659 end;
661 // Get the current user's directories in PATH.
662 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
664 // First, remove the installation directory from PATH in any case.
665 for i:=0 to GetArrayLength(EnvPath)-1 do begin
666 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
667 EnvPath[i]:='';
668 end;
669 end;
671 // Delete HOME if a previous installation modified it.
672 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
673 if (GetArrayLength(EnvHome)=1) and
674 (CompareStr(EnvHome[0],GetIniString('Environment','HOME','',FileName))=0) then begin
675 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
676 Msg:='Line {#emit __LINE__}: Unable to reset HOME prior to install.';
677 MsgBox(Msg,mbError,MB_OK);
678 Log(Msg);
679 // This is not a critical error, the user can probably fix it manually,
680 // so we continue.
681 end;
682 end;
684 // Modify the PATH variable as requested by the user.
685 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
686 i:=GetArrayLength(EnvPath);
687 SetArrayLength(EnvPath,i+1);
689 // List \cmd before \bin so \cmd has higher priority and programs in
690 // there will be called in favor of those in \bin.
691 EnvPath[i]:=ExpandConstant('{app}\cmd');
693 if RdbPath[GP_CmdTools].Checked then begin
694 SetArrayLength(EnvPath,i+2);
695 EnvPath[i+1]:=ExpandConstant('{app}\bin');
697 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
698 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
699 i:=GetArrayLength(EnvHome);
700 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
701 SetArrayLength(EnvHome,1);
702 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
703 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,EnvHome) then begin
704 Msg:='Line {#emit __LINE__}: Unable to set the HOME environment variable.';
705 MsgBox(Msg,mbError,MB_OK);
706 Log(Msg);
707 // This is not a critical error, the user can probably fix it manually,
708 // so we continue.
709 end;
711 // Mark that we have changed HOME.
712 if not SetIniString('Environment','HOME',EnvHome[0],FileName) then begin
713 Msg:='Line {#emit __LINE__}: Unable to write to file "'+FileName+'".';
714 MsgBox(Msg,mbError,MB_OK);
715 Log(Msg);
716 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
717 // so we continue.
718 end;
719 end;
720 end;
721 end;
723 // Set the current user's PATH directories.
724 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
725 Msg:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
726 MsgBox(Msg,mbError,MB_OK);
727 Log(Msg);
728 // This is not a critical error, the user can probably fix it manually,
729 // so we continue.
730 end;
733 Create the Windows Explorer shell extensions
736 if IsAdminLoggedOn then begin
737 RootKey:=HKEY_LOCAL_MACHINE;
738 end else begin
739 RootKey:=HKEY_CURRENT_USER;
740 end;
742 if IsTaskSelected('shellextension') then begin
743 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
744 (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','','wscript "'+AppDir+'\Git Bash.vbs" "%1"')) then begin
745 Msg:='Line {#emit __LINE__}: Unable to create "Git Bash Here" shell extension.';
746 MsgBox(Msg,mbError,MB_OK);
747 Log(Msg);
748 // This is not a critical error, the user can probably fix it manually,
749 // so we continue.
750 end;
751 end;
753 if IsTaskSelected('guiextension') then begin
754 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
755 (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
756 Msg:='Line {#emit __LINE__}: Unable to create "Git GUI Here" shell extension.';
757 MsgBox(Msg,mbError,MB_OK);
758 Log(Msg);
759 // This is not a critical error, the user can probably fix it manually,
760 // so we continue.
761 end;
762 end;
763 end;
765 procedure RegisterPreviousData(PreviousDataKey:Integer);
767 Data:String;
768 begin
769 // Git Path options.
770 Data:='';
771 if RdbPath[GP_BashOnly].Checked then begin
772 Data:='BashOnly';
773 end else if RdbPath[GP_Cmd].Checked then begin
774 Data:='Cmd';
775 end else if RdbPath[GP_CmdTools].Checked then begin
776 Data:='CmdTools';
777 end;
778 SetPreviousData(PreviousDataKey,'Path Option',Data);
780 // Git SSH options.
781 Data:='';
782 if (PuTTYPage=NIL) or RdbSSH[GS_OpenSSH].Checked then begin
783 Data:='OpenSSH';
784 end else if RdbSSH[GS_Plink].Checked then begin
785 Data:='Plink';
786 end;
787 SetPreviousData(PreviousDataKey,'SSH Option',Data);
789 // Line ending conversion options.
790 Data:='';
791 if RdbCRLF[GC_LFOnly].Checked then begin
792 Data:='LFOnly';
793 end else if RdbCRLF[GC_CRLFAlways].Checked then begin
794 Data:='CRLFAlways';
795 end else if RdbCRLF[GC_CRLFCommitAsIs].Checked then begin
796 Data:='CRLFCommitAsIs';
797 end;
798 SetPreviousData(PreviousDataKey,'CRLF Option',Data);
799 end;
802 Uninstaller code
805 function InitializeUninstall:Boolean;
807 FileName,NewName,Msg:String;
808 begin
809 FileName:=ExpandConstant('{app}\bin\ssh-agent.exe');
810 if FileExists(FileName) then begin
811 // Create a temporary copy of the file we try to delete.
812 NewName:=FileName+'.'+IntToStr(1000+Random(9000));
813 Result:=FileCopy(FileName,NewName,True) and DeleteFile(FileName);
815 if not Result then begin
816 Msg:='Line {#emit __LINE__}: Please stop all ssh-agent processes and run uninstall again.';
817 MsgBox(Msg,mbError,MB_OK);
818 Log(Msg);
820 // Clean-up the temporary copy (ignoring any errors).
821 DeleteFile(NewName);
822 end else begin
823 // Clean-up the temporary copy (ignoring any errors).
824 RenameFile(NewName,FileName);
825 end;
826 end else begin
827 Result:=True;
828 end;
829 end;
831 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
833 AppDir,Command,Msg:String;
834 EnvPath,EnvHome,EnvSSH:TArrayOfString;
835 i:Longint;
836 RootKey:Integer;
837 begin
838 if CurUninstallStep<>usUninstall then begin
839 Exit;
840 end;
843 Modify the environment
845 This must happen no later than usUninstall to make
846 "ChangesEnvironment=yes" not happend before the change!
849 AppDir:=ExpandConstant('{app}');
850 Command:=AppDir+'\setup.ini';
852 // Delete the current user's GIT_SSH and SVN_SSH if we set it.
853 EnvSSH:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn);
854 if (GetArrayLength(EnvSSH)=1) and
855 (CompareStr(EnvSSH[0],GetIniString('Environment','GIT_SSH','',Command))=0) then begin
856 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn,True,[]) then begin
857 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to GIT_SSH.';
858 MsgBox(Msg,mbError,MB_OK);
859 Log(Msg);
860 // This is not a critical error, the user can probably fix it manually,
861 // so we continue.
862 end;
863 end;
865 EnvSSH:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn);
866 if (GetArrayLength(EnvSSH)=1) and
867 (CompareStr(EnvSSH[0],GetIniString('Environment','SVN_SSH','',Command))=0) then begin
868 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn,True,[]) then begin
869 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to SVN_SSH.';
870 MsgBox(Msg,mbError,MB_OK);
871 Log(Msg);
872 // This is not a critical error, the user can probably fix it manually,
873 // so we continue.
874 end;
875 end;
877 // Get the current user's directories in PATH.
878 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
880 // Remove the installation directory from PATH in any case, even if it
881 // was not added by the installer.
882 for i:=0 to GetArrayLength(EnvPath)-1 do begin
883 if Pos(AppDir+'\',EnvPath[i]+'\')=1 then begin
884 EnvPath[i]:='';
885 end;
886 end;
888 // Reset the current user's directories in PATH.
889 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
890 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to PATH.';
891 MsgBox(Msg,mbError,MB_OK);
892 Log(Msg);
893 // This is not a critical error, the user can probably fix it manually,
894 // so we continue.
895 end;
897 // Reset the current user's HOME if we modified it.
898 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
899 if (GetArrayLength(EnvHome)=1) and
900 (CompareStr(EnvHome[0],GetIniString('Environment','HOME','',Command))=0) then begin
901 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
902 Msg:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
903 MsgBox(Msg,mbError,MB_OK);
904 Log(Msg);
905 // This is not a critical error, the user can probably fix it manually,
906 // so we continue.
907 end;
908 end;
910 if FileExists(Command) and (not DeleteFile(Command)) then begin
911 Msg:='Line {#emit __LINE__}: Unable to delete file "'+Command+'".';
912 MsgBox(Msg,mbError,MB_OK);
913 Log(Msg);
914 // This is not a critical error, the user can probably fix it manually,
915 // so we continue.
916 end;
919 Delete the Windows Explorer shell extensions
922 if IsAdminLoggedOn then begin
923 RootKey:=HKEY_LOCAL_MACHINE;
924 end else begin
925 RootKey:=HKEY_CURRENT_USER;
926 end;
928 Command:='';
929 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command);
930 if Pos(AppDir,Command)>0 then begin
931 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
932 Msg:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
933 MsgBox(Msg,mbError,MB_OK);
934 Log(Msg);
935 // This is not a critical error, the user can probably fix it manually,
936 // so we continue.
937 end;
938 end;
940 Command:='';
941 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command);
942 if Pos(AppDir,Command)>0 then begin
943 if not RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
944 Msg:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
945 MsgBox(Msg,mbError,MB_OK);
946 Log(Msg);
947 // This is not a critical error, the user can probably fix it manually,
948 // so we continue.
949 end;
950 end;
951 end;