2 #define APP_VERSION
'%APPVERSION%'
3 #define APP_URL
'http://code.google.com/p/msysgit/'
4 #define APP_BUILTINS
'etc\fileList-builtins.txt'
8 InternalCompressLevel
=max
9 OutputBaseFilename
={#emit APP_NAME+'-'+APP_VERSION}
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}
23 InfoBeforeFile
=gpl
-2.0.rtf
24 PrivilegesRequired
=none
25 UninstallDisplayIcon
=etc\git
.ico
28 SetupIconFile
=etc\git
.ico
29 WizardImageBackColor
=clWhite
31 WizardImageFile
=git
.bmp
32 WizardSmallImageFile
=gitsmall
.bmp
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
41 Source
: *; DestDir
: {app}; Excludes
: \
*.bmp
, gpl
-2.0.rtf
, \install
.*, \tmp
.*, \bin\
*install
*; Flags
: recursesubdirs replacesameversion
42 Source
: ReleaseNotes
.rtf
; DestDir
: {app}; Flags
: isreadme replacesameversion
45 Name
: {group}\Git GUI
; Filename
: {app}\bin\wish
.exe
; Parameters
: """{app}\libexec\git-core\git-gui"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
46 Name
: {group}\Git Bash
; Filename
: {syswow64}\cmd
.exe
; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
47 Name
: {group}\Uninstall Git
; Filename
: {uninstallexe}
48 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
49 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 BeveledLabel
={#emit APP_URL}
53 SetupAppTitle
={#emit APP_NAME} Setup
54 SetupWindowTitle
={#emit APP_NAME} Setup
57 Type: files; Name
: {app}\bin\git
-*.exe
58 Type: files; Name
: {app}\libexec\git
-core\git
-*.exe
59 Type: dirifempty; Name
: {app}\home\
{username}
60 Type: dirifempty; Name
: {app}\home
67 function GetShellFolder(Param
:string):string;
69 if IsAdminLoggedOn
then begin
70 Param
:='{common'+Param
+'}';
72 Param
:='{user'+Param
+'}';
74 Result
:=ExpandConstant(Param
);
77 function CreateHardLink(lpFileName
,lpExistingFileName
:string;lpSecurityAttributes
:Integer):Boolean;
78 external 'CreateHardLinkA@Kernel32.dll';
80 function GetEnvStrings(VarName
:string;AllUsers
:Boolean):TArrayOfString
;
88 // See http
://www
.jrsoftware
.org
/isfaq
.php#env
89 if AllUsers
then begin
90 // We ignore errors here
. The resulting
array of strings will be empty
.
91 RegQueryStringValue(HKEY_LOCAL_MACHINE
,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName
,Path
);
93 // We ignore errors here
. The resulting
array of strings will be empty
.
94 RegQueryStringValue(HKEY_CURRENT_USER
,'Environment',VarName
,Path
);
97 // Make sure we have at least one semicolon
.
100 // Split the directories
in PATH into an
array of strings
.
102 SetArrayLength(Result
,0);
106 SetArrayLength(Result
,i
+1);
108 Result
[i
]:=Copy(Path
,1,p
-1);
111 Path
:=Copy(Path
,p
+1,Length(Path
));
116 function SetEnvStrings(VarName
:string;AllUsers
,DeleteIfEmpty
:Boolean;DirStrings
:TArrayOfString
):Boolean;
121 // Merge all non
-empty directory strings into a PATH variable
.
123 for i
:=0 to GetArrayLength(DirStrings
)-1 do begin
124 if Length(DirStrings
[i
])>0 then begin
125 if Length(Path
)>0 then begin
126 Path
:=Path
+';'+DirStrings
[i
];
133 // See http
://www
.jrsoftware
.org
/isfaq
.php#env
134 if AllUsers
then begin
135 KeyName
:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
136 if DeleteIfEmpty
and (Length(Path
)=0) then begin
137 Result
:=(not RegValueExists(HKEY_LOCAL_MACHINE
,KeyName
,VarName
)) or
138 RegDeleteValue(HKEY_LOCAL_MACHINE
,KeyName
,VarName
);
140 Result
:=RegWriteStringValue(HKEY_LOCAL_MACHINE
,KeyName
,VarName
,Path
);
143 KeyName
:='Environment';
144 if DeleteIfEmpty
and (Length(Path
)=0) then begin
145 Result
:=(not RegValueExists(HKEY_CURRENT_USER
,KeyName
,VarName
)) or
146 RegDeleteValue(HKEY_CURRENT_USER
,KeyName
,VarName
);
148 Result
:=RegWriteStringValue(HKEY_CURRENT_USER
,KeyName
,VarName
,Path
);
154 TortoiseSVNInstallKey
='SOFTWARE\TortoiseSVN';
155 TortoiseCVSUninstallKey
='SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\TortoiseCVS_is1';
156 PuTTYUninstallKey
='SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PuTTY_is1';
157 PuTTYPrivateKeyAssoc
='PuTTYPrivateKey\shell\open\command';
159 function GetPuTTYLocation
:string;
161 // Prefer TortoisePlink over vanilla Plink
for its GUI dialog
to accept host keys
.
162 if (IsWin64
and RegQueryStringValue(HKEY_LOCAL_MACHINE_64
,TortoiseSVNInstallKey
,'Directory',Result
)) or
163 RegQueryStringValue(HKEY_LOCAL_MACHINE_32
,TortoiseSVNInstallKey
,'Directory',Result
) then begin
164 // C
:\
Program Files\TortoiseSVN\
165 Result
:=Result
+'bin\';
166 // C:\Program Files\TortoiseSVN\bin\
168 if not (IsWin64 and RegQueryStringValue(HKEY_LOCAL_MACHINE_64,TortoiseCVSUninstallKey,'InstallLocation
',Result)) then begin
169 RegQueryStringValue(HKEY_LOCAL_MACHINE_32,TortoiseCVSUninstallKey,'InstallLocation
',Result);
171 // C:\Program Files\TortoiseCVS\
174 if DirExists(Result) then begin
175 Result:=Result+'TortoisePlink
.exe
'
179 if not RegQueryStringValue(HKEY_LOCAL_MACHINE,PuTTYUninstallKey,'InstallLocation
',Result) then begin
180 if RegQueryStringValue(HKEY_CLASSES_ROOT,PuTTYPrivateKeyAssoc,'',Result) then begin
181 // "C:\Program Files\PuTTY\pageant.exe" "%1"
182 Result:=RemoveQuotes(Result);
183 // C:\Program Files\PuTTY\pageant.exe" "%1
184 Result:=ExtractFilePath(Result);
187 // C:\Program Files\PuTTY\
189 if not DirExists(Result) then begin
191 Result:='C
:\
Program Files\PuTTY
\';
194 Result
:=Result
+'plink.exe'
210 GC_CRLFCommitAsIs
= 3;
213 // Wizard page
and variables
for the Path options
.
214 PathPage
:TWizardPage
;
215 RdbPath
:array[GP_BashOnly
..GP_CmdTools
] of TRadioButton
;
217 // Wizard page
and variables
for the SSH options
.
218 PuTTYPage
:TWizardPage
;
219 RdbSSH
:array[GS_OpenSSH
..GS_Plink
] of TRadioButton
;
222 // Wizard page
and variables
for the CR
/LF options
.
223 CRLFPage
:TWizardPage
;
224 RdbCRLF
:array[GC_LFOnly
..GC_CRLFCommitAsIs
] of TRadioButton
;
226 procedure BrowseForPuTTYFolder(Sender
:TObject
);
230 Path
:=ExtractFilePath(EdtPlink
.Text);
231 BrowseForFolder('Please select the PuTTY folder:',Path
,False);
232 if FileExists(Path
+'\TortoisePlink.exe') then begin
233 EdtPlink
.Text:=Path
+'\TortoisePlink.exe';
234 RdbSSH
[GS_Plink
].Checked
:=True;
235 end else if FileExists(Path
+'\plink.exe') then begin
236 EdtPlink
.Text:=Path
+'\plink.exe';
237 RdbSSH
[GS_Plink
].Checked
:=True;
239 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError
,MB_OK
);
247 procedure InitializeWizard
;
249 LblGitBash
,LblGitCmd
,LblGitCmdTools
,LblGitCmdToolsWarn
:TLabel
;
250 LblOpenSSH
,LblPlink
:TLabel
;
251 LblLFOnly
,LblCRLFAlways
,LblCRLFCommitAsIs
:TLabel
;
255 // Create a custom page
for modifying the environment
.
256 PathPage
:=CreateCustomPage(
258 'Adjusting your PATH environment',
259 'How would you like to use Git from the command line?'
263 RdbPath
[GP_BashOnly
]:=TRadioButton
.Create(PathPage
);
264 with RdbPath
[GP_BashOnly
] do begin
265 Parent
:=PathPage
.Surface
;
266 Caption
:='Use Git Bash only';
271 Font
.Style
:=[fsBold
];
275 LblGitBash
:=TLabel
.Create(PathPage
);
276 with LblGitBash
do begin
277 Parent
:=PathPage
.Surface
;
279 'This is the most conservative choice if you are concerned about the stability' + #
13 +
280 'of your system. Your PATH will not be modified.';
288 RdbPath
[GP_Cmd
]:=TRadioButton
.Create(PathPage
);
289 with RdbPath
[GP_Cmd
] do begin
290 Parent
:=PathPage
.Surface
;
291 Caption
:='Run Git from the Windows Command Prompt';
296 Font
.Style
:=[fsBold
];
299 LblGitCmd
:=TLabel
.Create(PathPage
);
300 with LblGitCmd
do begin
301 Parent
:=PathPage
.Surface
;
303 'This option is considered safe and no conflicts with other tools are known.' + #
13 +
304 'Only Git will be added to your PATH. Use this option if you want to use Git' + #
13 +
305 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
313 RdbPath
[GP_CmdTools
]:=TRadioButton
.Create(PathPage
);
314 with RdbPath
[GP_CmdTools
] do begin
315 Parent
:=PathPage
.Surface
;
316 Caption
:='Run Git and included Unix tools from the Windows Command Prompt';
321 Font
.Style
:=[fsBold
];
324 LblGitCmdTools
:=TLabel
.Create(PathPage
);
325 with LblGitCmdTools
do begin
326 Parent
:=PathPage
.Surface
;
327 Caption
:='Both Git and its accompanying Unix tools will be added to your PATH.';
333 LblGitCmdToolsWarn
:=TLabel
.Create(PathPage
);
334 with LblGitCmdToolsWarn
do begin
335 Parent
:=PathPage
.Surface
;
337 'Warning: This will override Windows tools like find.exe and' + #
13 +
338 'sort.exe. Select this option only if you understand the implications.';
344 Font
.Style
:=[fsBold
];
347 // Restore the setting chosen during a previous install
.
348 Data
:=GetPreviousData('Path Option','BashOnly');
349 if Data
='BashOnly' then begin
350 RdbPath
[GP_BashOnly
].Checked
:=True;
351 end else if Data
='Cmd' then begin
352 RdbPath
[GP_Cmd
].Checked
:=True;
353 end else if Data
='CmdTools' then begin
354 RdbPath
[GP_CmdTools
].Checked
:=True;
357 // Create a custom page
for using (Tortoise
)Plink instead
of OpenSSH
.
358 PuTTYPage
:=CreateCustomPage(
360 'Choosing the SSH executable',
361 'Which Secure Shell client program would you like Git to use?'
365 RdbSSH
[GS_OpenSSH
]:=TRadioButton
.Create(PuTTYPage
);
366 with RdbSSH
[GS_OpenSSH
] do begin
367 Parent
:=PuTTYPage
.Surface
;
368 Caption
:='Use OpenSSH';
373 Font
.Style
:=[fsBold
];
377 LblOpenSSH
:=TLabel
.Create(PuTTYPage
);
378 with LblOpenSSH
do begin
379 Parent
:=PuTTYPage
.Surface
;
381 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #
13 +
382 'environment variables will not be modified.';
390 RdbSSH
[GS_Plink
]:=TRadioButton
.Create(PuTTYPage
);
391 with RdbSSH
[GS_Plink
] do begin
392 Parent
:=PuTTYPage
.Surface
;
393 Caption
:='Use (Tortoise)Plink';
398 Font
.Style
:=[fsBold
];
401 LblPlink
:=TLabel
.Create(PuTTYPage
);
402 with LblPlink
do begin
403 Parent
:=PuTTYPage
.Surface
;
405 'This uses (Tortoise)Plink.exe from the TortoiseSVN/CVS or PuTTY' + #
13 +
406 'applications which need to be provided by the user. The GIT_SSH and' + #
13 +
407 'SVN_SSH environment variables will point to the below executable:';
413 EdtPlink
:=TEdit
.Create(PuTTYPage
);
414 with EdtPlink
do begin
415 Parent
:=PuTTYPage
.Surface
;
416 Text:=GetPuTTYLocation
;
417 if not FileExists(Text) then begin
425 BtnPlink
:=TButton
.Create(PuTTYPage
);
426 with BtnPlink
do begin
427 Parent
:=PuTTYPage
.Surface
;
429 OnClick
:=@BrowseForPuTTYFolder
;
436 // Restore the setting chosen during a previous install
.
437 Data
:=GetPreviousData('SSH Option','OpenSSH');
438 if Data
='OpenSSH' then begin
439 RdbSSH
[GS_OpenSSH
].Checked
:=True;
440 end else if Data
='Plink' then begin
441 RdbSSH
[GS_Plink
].Checked
:=True;
444 // Create a custom page
for the autoCRLF setting
.
445 CRLFPage
:=CreateCustomPage(
447 'Choosing CR/LF behavior',
448 'Which CR/LF behavior would you like Git to have?'
452 RdbCRLF
[GC_LFOnly
]:=TRadioButton
.Create(CRLFPage
);
453 with RdbCRLF
[GC_LFOnly
] do begin
454 Parent
:=CRLFPage
.Surface
;
455 Caption
:='Use Unix style line endings';
460 Font
.Style
:=[fsBold
];
464 LblLFOnly
:=TLabel
.Create(CRLFPage
);
465 with LblLFOnly
do begin
466 Parent
:=CRLFPage
.Surface
;
468 'Choose this if a single Line Feed character ends your lines. Most Windows' + #
13 +
469 'programs can cope with these line endings. However, some editors, like' + #
13 +
470 'Notepad, will show everything in one line with this mode.';
478 RdbCRLF
[GC_CRLFAlways
]:=TRadioButton
.Create(CRLFPage
);
479 with RdbCRLF
[GC_CRLFAlways
] do begin
480 Parent
:=CRLFPage
.Surface
;
481 Caption
:='Use Windows style line endings';
486 Font
.Style
:=[fsBold
];
490 LblCRLFAlways
:=TLabel
.Create(CRLFPage
);
491 with LblCRLFAlways
do begin
492 Parent
:=CRLFPage
.Surface
;
494 'Choose this if your source code uses a Carriage Return and a Line Feed' + #
13 +
495 'character to end lines. This is the DOS convention; your checked-out files' + #
13 +
496 'might not be handled gracefully by MSYS / Cygwin command line utilities.';
504 RdbCRLF
[GC_CRLFCommitAsIs
]:=TRadioButton
.Create(CRLFPage
);
505 with RdbCRLF
[GC_CRLFCommitAsIs
] do begin
506 Parent
:=CRLFPage
.Surface
;
507 Caption
:='Commit line endings as they are';
512 Font
.Style
:=[fsBold
];
516 LblCRLFCommitAsIs
:=TLabel
.Create(CRLFPage
);
517 with LblCRLFCommitAsIs
do begin
518 Parent
:=CRLFPage
.Surface
;
520 'Choose this if you know what you are doing and want to track the files with' + #
13 +
521 'the line endings exactly as they appear in the files. This option might' + #
13 +
522 'cause your projects to be hard to use on other platforms.';
529 // Restore the setting chosen during a previous install
.
530 Data
:=GetPreviousData('CRLF Option','CRLFAlways');
531 if Data
='LFOnly' then begin
532 RdbCRLF
[GC_LFOnly
].Checked
:=True;
533 end else if Data
='CRLFAlways' then begin
534 RdbCRLF
[GC_CRLFAlways
].Checked
:=True;
535 end else if Data
='CRLFCommitAsIs' then begin
536 RdbCRLF
[GC_CRLFCommitAsIs
].Checked
:=True;
540 function NextButtonClick(CurPageID
:Integer):Boolean;
542 if CurPageID
<>PuTTYPage
.ID
then begin
547 Result
:=RdbSSH
[GS_OpenSSH
].Checked
or
548 (RdbSSH
[GS_Plink
].Checked
and FileExists(EdtPlink
.Text));
550 if not Result
then begin
551 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError
,MB_OK
);
555 procedure CurStepChanged(CurStep
:TSetupStep
);
557 AppDir
,FileName
,Cmd
,Msg
:string;
558 BuiltIns
,EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
564 if CurStep
<>ssPostInstall
then begin
568 AppDir
:=ExpandConstant('{app}');
574 // Load the built
-ins from a
text file.
575 FileName
:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}');
576 if LoadStringsFromFile(FileName,BuiltIns) then begin
577 // Check if we are running on NTFS.
579 if SetNTFSCompression(AppDir+'\bin\git
.exe
',true) then begin
580 IsNTFS:=SetNTFSCompression(AppDir+'\bin\git
.exe
',false);
583 Count:=GetArrayLength(BuiltIns)-1;
585 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
586 for i:=0 to Count do begin
587 FileName:=AppDir+'\bin
\'+ChangeFileExt(ExtractFileName(BuiltIns
[i
]),'');
588 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
589 Log('Line {#emit __LINE__}: Unable to delete script "'+FileName
+'", ignoring.');
593 // Map the built
-ins
to git
.exe
.
595 Log('Line {#emit __LINE__}: Partition seems to be NTFS, trying to create built-in aliases as hard links.');
597 for i
:=0 to Count
do begin
598 FileName
:=AppDir
+'\'+BuiltIns[i];
600 // On non-NTFS partitions, create hard links.
601 if (FileExists(FileName) and (not DeleteFile(FileName))) or
602 (not CreateHardLink(FileName,AppDir+'\bin\git
.exe
',0)) then begin
603 Log('Line
{#emit __LINE__}: Unable
to create hard link
"'+FileName+'", will
try to copy
files.');
609 Log('Line
{#emit __LINE__}: Successfully created built
-in aliases
as hard links
.');
612 // The fallback is to copy the files.
613 if not IsNTFS then begin
614 Log('Line
{#emit __LINE__}: Trying
to create built
-in aliases
as file copies
.');
616 for i:=0 to Count do begin
617 FileName:=AppDir+'\'+BuiltIns
[i
];
619 // On non
-NTFS partitions
, copy simply the
files (overwriting existing ones
).
620 if not FileCopy(AppDir
+'\bin\git.exe',FileName
,false) then begin
621 Msg
:='Line {#emit __LINE__}: Unable to create file copy "'+FileName
+'".';
622 MsgBox(Msg
,mbError
,MB_OK
);
624 // This
is not a critical error
, Git could basically be used without the
625 // aliases
for built
-ins
, so we continue
.
629 Log('Line {#emit __LINE__}: Successfully created built-in aliases as file copies.');
632 // Delete any duplicate
files in case we are updating from a non
-libexec
to a libexec directory layout
.
633 if FindFirst(AppDir
+'\libexec\git-core\*',FindRec
) then begin
635 if (FindRec
.Attributes
and FILE_ATTRIBUTE_DIRECTORY
)=0 then begin
636 FileName
:=AppDir
+'\bin\'+FindRec.name;
637 if (Pos(FindRec.name,'git
.exe
')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
638 Log('Line
{#emit __LINE__}: Unable
to delete dupe
"'+FileName+'", ignoring
.');
641 until not FindNext(FindRec);
645 Msg:='Line
{#emit __LINE__}: Unable
to read file "{#emit APP_BUILTINS}".';
646 MsgBox(Msg,mbError,MB_OK);
648 // This is not a critical error, Git could basically be used without the
649 // aliases for built-ins, so we continue.
656 if RdbCRLF[GC_LFOnly].checked then begin
657 Cmd:='core
.autoCRLF input
';
658 end else if RdbCRLF[GC_CRLFAlways].checked then begin
659 Cmd:='core
.autoCRLF
true';
661 Cmd:='core
.autoCRLF
false';
663 if not Exec(AppDir + '\bin\git
.exe
', 'config
-f gitconfig
' + Cmd,
664 AppDir + '\etc
', SW_HIDE, ewWaitUntilTerminated, i) then begin
665 Msg:='Could
not set CR
/LF behavior
: ' + Cmd;
666 MsgBox(Msg,mbError,MB_OK);
671 Modify the environment
673 This must happen no later than ssPostInstall to make
674 "ChangesEnvironment=yes" not happend before the change!
677 FileName:=AppDir+'\setup
.ini
';
679 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
680 EnvSSH:=GetEnvStrings('GIT_SSH
',IsAdminLoggedOn);
681 if (GetArrayLength(EnvSSH)=1) and
682 (CompareStr(EnvSSH[0],GetIniString('Environment
','GIT_SSH
','',FileName))=0) then begin
683 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,[]) then begin
684 Msg:='Line
{#emit __LINE__}: Unable
to reset GIT_SSH prior
to install
.';
685 MsgBox(Msg,mbError,MB_OK);
687 // This is not a critical error, the user can probably fix it manually,
692 EnvSSH:=GetEnvStrings('SVN_SSH
',IsAdminLoggedOn);
693 if (GetArrayLength(EnvSSH)=1) and
694 (CompareStr(EnvSSH[0],GetIniString('Environment
','SVN_SSH
','',FileName))=0) then begin
695 if not SetEnvStrings('SVN_SSH
',IsAdminLoggedOn,True,[]) then begin
696 Msg:='Line
{#emit __LINE__}: Unable
to reset SVN_SSH prior
to install
.';
697 MsgBox(Msg,mbError,MB_OK);
699 // This is not a critical error, the user can probably fix it manually,
704 if RdbSSH[GS_Plink].Checked then begin
705 SetArrayLength(EnvSSH,1);
706 EnvSSH[0]:=EdtPlink.Text;
708 // Set GIT_SSH as specified by the user.
709 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,EnvSSH) then begin
710 Msg:='Line
{#emit __LINE__}: Unable
to set the GIT_SSH environment variable
.';
711 MsgBox(Msg,mbError,MB_OK);
713 // This is not a critical error, the user can probably fix it manually,
717 // Mark that we have changed GIT_SSH by writing its value to a file.
718 if not SetIniString('Environment
','GIT_SSH
',EnvSSH[0],FileName) then begin
719 Msg:='Line
{#emit __LINE__}: Unable
to write
to file "'+FileName+'".';
720 MsgBox(Msg,mbError,MB_OK);
722 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
726 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
727 StringChangeEx(EnvSSH[0],'\','\\',True);
728 EnvSSH
[0]:=AddQuotes(EnvSSH
[0]);
730 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn
,True,EnvSSH
) then begin
731 Msg
:='Line {#emit __LINE__}: Unable to set the SVN_SSH environment variable.';
732 MsgBox(Msg
,mbError
,MB_OK
);
734 // This
is not a critical error
, the user can probably fix it manually
,
738 // Mark that we have changed SVN_SSH by writing its value
to a
file.
739 if not SetIniString('Environment','SVN_SSH',EnvSSH
[0],FileName
) then begin
740 Msg
:='Line {#emit __LINE__}: Unable to write to file "'+FileName
+'".';
741 MsgBox(Msg
,mbError
,MB_OK
);
743 // This
is not a critical error
, though uninstall
/ reinstall will probably
not run cleanly
,
748 // Get the current user
's directories in PATH.
749 EnvPath:=GetEnvStrings('PATH
',IsAdminLoggedOn);
751 // First, remove the installation directory from PATH in any case.
752 for i:=0 to GetArrayLength(EnvPath)-1 do begin
753 if Pos(AppDir+'\',EnvPath
[i
]+'\')=1 then begin
758 // Delete HOME if a previous installation modified it.
759 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
760 if (GetArrayLength(EnvHome)=1) and
761 (CompareStr(EnvHome[0],GetIniString('Environment
','HOME
','',FileName))=0) then begin
762 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,[]) then begin
763 Msg:='Line
{#emit __LINE__}: Unable
to reset HOME prior
to install
.';
764 MsgBox(Msg,mbError,MB_OK);
766 // This is not a critical error, the user can probably fix it manually,
771 // Modify the PATH variable as requested by the user.
772 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
773 i:=GetArrayLength(EnvPath);
774 SetArrayLength(EnvPath,i+1);
776 // List \cmd before \bin so \cmd has higher priority and programs in
777 // there will be called in favor of those in \bin.
778 EnvPath[i]:=ExpandConstant('{app}\cmd
');
780 if RdbPath[GP_CmdTools].Checked then begin
781 SetArrayLength(EnvPath,i+2);
782 EnvPath[i+1]:=ExpandConstant('{app}\bin
');
784 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
785 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
786 i:=GetArrayLength(EnvHome);
787 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
788 SetArrayLength(EnvHome,1);
789 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
790 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,EnvHome) then begin
791 Msg:='Line
{#emit __LINE__}: Unable
to set the HOME environment variable
.';
792 MsgBox(Msg,mbError,MB_OK);
794 // This is not a critical error, the user can probably fix it manually,
798 // Mark that we have changed HOME.
799 if not SetIniString('Environment
','HOME
',EnvHome[0],FileName) then begin
800 Msg:='Line
{#emit __LINE__}: Unable
to write
to file "'+FileName+'".';
801 MsgBox(Msg,mbError,MB_OK);
803 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
810 // Set the current user's PATH directories
.
811 if not SetEnvStrings('PATH',IsAdminLoggedOn
,True,EnvPath
) then begin
812 Msg
:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
813 MsgBox(Msg
,mbError
,MB_OK
);
815 // This
is not a critical error
, the user can probably fix it manually
,
820 Create the Windows Explorer shell extensions
823 if IsAdminLoggedOn
then begin
824 RootKey
:=HKEY_LOCAL_MACHINE
;
826 RootKey
:=HKEY_CURRENT_USER
;
829 if IsTaskSelected('shellextension') then begin
830 Cmd
:=ExpandConstant('"{syswow64}\cmd.exe"');
831 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
832 (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Cmd
+' /c "pushd "%1" && "'+AppDir
+'\bin\sh.exe" --login -i"')) then begin
833 Msg
:='Line {#emit __LINE__}: Unable to create "Git Bash Here" shell extension.';
834 MsgBox(Msg
,mbError
,MB_OK
);
836 // This
is not a critical error
, the user can probably fix it manually
,
841 if IsTaskSelected('guiextension') then begin
842 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
843 (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
844 Msg
:='Line {#emit __LINE__}: Unable to create "Git GUI Here" shell extension.';
845 MsgBox(Msg
,mbError
,MB_OK
);
847 // This
is not a critical error
, the user can probably fix it manually
,
853 procedure RegisterPreviousData(PreviousDataKey
:Integer);
859 if RdbPath
[GP_BashOnly
].Checked
then begin
861 end else if RdbPath
[GP_Cmd
].Checked
then begin
863 end else if RdbPath
[GP_CmdTools
].Checked
then begin
866 SetPreviousData(PreviousDataKey
,'Path Option',Data
);
870 if RdbSSH
[GS_OpenSSH
].Checked
then begin
872 end else if RdbSSH
[GS_Plink
].Checked
then begin
875 SetPreviousData(PreviousDataKey
,'SSH Option',Data
);
877 // Git CR
/LF options
.
879 if RdbCRLF
[GC_LFOnly
].Checked
then begin
881 end else if RdbCRLF
[GC_CRLFAlways
].Checked
then begin
883 end else if RdbCRLF
[GC_CRLFCommitAsIs
].Checked
then begin
884 Data
:='CRLFCommitAsIs';
886 SetPreviousData(PreviousDataKey
,'CRLF Option',Data
);
893 function InitializeUninstall
:Boolean;
895 FileName
,NewName
,Msg
:string;
897 FileName
:=ExpandConstant('{app}')+'\bin\ssh-agent.exe';
898 if FileExists(FileName
) then begin
899 // Create a temporary copy
of the
file we
try to delete
.
900 NewName
:=FileName
+'.'+IntToStr(1000+Random(9000));
901 Result
:=FileCopy(FileName
,NewName
,True) and DeleteFile(FileName
);
903 if not Result
then begin
904 Msg
:='Line {#emit __LINE__}: Please stop all ssh-agent processes and run uninstall again.';
905 MsgBox(Msg
,mbError
,MB_OK
);
908 // Clean
-up the temporary
copy (ignoring any errors
).
911 // Clean
-up the temporary
copy (ignoring any errors
).
912 RenameFile(NewName
,FileName
);
919 procedure CurUninstallStepChanged(CurUninstallStep
:TUninstallStep
);
921 AppDir
,Command
,Msg
:string;
922 EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
926 if CurUninstallStep
<>usUninstall
then begin
931 Modify the environment
933 This must happen no later than usUninstall to make
934 "ChangesEnvironment=yes" not happend before the change!
937 AppDir
:=ExpandConstant('{app}');
938 Command
:=AppDir
+'\setup.ini';
940 // Delete the current user
's GIT_SSH and SVN_SSH if we set it.
941 EnvSSH:=GetEnvStrings('GIT_SSH
',IsAdminLoggedOn);
942 if (GetArrayLength(EnvSSH)=1) and
943 (CompareStr(EnvSSH[0],GetIniString('Environment
','GIT_SSH
','',Command))=0) then begin
944 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,[]) then begin
945 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to GIT_SSH
.';
946 MsgBox(Msg,mbError,MB_OK);
948 // This is not a critical error, the user can probably fix it manually,
953 EnvSSH:=GetEnvStrings('SVN_SSH
',IsAdminLoggedOn);
954 if (GetArrayLength(EnvSSH)=1) and
955 (CompareStr(EnvSSH[0],GetIniString('Environment
','SVN_SSH
','',Command))=0) then begin
956 if not SetEnvStrings('SVN_SSH
',IsAdminLoggedOn,True,[]) then begin
957 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to SVN_SSH
.';
958 MsgBox(Msg,mbError,MB_OK);
960 // This is not a critical error, the user can probably fix it manually,
965 // Get the current user's directories
in PATH
.
966 EnvPath
:=GetEnvStrings('PATH',IsAdminLoggedOn
);
968 // Remove the installation directory from PATH
in any
case, even
if it
969 // was
not added by the installer
.
970 for i
:=0 to GetArrayLength(EnvPath
)-1 do begin
971 if Pos(AppDir
+'\',EnvPath[i]+'\')=1 then begin
976 // Reset the current user
's directories in PATH.
977 if not SetEnvStrings('PATH
',IsAdminLoggedOn,True,EnvPath) then begin
978 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to PATH
.';
979 MsgBox(Msg,mbError,MB_OK);
981 // This is not a critical error, the user can probably fix it manually,
985 // Reset the current user's HOME
if we modified it
.
986 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
987 if (GetArrayLength(EnvHome
)=1) and
988 (CompareStr(EnvHome
[0],GetIniString('Environment','HOME','',Command
))=0) then begin
989 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,[]) then begin
990 Msg
:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
991 MsgBox(Msg
,mbError
,MB_OK
);
993 // This
is not a critical error
, the user can probably fix it manually
,
998 if FileExists(Command
) and (not DeleteFile(Command
)) then begin
999 Msg
:='Line {#emit __LINE__}: Unable to delete file "'+Command
+'".';
1000 MsgBox(Msg
,mbError
,MB_OK
);
1002 // This
is not a critical error
, the user can probably fix it manually
,
1007 Delete the Windows Explorer shell extensions
1010 if IsAdminLoggedOn
then begin
1011 RootKey
:=HKEY_LOCAL_MACHINE
;
1013 RootKey
:=HKEY_CURRENT_USER
;
1017 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command
);
1018 if Pos(AppDir
,Command
)>0 then begin
1019 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
1020 Msg
:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
1021 MsgBox(Msg
,mbError
,MB_OK
);
1023 // This
is not a critical error
, the user can probably fix it manually
,
1029 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command
);
1030 if Pos(AppDir
,Command
)>0 then begin
1031 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
1032 Msg
:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
1033 MsgBox(Msg
,mbError
,MB_OK
);
1035 // This
is not a critical error
, the user can probably fix it manually
,