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 InfoAfterFile
=ReleaseNotes
.rtf
24 LicenseFile
=gpl
-2.0.rtf
25 PrivilegesRequired
=none
26 UninstallDisplayIcon
=etc\git
.ico
29 SetupIconFile
=etc\git
.ico
30 WizardSmallImageFile
=git
.bmp
33 Name
: quicklaunchicon; Description
: "Create a &Quick Launch icon"; GroupDescription
: "Additional icons:"; Flags
: checkedonce
34 Name
: desktopicon; Description
: "Create a &Desktop icon"; GroupDescription
: "Additional icons:"; Flags
: checkedonce
35 Name
: shellextension
; Description
: "Add ""Git Ba&sh Here"""; GroupDescription
: "Windows Explorer integration:"; Flags
: checkedonce
36 Name
: guiextension
; Description
: "Add ""Git &GUI Here"""; GroupDescription
: "Windows Explorer integration:"; Flags
: checkedonce
39 Source
: "*"; DestDir
: "{app}"; Excludes
: "\*.bmp, gpl-2.0.rtf, \install.*, \tmp.*, \bin\*install*"; Flags
: recursesubdirs
42 Name
: "{group}\Git GUI"; Filename
: "{app}\bin\wish.exe"; Parameters
: """{app}\bin\git-gui"""; WorkingDir
: "%USERPROFILE%"; IconFilename
: "{app}\etc\git.ico"
43 Name
: "{group}\Git Bash"; Filename
: "{syswow64}\cmd.exe"; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: "%USERPROFILE%"; IconFilename
: "{app}\etc\git.ico"
44 Name
: "{group}\Uninstall Git"; Filename
: "{uninstallexe}"
45 Name
: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash"; Filename
: "{syswow64}\cmd.exe"; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: "%USERPROFILE%"; IconFilename
: "{app}\etc\git.ico"; Tasks
: quicklaunchicon
46 Name
: "{code:GetShellFolder|desktop}\Git Bash"; Filename
: "{syswow64}\cmd.exe"; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: "%USERPROFILE%"; IconFilename
: "{app}\etc\git.ico"; Tasks
: desktopicon
49 BeveledLabel
={#emit APP_URL}
52 Type: files; Name
: "{app}\bin\git-*.exe"
53 Type: dirifempty; Name
: "{app}\home\{username}"
54 Type: dirifempty; Name
: "{app}\home"
61 function GetShellFolder(Param
:string):string;
63 if IsAdminLoggedOn
then begin
64 Param
:='{common'+Param
+'}';
66 Param
:='{user'+Param
+'}';
68 Result
:=ExpandConstant(Param
);
71 function CreateHardLink(lpFileName
,lpExistingFileName
:string;lpSecurityAttributes
:Integer):Boolean;
72 external 'CreateHardLinkA@Kernel32.dll';
74 function GetEnvStrings(VarName
:string;AllUsers
:Boolean):TArrayOfString
;
82 // See http
://www
.jrsoftware
.org
/isfaq
.php#env
83 if AllUsers
then begin
84 // We ignore errors here
. The resulting
array of strings will be empty
.
85 RegQueryStringValue(HKEY_LOCAL_MACHINE
,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName
,Path
);
87 // We ignore errors here
. The resulting
array of strings will be empty
.
88 RegQueryStringValue(HKEY_CURRENT_USER
,'Environment',VarName
,Path
);
91 // Make sure we have at least one semicolon
.
94 // Split the directories
in PATH into an
array of strings
.
96 SetArrayLength(Result
,0);
100 SetArrayLength(Result
,i
+1);
102 Result
[i
]:=Copy(Path
,1,p
-1);
105 Path
:=Copy(Path
,p
+1,Length(Path
));
110 function SetEnvStrings(VarName
:string;AllUsers
,DeleteIfEmpty
:Boolean;DirStrings
:TArrayOfString
):Boolean;
115 // Merge all non
-empty directory strings into a PATH variable
.
117 for i
:=0 to GetArrayLength(DirStrings
)-1 do begin
118 if Length(DirStrings
[i
])>0 then begin
119 if Length(Path
)>0 then begin
120 Path
:=Path
+';'+DirStrings
[i
];
127 // See http
://www
.jrsoftware
.org
/isfaq
.php#env
128 if AllUsers
then begin
129 KeyName
:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
130 if DeleteIfEmpty
and (Length(Path
)=0) then begin
131 Result
:=(not RegValueExists(HKEY_LOCAL_MACHINE
,KeyName
,VarName
))
132 or RegDeleteValue(HKEY_LOCAL_MACHINE
,KeyName
,VarName
);
134 Result
:=RegWriteStringValue(HKEY_LOCAL_MACHINE
,KeyName
,VarName
,Path
);
137 KeyName
:='Environment';
138 if DeleteIfEmpty
and (Length(Path
)=0) then begin
139 Result
:=(not RegValueExists(HKEY_CURRENT_USER
,KeyName
,VarName
))
140 or RegDeleteValue(HKEY_CURRENT_USER
,KeyName
,VarName
);
142 Result
:=RegWriteStringValue(HKEY_CURRENT_USER
,KeyName
,VarName
,Path
);
153 RdbGitBash
,RdbGitCmd
,RdbGitCmdTools
:TRadioButton
;
155 procedure InitializeWizard
;
157 LblGitBash
,LblGitCmd
,LblGitCmdTools
,LblGitCmdToolsWarn
:TLabel
;
159 // Create a custom page
for modifying the environment
.
160 EnvPage
:=CreateCustomPage(
162 'Adjusting your PATH environment',
163 'How would you like to use Git from the command line?'
167 RdbGitBash
:=TRadioButton
.Create(EnvPage
);
168 with RdbGitBash
do begin
169 Parent
:=EnvPage
.Surface
;
170 Caption
:='Use Git Bash only';
175 Font
.Style
:=[fsBold
];
179 LblGitBash
:=TLabel
.Create(EnvPage
);
180 with LblGitBash
do begin
181 Parent
:=EnvPage
.Surface
;
183 'This is the most conservative choice if you are concerned about the' + #
13 +
184 'stability of your system. Your PATH will not be modified.';
192 RdbGitCmd
:=TRadioButton
.Create(EnvPage
);
193 with RdbGitCmd
do begin
194 Parent
:=EnvPage
.Surface
;
195 Caption
:='Run Git from the Windows Command Prompt';
200 Font
.Style
:=[fsBold
];
203 LblGitCmd
:=TLabel
.Create(EnvPage
);
204 with LblGitCmd
do begin
205 Parent
:=EnvPage
.Surface
;
207 'This option is considered safe and no conflicts with other tools are' + #
13 +
208 'known. Only Git will be added to your PATH.';
216 RdbGitCmdTools
:=TRadioButton
.Create(EnvPage
);
217 with RdbGitCmdTools
do begin
218 Parent
:=EnvPage
.Surface
;
219 Caption
:='Run Git and included Unix tools from the Windows Command Prompt';
224 Font
.Style
:=[fsBold
];
227 LblGitCmdTools
:=TLabel
.Create(EnvPage
);
228 with LblGitCmdTools
do begin
229 Parent
:=EnvPage
.Surface
;
230 Caption
:='Both Git and the Unix tools will be added to your PATH.';
236 LblGitCmdToolsWarn
:=TLabel
.Create(EnvPage
);
237 with LblGitCmdToolsWarn
do begin
238 Parent
:=EnvPage
.Surface
;
240 'Warning: This will override Windows tools like find.exe and' + #
13 +
241 'sort.exe. Select this option only if you understand the implications.';
247 Font
.Style
:=[fsBold
];
251 procedure CurStepChanged(CurStep
:TSetupStep
);
253 AppDir
,FileName
,Cmd
,Msg
:string;
254 BuiltIns
,EnvPath
,EnvHome
:TArrayOfString
;
259 if CurStep
<>ssPostInstall
then begin
263 AppDir
:=ExpandConstant('{app}');
269 // Load the built
-ins from a
text file.
270 FileName
:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}');
271 if LoadStringsFromFile(FileName,BuiltIns) then begin
272 // Check if we are running on NTFS.
274 if SetNTFSCompression(AppDir+'\bin\git
.exe
',true) then begin
275 IsNTFS:=SetNTFSCompression(AppDir+'\bin\git
.exe
',false);
278 Count:=GetArrayLength(BuiltIns)-1;
280 // Map the built-ins to git.exe.
282 Log('Line
{#emit __LINE__}: Assuming the partition
is formatted using NTFS
.');
284 for i:=0 to Count do begin
285 FileName:=AppDir+'\'+BuiltIns
[i
];
287 // On non
-NTFS partitions
, create hard links
.
288 if (not DeleteFile(FileName
))
289 or (not CreateHardLink(FileName
,AppDir
+'\bin\git.exe',0)) then begin
290 Log('Line {#emit __LINE__}: Unable to create hard link "'+FileName
+'", will try to copy files.');
297 // The fallback
is to copy the
files.
298 if not IsNTFS
then begin
299 for i
:=0 to Count
do begin
300 FileName
:=AppDir
+'\'+BuiltIns[i];
302 // On non-NTFS partitions, copy simply the files (overwriting existing ones).
303 if not FileCopy(AppDir+'\bin\git
.exe
',FileName,false) then begin
304 Msg:='Line
{#emit __LINE__}: Unable
to create built
-in "'+FileName+'".';
305 MsgBox(Msg,mbError,MB_OK);
307 // This is not a critical error, Git could basically be used without the
308 // aliases for built-ins, so we continue.
313 Msg:='Line
{#emit __LINE__}: Unable
to read file "{#emit APP_BUILTINS}".';
314 MsgBox(Msg,mbError,MB_OK);
316 // This is not a critical error, Git could basically be used without the
317 // aliases for built-ins, so we continue.
322 Modify the environment
324 This must happen no later than ssPostInstall to make
325 "ChangesEnvironment=yes" not happend before the change!
328 // Get the current user's directories
in PATH
.
329 EnvPath
:=GetEnvStrings('PATH',IsAdminLoggedOn
);
331 // First
, remove the installation directory from PATH
in any
case.
332 for i
:=0 to GetArrayLength(EnvPath
)-1 do begin
333 if Pos(AppDir
,EnvPath
[i
])=1 then begin
338 // Delete HOME
if a previous installation modified it
.
339 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
340 if (GetArrayLength(EnvHome
)=1) and
341 (CompareStr(EnvHome
[0],GetIniString('Environment','HOME','',AppDir
+'\setup.ini'))=0) then begin
342 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,[]) then begin
343 Msg
:='Line {#emit __LINE__}: Unable to reset HOME prior to install.';
344 MsgBox(Msg
,mbError
,MB_OK
);
346 // This
is not a critical error
, the user can probably fix it manually
,
351 // Modify the PATH variable
as requested by the user
.
352 if RdbGitCmd
.Checked
or RdbGitCmdTools
.Checked
then begin
353 i
:=GetArrayLength(EnvPath
);
354 SetArrayLength(EnvPath
,i
+1);
356 // List \cmd before
\bin so \cmd has higher priority
and programs
in
357 // there will be called
in favor
of those
in \bin
.
358 EnvPath
[i
]:=ExpandConstant('{app}\cmd');
360 if RdbGitCmdTools
.Checked
then begin
361 SetArrayLength(EnvPath
,i
+2);
362 EnvPath
[i
+1]:=ExpandConstant('{app}\bin');
364 // Set HOME
for the Windows Command Prompt
.
365 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
366 i
:=GetArrayLength(EnvHome
);
367 if (i
=0) or ((i
=1) and (Length(EnvHome
[0])=0)) then begin
368 SetArrayLength(EnvHome
,1);
369 EnvHome
[0]:=ExpandConstant('{%USERPROFILE}');
370 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,EnvHome
) then begin
371 Msg
:='Line {#emit __LINE__}: Unable to set the HOME environment variable.';
372 MsgBox(Msg
,mbError
,MB_OK
);
374 // This
is not a critical error
, the user can probably fix it manually
,
378 // Mark that we have changed HOME
.
379 FileName
:=AppDir
+'\setup.ini';
380 if not SetIniString('Environment','HOME',EnvHome
[0],FileName
) then begin
381 Msg
:='Line {#emit __LINE__}: Unable to write to file "'+FileName
+'".';
382 MsgBox(Msg
,mbError
,MB_OK
);
384 // This
is not a critical error
, though uninstall
/ reinstall will probably
not run cleanly
,
391 // Set the current user
's PATH directories.
392 if not SetEnvStrings('PATH
',IsAdminLoggedOn,True,EnvPath) then begin
393 Msg:='Line
{#emit __LINE__}: Unable
to set the PATH environment variable
.';
394 MsgBox(Msg,mbError,MB_OK);
396 // This is not a critical error, the user can probably fix it manually,
401 Create the Windows Explorer shell extensions
404 if IsAdminLoggedOn then begin
405 RootKey:=HKEY_LOCAL_MACHINE;
407 RootKey:=HKEY_CURRENT_USER;
410 if IsTaskSelected('shellextension
') then begin
411 Cmd:=ExpandConstant('"{syswow64}\cmd.exe"');
412 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell
','','Git Ba
&sh Here
'))
413 or (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command
','',Cmd+' /c
"pushd "%1" && "'+AppDir+'\bin\sh
.exe
" --login -i"')) then begin
414 Msg:='Line
{#emit __LINE__}: Unable
to create
"Git Bash Here" shell extension
.';
415 MsgBox(Msg,mbError,MB_OK);
417 // This is not a critical error, the user can probably fix it manually,
422 if IsTaskSelected('guiextension
') then begin
423 if (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui
','','Git
&GUI Here
'))
424 or (not RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command
','','"'+AppDir+'\bin\wish.exe" "'+AppDir+'\bin\git-gui" "--working-dir" "%1"')) then begin
425 Msg:='Line
{#emit __LINE__}: Unable
to create
"Git GUI Here" shell extension
.';
426 MsgBox(Msg,mbError,MB_OK);
428 // This is not a critical error, the user can probably fix it manually,
438 function InitializeUninstall:Boolean;
440 FileName,NewName,Msg:string;
442 FileName:=ExpandConstant('{app}')+'\bin\ssh
-agent
.exe
';
443 if FileExists(FileName) then begin
444 // Create a temporary copy of the file we try to delete.
445 NewName:=FileName+'.'+IntToStr(1000+Random(9000));
446 Result:=FileCopy(FileName,NewName,True) and DeleteFile(FileName);
448 if not Result then begin
449 Msg:='Line
{#emit __LINE__}: Please stop all ssh
-agent processes
and run uninstall again
.';
450 MsgBox(Msg,mbError,MB_OK);
453 // Clean-up the temporary copy (ignoring any errors).
456 // Clean-up the temporary copy (ignoring any errors).
457 RenameFile(NewName,FileName);
464 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
466 AppDir,Command,Msg:string;
467 EnvPath,EnvHome:TArrayOfString;
471 if CurUninstallStep<>usUninstall then begin
476 Modify the environment
478 This must happen no later than usUninstall to make
479 "ChangesEnvironment=yes" not happend before the change!
482 AppDir:=ExpandConstant('{app}');
484 // Get the current user's directories
in PATH
.
485 EnvPath
:=GetEnvStrings('PATH',IsAdminLoggedOn
);
487 // Remove the installation directory from PATH
in any
case, even
if it
488 // was
not added by the installer
.
489 for i
:=0 to GetArrayLength(EnvPath
)-1 do begin
490 if Pos(AppDir
,EnvPath
[i
])=1 then begin
495 // Reset the current user
's directories in PATH.
496 if not SetEnvStrings('PATH
',IsAdminLoggedOn,True,EnvPath) then begin
497 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to PATH
.';
498 MsgBox(Msg,mbError,MB_OK);
500 // This is not a critical error, the user can probably fix it manually,
504 // Reset the current user's HOME
if we modified it
.
505 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
506 if (GetArrayLength(EnvHome
)=1) and
507 (CompareStr(EnvHome
[0],GetIniString('Environment','HOME','',AppDir
+'\setup.ini'))=0) then begin
508 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,[]) then begin
509 Msg
:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
510 MsgBox(Msg
,mbError
,MB_OK
);
512 // This
is not a critical error
, the user can probably fix it manually
,
517 Command
:=AppDir
+'\setup.ini';
518 if not DeleteFile(Command
) then begin
519 Msg
:='Line {#emit __LINE__}: Unable to delete file "'+Command
+'".';
520 MsgBox(Msg
,mbError
,MB_OK
);
522 // This
is not a critical error
, the user can probably fix it manually
,
527 Delete the Windows Explorer shell extensions
530 if IsAdminLoggedOn
then begin
531 RootKey
:=HKEY_LOCAL_MACHINE
;
533 RootKey
:=HKEY_CURRENT_USER
;
537 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command
);
538 if Pos(AppDir
,Command
)>0 then begin
539 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
540 Msg
:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
541 MsgBox(Msg
,mbError
,MB_OK
);
543 // This
is not a critical error
, the user can probably fix it manually
,
549 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command
);
550 if Pos(AppDir
,Command
)>0 then begin
551 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
552 Msg
:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
553 MsgBox(Msg
,mbError
,MB_OK
);
555 // This
is not a critical error
, the user can probably fix it manually
,