1 ; Uncomment the line below to be able to compile the script from within the IDE.
2 ;#define COMPILE_FROM_IDE
5 #ifdef COMPILE_FROM_IDE
6 #define APP_VERSION
'Snapshot'
8 #define APP_VERSION
'%APPVERSION%'
10 #define APP_URL
'http://msysgit.googlecode.com/'
11 #define APP_BUILTINS
'etc\fileList-builtins.txt'
12 #define APP_BINDIMAGE
'etc\fileList-bindimage.txt'
14 #define COMP_CONSOLE_FONT
'Use a TrueType font in all console windows (not only for Git Bash)'
16 #define DROP_HANDLER_GUID
'{{86C86720-42A0-1069-A2E8-08002B30309D}}'
20 Compression
=lzma2
/ultra
21 LZMAUseSeparateProcess
=yes
22 OutputBaseFilename
={#APP_NAME+'-'+APP_VERSION}
23 OutputDir
={#GetEnv('USERPROFILE')}
25 #ifdef COMPILE_FROM_IDE
26 SourceDir
={#GetEnv('TEMP')}\WinGit
32 AppPublisher
=The Git Development Community
33 AppPublisherURL
={#APP_URL}
34 AppVersion
={#APP_VERSION}
35 ChangesEnvironment
=yes
36 DefaultDirName
={pf}\
{#APP_NAME}
38 DefaultGroupName
={#APP_NAME}
39 DisableProgramGroupPage
=auto
41 InfoBeforeFile
=gpl
-2.0.rtf
42 PrivilegesRequired
=none
43 UninstallDisplayIcon
={app}\etc\git
.ico
44 #ifndef COMPILE_FROM_IDE
45 #
if Pos('-',APP_VERSION
)>0
46 VersionInfoVersion
={#Copy(APP_VERSION,1,Pos('-',APP_VERSION)-1)}
48 VersionInfoVersion
={#APP_VERSION}
53 SetupIconFile
=etc\git
.ico
54 WizardImageBackColor
=clWhite
56 WizardImageFile
=git
.bmp
57 WizardSmallImageFile
=gitsmall
.bmp
60 ; Define a dummy type to avoid getting the default ones.
61 Name
: custom
; Description
: Custom installation
; Flags
: iscustom
64 Name
: icons
; Description
: Additional icons
; Types
: custom
65 Name
: icons\quicklaunch
; Description
: In the Quick Launch
; Types
: custom
66 Name
: icons\desktop
; Description
: On the Desktop
; Types
: custom
67 Name
: ext
; Description
: Windows Explorer integration
; Types
: custom
68 Name
: ext
\reg
; Description
: Simple context
menu (Registry based
); Flags
: exclusive; Types
: custom
69 Name
: ext
\reg\shellhere
; Description
: Git Bash Here
; Types
: custom
70 Name
: ext
\reg\guihere
; Description
: Git GUI Here
; Types
: custom
71 Name
: ext\cheetah
; Description
: Advanced context
menu (git
-cheetah plugin
); Flags
: exclusive; Types
: custom
72 Name
: assoc
; Description
: Associate
.git
* configuration
files with the default
text editor
; Types
: custom
73 Name
: assoc_sh
; Description
: Associate
.sh
files to be run
with Bash
; Types
: custom
74 Name
: consolefont
; Description
: {#COMP_CONSOLE_FONT}; Types
: custom
77 ; Install files that might be in use during setup under a different name.
78 Source
: git
-cheetah\git_shell_ext
.dll
; DestDir
: {app}\git
-cheetah
; DestName
: git_shell_ext
.dll
.new
; Flags
: replacesameversion; Components
: ext\cheetah
; AfterInstall
: DeleteFromVirtualStore
79 Source
: git
-cheetah\git_shell_ext64
.dll
; DestDir
: {app}\git
-cheetah
; DestName
: git_shell_ext64
.dll
.new
; Flags
: replacesameversion; Components
: ext\cheetah
; AfterInstall
: DeleteFromVirtualStore
81 Source
: *; DestDir
: {app}; Excludes
: \
*.bmp
, gpl
-2.0.rtf
, \
*.iss
, \tmp
.*, \bin\
*install
*, \git
-cheetah\git_shell_ext
.dll
, \git
-cheetah\git_shell_ext64
.dll
; Flags
: recursesubdirs replacesameversion sortfilesbyextension; AfterInstall
: DeleteFromVirtualStore
82 Source
: ReleaseNotes
.rtf
; DestDir
: {app}; Flags
: isreadme replacesameversion; AfterInstall
: DeleteFromVirtualStore
85 Name
: {group}\Git GUI
; Filename
: {app}\bin\wish
.exe
; Parameters
: """{app}\libexec\git-core\git-gui"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
86 Name
: {group}\Git Bash
; Filename
: {syswow64}\cmd
.exe
; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
89 BeveledLabel
={#APP_URL}
90 SetupAppTitle
={#APP_NAME} Setup
91 SetupWindowTitle
={#APP_NAME} Setup
94 ; There is no "Console" key in HKLM.
95 Root
: HKCU
; Subkey
: Console
; ValueType
: string; ValueName
: FaceName
; ValueData
: Lucida Console
; Flags
: uninsclearvalue; Components
: consolefont
96 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontFamily
; ValueData
: $00000036; Components
: consolefont
97 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontSize
; ValueData
: $000e0000; Components
: consolefont
98 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontWeight
; ValueData
: $00000190; Components
: consolefont
100 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: string; ValueName
: FaceName
; ValueData
: Lucida Console
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
101 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontFamily
; ValueData
: $00000036; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
102 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontSize
; ValueData
: $000e0000; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
103 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontWeight
; ValueData
: $00000190; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty
105 ; Note that we write the Registry values below either to HKLM or to HKCU depending on whether the user running the installer
106 ; is a member of the local Administrators group or not (see the "Check" argument).
108 ; File associations for configuration files that may be contained in a repository (so this does not include ".gitconfig").
109 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
110 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
111 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
112 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
113 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
114 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
116 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
117 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
118 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
119 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
120 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
121 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
123 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
124 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
125 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: IsAdminLoggedOn
; Components
: assoc
126 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
127 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
128 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist uninsdeletevalue uninsdeletekeyifempty; Check
: not IsAdminLoggedOn
; Components
: assoc
130 ; Associate .sh extension with sh.exe so those files are double-clickable,
131 ; startable from cmd.exe, and when files are dropped on them they are passed
132 ; as arguments to the script.
134 ; Install under HKEY_LOCAL_MACHINE if an administrator is installing.
135 Root
: HKLM
; Subkey
: Software\Classes\
.sh
; ValueType
: string; ValueData
: sh_auto_file
; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: IsAdminLoggedOn
; Components
: assoc_sh
136 Root
: HKLM
; Subkey
: Software\Classes\sh_auto_file
; ValueType
: string; ValueData
: "Shell Script"; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: IsAdminLoggedOn
; Components
: assoc_sh
137 Root
: HKLM
; Subkey
: Software\Classes\sh_auto_file\shell\open\command
; ValueType
: string; ValueData
: "{syswow64}\cmd.exe /C """"{app}\bin\sh.exe"" ""--login"" ""%1"" %*"""; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: IsAdminLoggedOn
; Components
: assoc_sh
138 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
139 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
141 ; Install under HKEY_CURRENT_USER if a non-administrator is installing.
142 Root
: HKCU
; Subkey
: Software\Classes\
.sh
; ValueType
: string; ValueData
: sh_auto_file
; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: not IsAdminLoggedOn
; Components
: assoc_sh
143 Root
: HKCU
; Subkey
: Software\Classes\sh_auto_file
; ValueType
: string; ValueData
: "Shell Script"; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: not IsAdminLoggedOn
; Components
: assoc_sh
144 Root
: HKCU
; Subkey
: Software\Classes\sh_auto_file\shell\open\command
; ValueType
: string; ValueData
: "{syswow64}\cmd.exe /C """"{app}\bin\sh.exe"" ""--login"" ""%1"" %*"""; Flags
: createvalueifdoesntexist uninsdeletekeyifempty uninsdeletevalue; Check
: not IsAdminLoggedOn
; Components
: assoc_sh
145 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
146 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
149 ; Delete the built-ins.
150 Type: files; Name
: {app}\bin\git
-*.exe
151 Type: files; Name
: {app}\libexec\git
-core\git
-*.exe
152 Type: files; Name
: {app}\libexec\git
-core\git
.exe
154 ; Delete any (temporary) git-cheetah files.
155 Type: files; Name
: {app}\git
-cheetah\
*.*
157 ; Delete any manually created shortcuts.
158 Type: files; Name
: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash
.lnk
159 Type: files; Name
: {code:GetShellFolder|desktop}\Git Bash
.lnk
160 Type: files; Name
: {app}\Git Bash
.lnk
162 ; Delete a home directory inside the msysGit directory.
163 Type: dirifempty; Name
: {app}\home\
{username}
164 Type: dirifempty; Name
: {app}\home
167 #include
"helpers.inc.iss"
168 #include
"environment.inc.iss"
169 #include
"putty.inc.iss"
170 #include
"modules.inc.iss"
172 procedure DeleteFromVirtualStore
;
174 VirtualStore
,FileName
:String;
177 VirtualStore
:=AddBackslash(ExpandConstant('{localappdata}'))+'VirtualStore';
178 FileName
:=ExpandConstant(CurrentFileName
);
179 DriveChars
:=Length(ExtractFileDrive(FileName
));
180 if DriveChars
>0 then begin
181 Delete(FileName
,1,DriveChars
);
182 FileName
:=VirtualStore
+FileName
;
183 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
184 Log('Line {#__LINE__}: Unable delete "'+FileName
+'".');
185 // This
is not a critical error
, the user can probably fix it manually
,
191 function CreateHardLink(lpFileName
,lpExistingFileName
:String;lpSecurityAttributes
:Integer):Boolean;
193 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
195 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
198 function BindImageEx(Flags
:DWORD
;ImageName
,DllPath
,SymbolPath
:AnsiString
;StatusRoutine
:Integer):Boolean;
199 external 'BindImageEx@Imagehlp.dll stdcall delayload setuponly';
211 // Git line ending conversion options
.
214 GC_CRLFCommitAsIs
= 3;
216 // BindImageEx API constants
.
217 BIND_NO_BOUND_IMPORTS
= $00000001;
218 BIND_NO_UPDATE
= $00000002;
219 BIND_ALL_IMAGES
= $00000004;
220 BIND_CACHE_IMPORT_DLLS
= $00000008;
223 // Wizard page
and variables
for the Path options
.
224 PathPage
:TWizardPage
;
225 RdbPath
:array[GP_BashOnly
..GP_CmdTools
] of TRadioButton
;
227 // Wizard page
and variables
for the SSH options
.
228 PuTTYPage
:TWizardPage
;
229 RdbSSH
:array[GS_OpenSSH
..GS_Plink
] of TRadioButton
;
232 // Wizard page
and variables
for the line ending conversion options
.
233 CRLFPage
:TWizardPage
;
234 RdbCRLF
:array[GC_LFOnly
..GC_CRLFCommitAsIs
] of TRadioButton
;
236 // Wizard page
and variables
for the processes page
.
238 Processes
:ProcessList
;
239 ProcessesPage
:TWizardPage
;
240 ProcessesListBox
:TListBox
;
241 ProcessesRefresh
,ContinueButton
:TButton
;
243 procedure BrowseForPuTTYFolder(Sender
:TObject
);
247 Path
:=ExtractFilePath(EdtPlink
.Text);
248 BrowseForFolder('Please select the PuTTY folder:',Path
,False);
249 if FileExists(Path
+'\TortoisePlink.exe') then begin
250 EdtPlink
.Text:=Path
+'\TortoisePlink.exe';
251 RdbSSH
[GS_Plink
].Checked
:=True;
252 end else if FileExists(Path
+'\plink.exe') then begin
253 EdtPlink
.Text:=Path
+'\plink.exe';
254 RdbSSH
[GS_Plink
].Checked
:=True;
256 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError
,MB_OK
);
260 procedure DeleteContextMenuEntries
;
262 AppDir
,Command
,Msg
:String;
265 AppDir
:=ExpandConstant('{app}');
267 if IsAdminLoggedOn
then begin
268 RootKey
:=HKEY_LOCAL_MACHINE
;
270 RootKey
:=HKEY_CURRENT_USER
;
274 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command
);
275 if Pos(AppDir
,Command
)>0 then begin
276 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
277 Msg
:='Line {#__LINE__}: Unable to remove "Git Bash Here" shell extension.';
278 MsgBox(Msg
,mbError
,MB_OK
);
280 // This
is not a critical error
, the user can probably fix it manually
,
286 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command
);
287 if Pos(AppDir
,Command
)>0 then begin
288 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
289 Msg
:='Line {#__LINE__}: Unable to remove "Git GUI Here" shell extension.';
290 MsgBox(Msg
,mbError
,MB_OK
);
292 // This
is not a critical error
, the user can probably fix it manually
,
298 procedure RefreshProcessList(Sender
:TObject
);
300 Version
:TWindowsVersion
;
301 Modules
:TArrayOfString
;
302 ProcsCloseRequired
,ProcsCloseOptional
:ProcessList
;
305 ManualClosingRequired
:Boolean;
307 GetWindowsVersionEx(Version
);
309 // Use the
Restart Manager API when installing the shell extension on Windows Vista
and above
.
310 if Version
.Major
>=6 then begin
311 SetArrayLength(Modules
,5);
312 Modules
[0]:=ExpandConstant('{app}\bin\msys-1.0.dll');
313 Modules
[1]:=ExpandConstant('{app}\bin\tcl85.dll');
314 Modules
[2]:=ExpandConstant('{app}\bin\tk85.dll');
315 Modules
[3]:=ExpandConstant('{app}\git-cheetah\git_shell_ext.dll');
316 Modules
[4]:=ExpandConstant('{app}\git-cheetah\git_shell_ext64.dll');
317 SessionHandle
:=FindProcessesUsingModules(Modules
,Processes
);
319 SetArrayLength(Modules
,3);
320 Modules
[0]:=ExpandConstant('{app}\bin\msys-1.0.dll');
321 Modules
[1]:=ExpandConstant('{app}\bin\tcl85.dll');
322 Modules
[2]:=ExpandConstant('{app}\bin\tk85.dll');
323 SessionHandle
:=FindProcessesUsingModules(Modules
,ProcsCloseRequired
);
325 SetArrayLength(Modules
,2);
326 Modules
[0]:=ExpandConstant('{app}\git-cheetah\git_shell_ext.dll');
327 Modules
[1]:=ExpandConstant('{app}\git-cheetah\git_shell_ext64.dll');
328 SessionHandle
:=FindProcessesUsingModules(Modules
,ProcsCloseOptional
) or SessionHandle
;
330 // Misuse the
"Restartable" flag
to indicate which processes are required
331 // to be closed before setup can continue
, and which just should be closed
332 // in order
to make changes take effect immediately
.
333 SetArrayLength(Processes
,GetArrayLength(ProcsCloseRequired
)+GetArrayLength(ProcsCloseOptional
));
334 for i
:=0 to GetArrayLength(ProcsCloseRequired
)-1 do begin
335 Processes
[i
]:=ProcsCloseRequired
[i
];
336 Processes
[i
].Restartable
:=False;
338 for i
:=0 to GetArrayLength(ProcsCloseOptional
)-1 do begin
339 Processes
[GetArrayLength(ProcsCloseRequired
)+i
]:=ProcsCloseOptional
[i
];
340 Processes
[GetArrayLength(ProcsCloseRequired
)+i
].Restartable
:=True;
344 ManualClosingRequired
:=False;
346 ProcessesListBox
.Items
.Clear
;
347 if (Sender
=NIL) or (SessionHandle
>0) then begin
348 for i
:=0 to GetArrayLength(Processes
)-1 do begin
349 Caption
:=Processes
[i
].Name
+' (PID '+IntToStr(Processes
[i
].ID
);
350 if Processes
[i
].Restartable
then begin
351 Caption
:=Caption
+', closing is optional';
353 Caption
:=Caption
+', closing is required';
354 ManualClosingRequired
:=True;
356 Caption
:=Caption
+')';
357 ProcessesListBox
.Items
.Append(Caption
);
361 if ContinueButton
<>NIL then begin
362 ContinueButton
.Enabled
:=not ManualClosingRequired
;
370 procedure InitializeWizard
;
373 LblGitBash
,LblGitCmd
,LblGitCmdTools
,LblGitCmdToolsWarn
:TLabel
;
374 LblOpenSSH
,LblPlink
:TLabel
;
375 PuTTYSessions
:TArrayOfString
;
376 LblLFOnly
,LblCRLFAlways
,LblCRLFCommitAsIs
:TLabel
;
381 PrevPageID
:=wpSelectProgramGroup
;
384 * Create a custom page for modifying the environment.
387 PathPage
:=CreateCustomPage(
389 'Adjusting your PATH environment',
390 'How would you like to use Git from the command line?'
392 PrevPageID
:=PathPage
.ID
;
395 RdbPath
[GP_BashOnly
]:=TRadioButton
.Create(PathPage
);
396 with RdbPath
[GP_BashOnly
] do begin
397 Parent
:=PathPage
.Surface
;
398 Caption
:='Use Git Bash only';
403 Font
.Style
:=[fsBold
];
407 LblGitBash
:=TLabel
.Create(PathPage
);
408 with LblGitBash
do begin
409 Parent
:=PathPage
.Surface
;
411 'This is the most conservative choice if you are concerned about the stability' + #
13 +
412 'of your system. Your PATH will not be modified.';
420 RdbPath
[GP_Cmd
]:=TRadioButton
.Create(PathPage
);
421 with RdbPath
[GP_Cmd
] do begin
422 Parent
:=PathPage
.Surface
;
423 Caption
:='Run Git from the Windows Command Prompt';
428 Font
.Style
:=[fsBold
];
431 LblGitCmd
:=TLabel
.Create(PathPage
);
432 with LblGitCmd
do begin
433 Parent
:=PathPage
.Surface
;
435 'This option is considered safe and no conflicts with other tools are known.' + #
13 +
436 'Only Git will be added to your PATH. Use this option if you want to use Git' + #
13 +
437 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
445 RdbPath
[GP_CmdTools
]:=TRadioButton
.Create(PathPage
);
446 with RdbPath
[GP_CmdTools
] do begin
447 Parent
:=PathPage
.Surface
;
448 Caption
:='Run Git and included Unix tools from the Windows Command Prompt';
453 Font
.Style
:=[fsBold
];
456 LblGitCmdTools
:=TLabel
.Create(PathPage
);
457 with LblGitCmdTools
do begin
458 Parent
:=PathPage
.Surface
;
459 Caption
:='Both Git and its accompanying Unix tools will be added to your PATH.';
465 LblGitCmdToolsWarn
:=TLabel
.Create(PathPage
);
466 with LblGitCmdToolsWarn
do begin
467 Parent
:=PathPage
.Surface
;
469 'Warning: This will override Windows tools like find.exe and' + #
13 +
470 'sort.exe. Select this option only if you understand the implications.';
476 Font
.Style
:=[fsBold
];
479 // Restore the setting chosen during a previous install
.
480 Data
:=GetPreviousData('Path Option','BashOnly');
481 if Data
='BashOnly' then begin
482 RdbPath
[GP_BashOnly
].Checked
:=True;
483 end else if Data
='Cmd' then begin
484 RdbPath
[GP_Cmd
].Checked
:=True;
485 end else if Data
='CmdTools' then begin
486 RdbPath
[GP_CmdTools
].Checked
:=True;
490 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
491 * if at least one PuTTY session is found in the Registry.
494 if RegGetSubkeyNames(HKEY_CURRENT_USER
,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions
) and (GetArrayLength(PuTTYSessions
)>0) then begin
495 PuTTYPage
:=CreateCustomPage(
497 'Choosing the SSH executable',
498 'Which Secure Shell client program would you like Git to use?'
500 PrevPageID
:=PuTTYPage
.ID
;
503 RdbSSH
[GS_OpenSSH
]:=TRadioButton
.Create(PuTTYPage
);
504 with RdbSSH
[GS_OpenSSH
] do begin
505 Parent
:=PuTTYPage
.Surface
;
506 Caption
:='Use OpenSSH';
511 Font
.Style
:=[fsBold
];
515 LblOpenSSH
:=TLabel
.Create(PuTTYPage
);
516 with LblOpenSSH
do begin
517 Parent
:=PuTTYPage
.Surface
;
519 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #
13 +
520 'environment variables will not be modified.';
528 RdbSSH
[GS_Plink
]:=TRadioButton
.Create(PuTTYPage
);
529 with RdbSSH
[GS_Plink
] do begin
530 Parent
:=PuTTYPage
.Surface
;
531 Caption
:='Use (Tortoise)Plink';
536 Font
.Style
:=[fsBold
];
539 LblPlink
:=TLabel
.Create(PuTTYPage
);
540 with LblPlink
do begin
541 Parent
:=PuTTYPage
.Surface
;
543 'PuTTY sessions were found in your Registry. You may specify the path' + #
13 +
544 'to an existing copy of (Tortoise)Plink.exe from the TortoiseGit/SVN/CVS' + #
13 +
545 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #
13 +
546 'variables will be adjusted to point to the following executable:';
552 EdtPlink
:=TEdit
.Create(PuTTYPage
);
553 with EdtPlink
do begin
554 Parent
:=PuTTYPage
.Surface
;
555 Text:=GetPuTTYLocation
;
556 if not FileExists(Text) then begin
564 BtnPlink
:=TButton
.Create(PuTTYPage
);
565 with BtnPlink
do begin
566 Parent
:=PuTTYPage
.Surface
;
568 OnClick
:=@BrowseForPuTTYFolder
;
575 // Restore the setting chosen during a previous install
.
576 Data
:=GetPreviousData('SSH Option','OpenSSH');
577 if Data
='OpenSSH' then begin
578 RdbSSH
[GS_OpenSSH
].Checked
:=True;
579 end else if Data
='Plink' then begin
580 RdbSSH
[GS_Plink
].Checked
:=True;
587 * Create a custom page for the core.autocrlf setting.
590 CRLFPage
:=CreateCustomPage(
592 'Configuring the line ending conversions',
593 'How should Git treat line endings in text files?'
595 PrevPageID
:=CRLFPage
.ID
;
598 RdbCRLF
[GC_CRLFAlways
]:=TRadioButton
.Create(CRLFPage
);
599 with RdbCRLF
[GC_CRLFAlways
] do begin
600 Parent
:=CRLFPage
.Surface
;
601 Caption
:='Checkout Windows-style, commit Unix-style line endings';
606 Font
.Style
:=[fsBold
];
610 LblCRLFAlways
:=TLabel
.Create(CRLFPage
);
611 with LblCRLFAlways
do begin
612 Parent
:=CRLFPage
.Surface
;
614 'Git will convert LF to CRLF when checking out text files. When committing' + #
13 +
615 'text files, CRLF will be converted to LF. For cross-platform projects,' + #
13 +
616 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
624 RdbCRLF
[GC_LFOnly
]:=TRadioButton
.Create(CRLFPage
);
625 with RdbCRLF
[GC_LFOnly
] do begin
626 Parent
:=CRLFPage
.Surface
;
627 Caption
:='Checkout as-is, commit Unix-style line endings';
632 Font
.Style
:=[fsBold
];
636 LblLFOnly
:=TLabel
.Create(CRLFPage
);
637 with LblLFOnly
do begin
638 Parent
:=CRLFPage
.Surface
;
640 'Git will not perform any conversion when checking out text files. When' + #
13 +
641 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #
13 +
642 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
650 RdbCRLF
[GC_CRLFCommitAsIs
]:=TRadioButton
.Create(CRLFPage
);
651 with RdbCRLF
[GC_CRLFCommitAsIs
] do begin
652 Parent
:=CRLFPage
.Surface
;
653 Caption
:='Checkout as-is, commit as-is';
658 Font
.Style
:=[fsBold
];
662 LblCRLFCommitAsIs
:=TLabel
.Create(CRLFPage
);
663 with LblCRLFCommitAsIs
do begin
664 Parent
:=CRLFPage
.Surface
;
666 'Git will not perform any conversions when checking out or committing' + #
13 +
667 'text files. Choosing this option is not recommended for cross-platform' + #
13 +
668 'projects ("core.autocrlf" is set to "false").';
675 // Restore the setting chosen during a previous install
.
676 Data
:=GetPreviousData('CRLF Option','CRLFAlways');
677 if Data
='LFOnly' then begin
678 RdbCRLF
[GC_LFOnly
].Checked
:=True;
679 end else if Data
='CRLFAlways' then begin
680 RdbCRLF
[GC_CRLFAlways
].Checked
:=True;
681 end else if Data
='CRLFCommitAsIs' then begin
682 RdbCRLF
[GC_CRLFCommitAsIs
].Checked
:=True;
686 * Create a custom page for finding the processes that lock a module.
689 ProcessesPage
:=CreateCustomPage(
691 'Replacing in-use files',
692 'The following applications use files that need to be replaced, please close them.'
695 ProcessesListBox
:=TListBox
.Create(ProcessesPage
);
696 with ProcessesListBox
do begin
697 Parent
:=ProcessesPage
.Surface
;
698 Width
:=ProcessesPage
.SurfaceWidth
;
699 Height
:=ProcessesPage
.SurfaceHeight
-ScaleY(8);
702 ProcessesRefresh
:=TNewButton
.Create(WizardForm
);
703 with ProcessesRefresh
do begin
705 Width
:=WizardForm
.CancelButton
.Width
;
706 Height
:=WizardForm
.CancelButton
.Height
;
707 Top
:=WizardForm
.CancelButton
.Top
;
708 Left
:=WizardForm
.ClientWidth
-(WizardForm
.CancelButton
.Left
+WizardForm
.CancelButton
.Width
);
710 OnClick
:=@RefreshProcessList
;
713 // This button
is only used by the uninstaller
.
716 // Initially hide the Refresh button
, show it when the process page becomes current
.
717 ProcessesRefresh
.Hide
;
720 function ShouldSkipPage(PageID
:Integer):Boolean;
722 if (ProcessesPage
<>NIL) and (PageID
=ProcessesPage
.ID
) then begin
723 // This page
is only reached
forward (by pressing
"Next", never by pressing
"Back").
724 RefreshProcessList(NIL);
725 Result
:=(GetArrayLength(Processes
)=0);
731 procedure CurPageChanged(CurPageID
:Integer);
735 if CurPageID
=wpSelectDir
then begin
736 if not IsDirWritable(WizardDirValue
) then begin
737 // If the default directory
is not writable
, choose another default that most likely
is.
738 // This will be checked later again when the user clicks
"Next".
739 WizardForm
.DirEdit
.Text:=ExpandConstant('{userpf}\{#APP_NAME}');
743 // Uncheck the console font option by default
.
744 if CurPageID
=wpSelectComponents
then begin
745 for i
:=0 to WizardForm
.ComponentsList
.Items
.Count
-1 do begin
746 if WizardForm
.ComponentsList
.ItemCaption
[i
]='{#COMP_CONSOLE_FONT}' then begin
747 WizardForm
.ComponentsList
.Checked
[i
]:=False;
753 // Show the
"Refresh" button only on the processes page
.
754 if (ProcessesPage
<>NIL) and (CurPageID
=ProcessesPage
.ID
) then begin
755 ProcessesRefresh
.Show
;
757 ProcessesRefresh
.Hide
;
761 function NextButtonClick(CurPageID
:Integer):Boolean;
764 Version
:TWindowsVersion
;
768 if CurPageID
=wpSelectDir
then begin
769 if not IsDirWritable(WizardDirValue
) then begin
771 'The specified installation directory does not seem to be writable. ' +
772 + 'Please choose another directory or restart setup as a user with sufficient permissions.'
781 if (PuTTYPage
<>NIL) and (CurPageID
=PuTTYPage
.ID
) then begin
782 Result
:=RdbSSH
[GS_OpenSSH
].Checked
or
783 (RdbSSH
[GS_Plink
].Checked
and FileExists(EdtPlink
.Text));
784 if not Result
then begin
785 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError
,MB_OK
);
787 end else if (ProcessesPage
<>NIL) and (CurPageID
=ProcessesPage
.ID
) then begin
788 // It would have been nicer
to just disable the
"Next" button
, but the
789 // WizardForm
exports the button just
read-only
.
790 for i
:=0 to GetArrayLength(Processes
)-1 do begin
791 if not Processes
[i
].Restartable
then begin
792 MsgBox('Setup cannot continue until you close at least those applications in the list that are marked as "closing is required".',mbCriticalError
,MB_OK
);
798 Result
:=(GetArrayLength(Processes
)=0);
800 if not Result
then begin
801 GetWindowsVersionEx(Version
);
802 if Version
.Major
>=6 then begin
804 'If you continue without closing the listed applications they will be closed and restarted automatically.' + #
13 + #
13 +
805 'Are you sure you want to continue?',
811 'If you continue without closing the listed applications you will need to log off and on again before changes take effect.' + #
13 + #
13 +
812 'Are you sure you want to continue anyway?',
821 procedure CurStepChanged(CurStep
:TSetupStep
);
823 AppDir
,DllPath
,FileName
,TempName
,Cmd
,Msg
:String;
824 BuiltIns
,ImageNames
,EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
830 if CurStep
=ssInstall
then begin
831 // Shutdown locking processes just before the actual installation starts
.
832 if SessionHandle
>0 then try
833 RmShutdown(SessionHandle
,RmShutdownOnlyRegistered
,0);
835 Log('Line {#__LINE__}: RmShutdown not supported.');
841 // Make sure the code below
is only executed just after the actual installation finishes
.
842 if CurStep
<>ssPostInstall
then begin
846 AppDir
:=ExpandConstant('{app}');
849 Bind the imported function addresses
853 DllPath
:=ExpandConstant('{app}\bin;{sys}');
855 // Load the list
of images from a
text file.
856 FileName
:=AppDir
+'\{#APP_BINDIMAGE}';
857 if LoadStringsFromFile(FileName
,ImageNames
) then begin
858 Count
:=GetArrayLength(ImageNames
)-1;
859 for i
:=0 to Count
do begin
860 FileName
:=AppDir
+'\'+ImageNames[i];
861 if not BindImageEx(BIND_NO_BOUND_IMPORTS or BIND_CACHE_IMPORT_DLLS,FileName,DllPath,'',0) then begin
862 Log('Line
{#__LINE__}: Error calling BindImageEx
for "'+FileName+'".');
867 Log('Line
{#__LINE__}: An exception occurred
while calling BindImageEx
.');
874 // Load the built-ins from a text file.
875 FileName:=AppDir+'\
{#APP_BUILTINS}';
876 if LoadStringsFromFile(FileName,BuiltIns) then begin
877 Count:=GetArrayLength(BuiltIns)-1;
879 // Delete those scripts from "bin" which have been replaced by built-ins in "libexec\git-core".
880 for i:=0 to Count do begin
881 FileName:=AppDir+'\bin
\'+ChangeFileExt(ExtractFileName(BuiltIns
[i
]),'');
882 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
883 Log('Line {#__LINE__}: Unable to delete script "'+FileName
+'", ignoring.');
887 // Create built
-ins
as aliases
for git
.exe
.
888 for i
:=0 to Count
do begin
889 FileName
:=AppDir
+'\'+BuiltIns[i];
891 // Delete any existing built-in.
892 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
893 Log('Line
{#__LINE__}: Unable
to delete existing built
-in "'+FileName+'", skipping
.');
898 // This will throw an exception on pre-Win2k systems.
899 LinkCreated:=CreateHardLink(FileName,AppDir+'\bin\git
.exe
',0);
902 Log('Line
{#__LINE__}: Creating hardlink
"'+FileName+'" failed
, will
try a copy
.');
905 if not LinkCreated then begin
906 if not FileCopy(AppDir+'\bin\git
.exe
',FileName,False) then begin
907 Log('Line
{#__LINE__}: Creating copy
"'+FileName+'" failed
, giving up
.');
908 // This is not a critical error, Git could basically be used without the
909 // aliases for built-ins, so we continue.
914 // Delete any duplicate files in case we are updating from a non-libexec to a libexec directory layout.
915 if FindFirst(AppDir+'\libexec\git
-core\
*',FindRec) then begin
917 if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY)=0 then begin
918 FileName:=AppDir+'\bin
\'+FindRec
.name
;
919 if (Pos(FindRec
.name
,'git.exe')<>1) and FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
920 Log('Line {#__LINE__}: Unable to delete dupe "'+FileName
+'", ignoring.');
923 until not FindNext(FindRec
);
927 Msg
:='Line {#__LINE__}: Unable to read file "{#APP_BUILTINS}".';
928 MsgBox(Msg
,mbError
,MB_OK
);
930 // This
is not a critical error
, Git could basically be used without the
931 // aliases
for built
-ins
, so we continue
.
938 if RdbCRLF
[GC_LFOnly
].checked
then begin
939 Cmd
:='core.autocrlf input';
940 end else if RdbCRLF
[GC_CRLFAlways
].checked
then begin
941 Cmd
:='core.autocrlf true';
943 Cmd
:='core.autocrlf false';
945 if not Exec(AppDir
+ '\bin\git.exe', 'config -f gitconfig ' + Cmd
,
946 AppDir
+ '\etc', SW_HIDE
, ewWaitUntilTerminated
, i
) then begin
947 Msg
:='Unable to configure the line ending conversion: ' + Cmd
;
948 MsgBox(Msg
,mbError
,MB_OK
);
950 // This
is not a critical error
, the user can probably fix it manually
,
955 Modify the environment
957 This must happen no later than ssPostInstall to make
958 "ChangesEnvironment=yes" not happend before the change!
961 FileName
:=AppDir
+'\setup.ini';
963 // Delete GIT_SSH
and SVN_SSH
if a previous installation
set them (this
is required
for the GS_OpenSSH
case).
964 EnvSSH
:=GetEnvStrings('GIT_SSH',IsAdminLoggedOn
);
965 if (GetArrayLength(EnvSSH
)=1) and
966 (CompareStr(RemoveQuotes(EnvSSH
[0]),GetIniString('Environment','GIT_SSH','',FileName
))=0) then begin
967 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn
,True,[]) then begin
968 Msg
:='Line {#__LINE__}: Unable to reset GIT_SSH prior to install.';
969 MsgBox(Msg
,mbError
,MB_OK
);
971 // This
is not a critical error
, the user can probably fix it manually
,
976 EnvSSH
:=GetEnvStrings('SVN_SSH',IsAdminLoggedOn
);
977 if (GetArrayLength(EnvSSH
)=1) and
978 (CompareStr(RemoveQuotes(EnvSSH
[0]),GetIniString('Environment','SVN_SSH','',FileName
))=0) then begin
979 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn
,True,[]) then begin
980 Msg
:='Line {#__LINE__}: Unable to reset SVN_SSH prior to install.';
981 MsgBox(Msg
,mbError
,MB_OK
);
983 // This
is not a critical error
, the user can probably fix it manually
,
988 if (PuTTYPage
<>NIL) and RdbSSH
[GS_Plink
].Checked
then begin
989 SetArrayLength(EnvSSH
,1);
990 EnvSSH
[0]:=EdtPlink
.Text;
992 // Set GIT_SSH
as specified by the user
.
993 if not SetEnvStrings('GIT_SSH',IsAdminLoggedOn
,True,EnvSSH
) then begin
994 Msg
:='Line {#__LINE__}: Unable to set the GIT_SSH environment variable.';
995 MsgBox(Msg
,mbError
,MB_OK
);
997 // This
is not a critical error
, the user can probably fix it manually
,
1001 // Mark that we have changed GIT_SSH by writing its value
to a
file.
1002 if not SetIniString('Environment','GIT_SSH',EnvSSH
[0],FileName
) then begin
1003 Msg
:='Line {#__LINE__}: Unable to write to file "'+FileName
+'".';
1004 MsgBox(Msg
,mbError
,MB_OK
);
1006 // This
is not a critical error
, though uninstall
/ reinstall will probably
not run cleanly
,
1010 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn
,True,EnvSSH
) then begin
1011 Msg
:='Line {#__LINE__}: Unable to set the SVN_SSH environment variable.';
1012 MsgBox(Msg
,mbError
,MB_OK
);
1014 // This
is not a critical error
, the user can probably fix it manually
,
1018 // Mark that we have changed SVN_SSH by writing its value
to a
file.
1019 if not SetIniString('Environment','SVN_SSH',EnvSSH
[0],FileName
) then begin
1020 Msg
:='Line {#__LINE__}: Unable to write to file "'+FileName
+'".';
1021 MsgBox(Msg
,mbError
,MB_OK
);
1023 // This
is not a critical error
, though uninstall
/ reinstall will probably
not run cleanly
,
1028 // Get the current user
's directories in PATH.
1029 EnvPath:=GetEnvStrings('PATH
',IsAdminLoggedOn);
1031 // First, remove the installation directory from PATH in any case.
1032 for i:=0 to GetArrayLength(EnvPath)-1 do begin
1033 if Pos(AppDir+'\',EnvPath
[i
]+'\')=1 then begin
1038 // Delete HOME if a previous installation modified it.
1039 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
1040 if (GetArrayLength(EnvHome)=1) and
1041 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment
','HOME
','',FileName))=0) then begin
1042 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,[]) then begin
1043 Msg:='Line
{#__LINE__}: Unable
to reset HOME prior
to install
.';
1044 MsgBox(Msg,mbError,MB_OK);
1046 // This is not a critical error, the user can probably fix it manually,
1051 // Modify the PATH variable as requested by the user.
1052 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
1053 i:=GetArrayLength(EnvPath);
1054 SetArrayLength(EnvPath,i+1);
1056 // List \cmd before \bin so \cmd has higher priority and programs in
1057 // there will be called in favor of those in \bin.
1058 EnvPath[i]:=AppDir+'\cmd
';
1060 if RdbPath[GP_CmdTools].Checked then begin
1061 SetArrayLength(EnvPath,i+2);
1062 EnvPath[i+1]:=AppDir+'\bin
';
1064 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
1065 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
1066 i:=GetArrayLength(EnvHome);
1067 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
1068 SetArrayLength(EnvHome,1);
1069 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
1070 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,EnvHome) then begin
1071 Msg:='Line
{#__LINE__}: Unable
to set the HOME environment variable
.';
1072 MsgBox(Msg,mbError,MB_OK);
1074 // This is not a critical error, the user can probably fix it manually,
1078 // Mark that we have changed HOME.
1079 if not SetIniString('Environment
','HOME
',EnvHome[0],FileName) then begin
1080 Msg:='Line
{#__LINE__}: Unable
to write
to file "'+FileName+'".';
1081 MsgBox(Msg,mbError,MB_OK);
1083 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
1090 // Set the current user's PATH directories
.
1091 if not SetEnvStrings('PATH',IsAdminLoggedOn
,True,EnvPath
) then begin
1092 Msg
:='Line {#__LINE__}: Unable to set the PATH environment variable.';
1093 MsgBox(Msg
,mbError
,MB_OK
);
1095 // This
is not a critical error
, the user can probably fix it manually
,
1100 Create shortcuts that need to be created regardless of the "Don't create a Start Menu folder" toggle
1103 Cmd
:=ExpandConstant('{syswow64}\cmd.exe');
1104 TempName
:='/c ""'+AppDir
+'\bin\sh.exe" --login -i"';
1105 FileName
:=AppDir
+'\etc\git.ico';
1107 if IsComponentSelected('icons\quicklaunch') then begin
1109 ExpandConstant('{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash.lnk')
1113 , '%HOMEDRIVE%%HOMEPATH%'
1119 if IsComponentSelected('icons\desktop') then begin
1121 GetShellFolder('desktop')+'\Git Bash.lnk'
1125 , '%HOMEDRIVE%%HOMEPATH%'
1132 // Create a special shortcut that does
not set a working
directory (Note
: Since Inno Setup
5.3.11,
1133 // passing an empty WorkingDir gets replaced
with {sys}, so use
'.' instead
).
1134 // This shortcut
is used by
"Git Bash.vbs", which
in turn
is run by the
"Git Bash Here" shell extension
.
1136 AppDir
+'\Git Bash.lnk'
1147 Create the Windows Explorer integrations
1150 if IsAdminLoggedOn
then begin
1151 RootKey
:=HKEY_LOCAL_MACHINE
;
1153 RootKey
:=HKEY_CURRENT_USER
;
1156 if IsComponentSelected('ext\reg\shellhere') then begin
1157 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
1158 (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','','"'+ExpandConstant('{syswow64}')+'\wscript" "'+AppDir
+'\Git Bash.vbs" "%1"')) then begin
1159 Msg
:='Line {#__LINE__}: Unable to create "Git Bash Here" shell extension.';
1160 MsgBox(Msg
,mbError
,MB_OK
);
1162 // This
is not a critical error
, the user can probably fix it manually
,
1167 if IsComponentSelected('ext\reg\guihere') then begin
1168 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
1169 (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
1170 Msg
:='Line {#__LINE__}: Unable to create "Git GUI Here" shell extension.';
1171 MsgBox(Msg
,mbError
,MB_OK
);
1173 // This
is not a critical error
, the user can probably fix it manually
,
1178 // It
is either the Registry
-based context menu entries
, or the shell extension
.
1179 if IsComponentSelected('ext\cheetah') then begin
1180 DeleteContextMenuEntries
;
1182 if isWin64
then begin
1183 FileName
:=AppDir
+'\git-cheetah\git_shell_ext64.dll';
1185 FileName
:=AppDir
+'\git-cheetah\git_shell_ext.dll';
1187 if not ReplaceInUseFile(FileName
,FileName
+'.new',True) then begin
1188 Log('Line {#__LINE__}: Replacing file "'+FileName
+'" failed.');
1193 Restart any processes that were shut down via the Restart Manager
1196 if SessionHandle
>0 then try
1197 RmRestart(SessionHandle
,0,0);
1198 RmEndSession(SessionHandle
);
1200 Log('Line {#__LINE__}: RmRestart not supported.');
1204 procedure RegisterPreviousData(PreviousDataKey
:Integer);
1208 // Git Path options
.
1210 if RdbPath
[GP_BashOnly
].Checked
then begin
1212 end else if RdbPath
[GP_Cmd
].Checked
then begin
1214 end else if RdbPath
[GP_CmdTools
].Checked
then begin
1217 SetPreviousData(PreviousDataKey
,'Path Option',Data
);
1221 if (PuTTYPage
=NIL) or RdbSSH
[GS_OpenSSH
].Checked
then begin
1223 end else if RdbSSH
[GS_Plink
].Checked
then begin
1226 SetPreviousData(PreviousDataKey
,'SSH Option',Data
);
1228 // Line ending conversion options
.
1230 if RdbCRLF
[GC_LFOnly
].Checked
then begin
1232 end else if RdbCRLF
[GC_CRLFAlways
].Checked
then begin
1234 end else if RdbCRLF
[GC_CRLFCommitAsIs
].Checked
then begin
1235 Data
:='CRLFCommitAsIs';
1237 SetPreviousData(PreviousDataKey
,'CRLF Option',Data
);
1244 function InitializeUninstall
:Boolean;
1248 ExitButton
,RefreshButton
:TButton
;
1252 Form
:=CreateCustomForm
;
1254 Form
.Caption
:='Git Uninstall: Removing in-use files';
1255 Form
.ClientWidth
:=ScaleX(500);
1256 Form
.ClientHeight
:=ScaleY(256);
1259 Info
:=TLabel
.Create(Form
);
1265 Caption
:='The following applications use files that need to be removed, please close them.';
1268 ContinueButton
:=TButton
.Create(Form
);
1269 with ContinueButton
do begin
1271 Left
:=Form
.ClientWidth
-ScaleX(75+10);
1272 Top
:=Form
.ClientHeight
-ScaleY(23+10);
1275 Caption
:='Continue';
1279 ExitButton
:=TButton
.Create(Form
);
1280 with ExitButton
do begin
1282 Left
:=ContinueButton
.Left
-ScaleX(75+6);
1283 Top
:=ContinueButton
.Top
;
1287 ModalResult
:=mrCancel
;
1291 RefreshButton
:=TButton
.Create(Form
);
1292 with RefreshButton
do begin
1295 Top
:=ExitButton
.Top
;
1299 OnClick
:=@RefreshProcessList
;
1302 ProcessesListBox
:=TListBox
.Create(Form
);
1303 with ProcessesListBox
do begin
1306 Top
:=Info
.Top
+Info
.Height
+11;
1307 Width
:=Form
.ClientWidth
-ScaleX(11*2);
1308 Height
:=ContinueButton
.Top
-ScaleY(11*4);
1311 Form
.ActiveControl
:=ContinueButton
;
1313 RefreshProcessList(NIL);
1314 if GetArrayLength(Processes
)>0 then begin
1315 // Now that these dialogs are going
to be shown
, we should probably
1316 // disable the
"Are you sure to remove Git?" confirmation dialog
, but
1317 // unfortunately that
is not possible
with Inno Setup currently
.
1318 Result
:=(Form
.ShowModal()=mrOk
);
1320 // Note
: The number
of processes might have changed during a refresh
.
1321 if Result
and (GetArrayLength(Processes
)>0) then begin
1323 'If you continue without closing the listed applications, you will need to log off and on again to remove some files manually.' + #
13 + #
13 +
1324 'Are you sure you want to continue anyway?',
1337 // Even though the name
of this
function suggests otherwise most
of the
1338 // code below
is only executed right before the actual uninstallation
.
1339 // This happens because
of the
if-guard right
in the beginning
of this
1341 procedure CurUninstallStepChanged(CurUninstallStep
:TUninstallStep
);
1343 AppDir
,FileName
,Msg
:String;
1344 EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
1347 if CurUninstallStep
<>usUninstall
then begin
1351 // Reset the console
font (the FontType
is reset
in the Registry section
).
1352 if IsComponentInstalled('consolefont') then begin
1353 if MsgBox('Do you want to revert the TrueType font setting for all console windows?',mbConfirmation
,MB_YESNO
)=IDYES
then begin
1354 RegWriteDWordValue(HKEY_CURRENT_USER
,'Console','FontFamily',0);
1355 RegWriteDWordValue(HKEY_CURRENT_USER
,'Console','FontSize',0);
1356 RegWriteDWordValue(HKEY_CURRENT_USER
,'Console','FontWeight',0);
1361 Modify the environment
1363 This must happen no later than usUninstall to make
1364 "ChangesEnvironment=yes" not happend before the change!
1367 AppDir
:=ExpandConstant('{app}');
1368 FileName
:=AppDir
+'\setup.ini';
1370 // Delete the current user
's GIT_SSH and SVN_SSH if we set it.
1371 EnvSSH:=GetEnvStrings('GIT_SSH
',IsAdminLoggedOn);
1372 if (GetArrayLength(EnvSSH)=1) and
1373 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','GIT_SSH
','',FileName))=0) then begin
1374 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,[]) then begin
1375 Msg:='Line
{#__LINE__}: Unable
to revert any possible changes
to GIT_SSH
.';
1376 MsgBox(Msg,mbError,MB_OK);
1378 // This is not a critical error, the user can probably fix it manually,
1383 EnvSSH:=GetEnvStrings('SVN_SSH
',IsAdminLoggedOn);
1384 if (GetArrayLength(EnvSSH)=1) and
1385 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','SVN_SSH
','',FileName))=0) then begin
1386 if not SetEnvStrings('SVN_SSH
',IsAdminLoggedOn,True,[]) then begin
1387 Msg:='Line
{#__LINE__}: Unable
to revert any possible changes
to SVN_SSH
.';
1388 MsgBox(Msg,mbError,MB_OK);
1390 // This is not a critical error, the user can probably fix it manually,
1395 // Get the current user's directories
in PATH
.
1396 EnvPath
:=GetEnvStrings('PATH',IsAdminLoggedOn
);
1398 // Remove the installation directory from PATH
in any
case, even
if it
1399 // was
not added by the installer
.
1400 for i
:=0 to GetArrayLength(EnvPath
)-1 do begin
1401 if Pos(AppDir
+'\',EnvPath[i]+'\')=1 then begin
1406 // Reset the current user
's directories in PATH.
1407 if not SetEnvStrings('PATH
',IsAdminLoggedOn,True,EnvPath) then begin
1408 Msg:='Line
{#__LINE__}: Unable
to revert any possible changes
to PATH
.';
1409 MsgBox(Msg,mbError,MB_OK);
1411 // This is not a critical error, the user can probably fix it manually,
1415 // Reset the current user's HOME
if we modified it
.
1416 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
1417 if (GetArrayLength(EnvHome
)=1) and
1418 (CompareStr(RemoveQuotes(EnvHome
[0]),GetIniString('Environment','HOME','',FileName
))=0) then begin
1419 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,[]) then begin
1420 Msg
:='Line {#__LINE__}: Unable to revert any possible changes to HOME.';
1421 MsgBox(Msg
,mbError
,MB_OK
);
1423 // This
is not a critical error
, the user can probably fix it manually
,
1428 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
1429 Msg
:='Line {#__LINE__}: Unable to delete file "'+FileName
+'".';
1430 MsgBox(Msg
,mbError
,MB_OK
);
1432 // This
is not a critical error
, the user can probably fix it manually
,
1437 Delete the Windows Explorer integrations
1440 DeleteContextMenuEntries
;
1442 if isWin64
then begin
1443 FileName
:=AppDir
+'\git-cheetah\git_shell_ext64.dll';
1445 FileName
:=AppDir
+'\git-cheetah\git_shell_ext.dll';
1447 if FileExists(FileName
) then begin
1448 if not UnregisterServer(Is64BitInstallMode
,FileName
,False) then begin
1449 Msg
:='Line {#__LINE__}: Unable to unregister file "'+FileName
+'". Please do it manually by running "regsvr32 /u '+ExtractFileName(FileName
)+'".';
1450 MsgBox(Msg
,mbError
,MB_OK
);
1454 if not DeleteFile(FileName
) then begin
1455 Msg
:='Line {#__LINE__}: Unable to delete file "'+FileName
+'". Please do it manually after logging off and on again.';
1456 MsgBox(Msg
,mbError
,MB_OK
);