2 #define APP_VERSION
'%APPVERSION%'
3 #define APP_URL
'http://msysgit.googlecode.com/'
4 #define APP_BUILTINS
'etc\fileList-builtins.txt'
8 Compression
=lzma2
/ultra
9 LZMAUseSeparateProcess
=yes
10 OutputBaseFilename
={#emit APP_NAME+'-'+APP_VERSION}
14 ; Uncomment the line below to be able to compile the script from within the IDE.
15 ;SourceDir={#GetEnv('TEMP')}\WinGit
19 AppName
={#emit APP_NAME}
20 AppPublisherURL
={#emit APP_URL}
21 AppVersion
={#emit APP_VERSION}
22 AppVerName
={#emit APP_NAME+' '+APP_VERSION}
23 ChangesEnvironment
=yes
24 DefaultDirName
={pf}\
{#emit APP_NAME}
25 DefaultGroupName
={#emit APP_NAME}
27 InfoBeforeFile
=gpl
-2.0.rtf
28 PrivilegesRequired
=none
29 UninstallDisplayIcon
=etc\git
.ico
32 SetupIconFile
=etc\git
.ico
33 WizardImageBackColor
=clWhite
35 WizardImageFile
=git
.bmp
36 WizardSmallImageFile
=gitsmall
.bmp
39 ; Define a dummy type to avoid getting the default ones.
40 Name
: custom
; Description
: Custom installation
; Flags
: iscustom
43 Name
: icons
; Description
: Additional icons
; Types
: custom
44 Name
: icons\quicklaunch
; Description
: In the Quick Launch
; Types
: custom
45 Name
: icons\desktop
; Description
: On the Desktop
; Types
: custom
46 Name
: ext
; Description
: Windows Explorer integration
; Types
: custom
47 Name
: ext
\reg
; Description
: Context menu entries
; Flags
: exclusive; Types
: custom
48 Name
: ext
\reg\shellhere
; Description
: Git Bash Here
; Types
: custom
49 Name
: ext
\reg\guihere
; Description
: Git GUI Here
; Types
: custom
50 Name
: ext\cheetah
; Description
: git
-cheetah shell
extension (32-bit only
); Flags
: exclusive; Types
: custom
51 Name
: assoc
; Description
: Associate
.git
* configuration
files with the default
text editor
; Types
: custom
52 Name
: consolefont
; Description
: Use a TrueType font
in the
console (required
for proper character encoding
); Types
: custom
55 Source
: *; DestDir
: {app}; Excludes
: \
*.bmp
, gpl
-2.0.rtf
, \
*.iss
, \tmp
.*, \bin\
*install
*; Flags
: recursesubdirs replacesameversion
56 Source
: ReleaseNotes
.rtf
; DestDir
: {app}; Flags
: isreadme replacesameversion
59 Name
: {group}\Git GUI
; Filename
: {app}\bin\wish
.exe
; Parameters
: """{app}\libexec\git-core\git-gui"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
60 Name
: {group}\Git Bash
; Filename
: {syswow64}\cmd
.exe
; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; WorkingDir
: %HOMEDRIVE
%%HOMEPATH
%; IconFilename
: {app}\etc\git
.ico
61 Name
: {group}\Uninstall Git
; Filename
: {uninstallexe}
62 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
; Components
: icons\quicklaunch
63 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
; Components
: icons\desktop
65 ; Create a special shortcut that does not set a working directory. This is used by "Git Bash.vbs", which in turn is run by the "Git Bash Here" shell extension.
66 Name
: {app}\Git Bash
; Filename
: {syswow64}\cmd
.exe
; Parameters
: "/c """"{app}\bin\sh.exe"" --login -i"""; IconFilename
: {app}\etc\git
.ico
69 BeveledLabel
={#emit APP_URL}
70 SetupAppTitle
={#emit APP_NAME} Setup
71 SetupWindowTitle
={#emit APP_NAME} Setup
74 ; There is no "Console" key in HKLM.
75 Root
: HKCU
; Subkey
: Console
; ValueType
: string; ValueName
: FaceName
; ValueData
: Lucida Console
; Components
: consolefont
76 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontFamily
; ValueData
: $00000036; Components
: consolefont
77 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontSize
; ValueData
: $000e0000; Components
: consolefont
78 Root
: HKCU
; Subkey
: Console
; ValueType
: dword
; ValueName
: FontWeight
; ValueData
: $00000190; Components
: consolefont
80 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: string; ValueName
: FaceName
; ValueData
: Lucida Console
; Flags
: createvalueifdoesntexist
81 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontFamily
; ValueData
: $00000036; Flags
: createvalueifdoesntexist
82 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontSize
; ValueData
: $000e0000; Flags
: createvalueifdoesntexist
83 Root
: HKCU
; Subkey
: Console\Git Bash
; ValueType
: dword
; ValueName
: FontWeight
; ValueData
: $00000190; Flags
: createvalueifdoesntexist
85 ; File associations for configuration files that may be contained in a repository (so this does not include ".gitconfig").
86 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
87 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
88 Root
: HKLM
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
89 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
90 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
91 Root
: HKCU
; Subkey
: Software\Classes\
.gitattributes
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
93 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
94 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
95 Root
: HKLM
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
96 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
97 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
98 Root
: HKCU
; Subkey
: Software\Classes\
.gitignore
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
100 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
101 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
102 Root
: HKLM
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: IsAdminLoggedOn
; Components
: assoc
103 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueData
: txtfile
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
104 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: Content
Type; ValueData
: text/plain
; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
105 Root
: HKCU
; Subkey
: Software\Classes\
.gitmodules
; ValueType
: string; ValueName
: PerceivedType
; ValueData
: text; Flags
: createvalueifdoesntexist; Check
: not IsAdminLoggedOn
; Components
: assoc
108 ; Delete the built-ins.
109 Type: files; Name
: {app}\bin\git
-*.exe
110 Type: files; Name
: {app}\libexec\git
-core\git
-*.exe
111 Type: files; Name
: {app}\libexec\git
-core\git
.exe
113 ; Delete any (temporary) git-cheetah files.
114 Type: files; Name
: {app}\git
-cheetah\
*.*
116 ; Delete a home directory inside the msysGit directory.
117 Type: dirifempty; Name
: {app}\home\
{username}
118 Type: dirifempty; Name
: {app}\home
121 #include
"helpers.inc.iss"
122 #include
"putty.inc.iss"
123 #include
"modules.inc.iss"
125 function CreateHardLink(lpFileName
,lpExistingFileName
:String;lpSecurityAttributes
:Integer):Boolean;
127 external 'CreateHardLinkW@Kernel32.dll stdcall delayload setuponly';
129 external 'CreateHardLinkA@Kernel32.dll stdcall delayload setuponly';
132 function CreateSymbolicLink(lpSymlinkFileName
,lpTargetFileName
:String;dwFlags
:DWORD
):Boolean;
134 external 'CreateSymbolicLinkW@Kernel32.dll stdcall delayload setuponly';
136 external 'CreateSymbolicLinkA@Kernel32.dll stdcall delayload setuponly';
149 // Git line ending conversion options
.
152 GC_CRLFCommitAsIs
= 3;
155 // Wizard page
and variables
for the Path options
.
156 PathPage
:TWizardPage
;
157 RdbPath
:array[GP_BashOnly
..GP_CmdTools
] of TRadioButton
;
159 // Wizard page
and variables
for the SSH options
.
160 PuTTYPage
:TWizardPage
;
161 RdbSSH
:array[GS_OpenSSH
..GS_Plink
] of TRadioButton
;
164 // Wizard page
and variables
for the line ending conversion options
.
165 CRLFPage
:TWizardPage
;
166 RdbCRLF
:array[GC_LFOnly
..GC_CRLFCommitAsIs
] of TRadioButton
;
168 // Wizard page
and variables
for the processes page
.
169 Processes
:ProcessList
;
170 ProcessesPage
:TWizardPage
;
171 ProcessesListBox
:TListBox
;
172 ProcessesRefresh
:TButton
;
174 procedure BrowseForPuTTYFolder(Sender
:TObject
);
178 Path
:=ExtractFilePath(EdtPlink
.Text);
179 BrowseForFolder('Please select the PuTTY folder:',Path
,False);
180 if FileExists(Path
+'\TortoisePlink.exe') then begin
181 EdtPlink
.Text:=Path
+'\TortoisePlink.exe';
182 RdbSSH
[GS_Plink
].Checked
:=True;
183 end else if FileExists(Path
+'\plink.exe') then begin
184 EdtPlink
.Text:=Path
+'\plink.exe';
185 RdbSSH
[GS_Plink
].Checked
:=True;
187 MsgBox('Please enter a valid path to "TortoisePlink.exe" or "plink.exe".',mbError
,MB_OK
);
191 procedure DeleteContextMenuEntries
;
193 AppDir
,Command
,Msg
:String;
196 AppDir
:=ExpandConstant('{app}');
198 if IsAdminLoggedOn
then begin
199 RootKey
:=HKEY_LOCAL_MACHINE
;
201 RootKey
:=HKEY_CURRENT_USER
;
205 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command
);
206 if Pos(AppDir
,Command
)>0 then begin
207 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell') then begin
208 Msg
:='Line {#emit __LINE__}: Unable to remove "Git Bash Here" shell extension.';
209 MsgBox(Msg
,mbError
,MB_OK
);
211 // This
is not a critical error
, the user can probably fix it manually
,
217 RegQueryStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command
);
218 if Pos(AppDir
,Command
)>0 then begin
219 if not RegDeleteKeyIncludingSubkeys(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui') then begin
220 Msg
:='Line {#emit __LINE__}: Unable to remove "Git GUI Here" shell extension.';
221 MsgBox(Msg
,mbError
,MB_OK
);
223 // This
is not a critical error
, the user can probably fix it manually
,
229 procedure RefreshProcessList(Sender
:TObject
);
234 ProcessesListBox
.Items
.Clear
;
235 if (Sender
=NIL) or (FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),Processes
)) then begin
236 for i
:=0 to GetArrayLength(Processes
)-1 do begin
237 Caption
:=Processes
[i
].Name
+' (PID '+IntToStr(Processes
[i
].ID
)+')';
238 ProcessesListBox
.Items
.Append(Caption
);
247 procedure InitializeWizard
;
249 i
,PrevPageID
:Integer;
250 LblGitBash
,LblGitCmd
,LblGitCmdTools
,LblGitCmdToolsWarn
:TLabel
;
251 LblOpenSSH
,LblPlink
:TLabel
;
252 PuTTYSessions
:TArrayOfString
;
253 LblLFOnly
,LblCRLFAlways
,LblCRLFCommitAsIs
:TLabel
;
257 // Until we have a
64-bit version
of git
-cheetah
, disable it on
64-bit Windows
.
258 if isWin64
then begin
259 for i
:=0 to WizardForm
.ComponentsList
.Items
.Count
-1 do begin
260 Data
:=LowerCase(WizardForm
.ComponentsList
.ItemCaption
[i
]);
261 if Pos('context',Data
)>0 then begin
262 // Select the Registry
-based context menu entries
.
263 WizardForm
.ComponentsList
.Checked
[i
]:=True;
264 end else if Pos('cheetah',Data
)>0 then begin
265 // Disable the git
-cheetah shell extension
.
266 WizardForm
.ComponentsList
.ItemEnabled
[i
]:=False;
271 PrevPageID
:=wpSelectProgramGroup
;
274 * Create a custom page for modifying the environment.
277 PathPage
:=CreateCustomPage(
279 'Adjusting your PATH environment',
280 'How would you like to use Git from the command line?'
282 PrevPageID
:=PathPage
.ID
;
285 RdbPath
[GP_BashOnly
]:=TRadioButton
.Create(PathPage
);
286 with RdbPath
[GP_BashOnly
] do begin
287 Parent
:=PathPage
.Surface
;
288 Caption
:='Use Git Bash only';
293 Font
.Style
:=[fsBold
];
297 LblGitBash
:=TLabel
.Create(PathPage
);
298 with LblGitBash
do begin
299 Parent
:=PathPage
.Surface
;
301 'This is the most conservative choice if you are concerned about the stability' + #
13 +
302 'of your system. Your PATH will not be modified.';
310 RdbPath
[GP_Cmd
]:=TRadioButton
.Create(PathPage
);
311 with RdbPath
[GP_Cmd
] do begin
312 Parent
:=PathPage
.Surface
;
313 Caption
:='Run Git from the Windows Command Prompt';
318 Font
.Style
:=[fsBold
];
321 LblGitCmd
:=TLabel
.Create(PathPage
);
322 with LblGitCmd
do begin
323 Parent
:=PathPage
.Surface
;
325 'This option is considered safe and no conflicts with other tools are known.' + #
13 +
326 'Only Git will be added to your PATH. Use this option if you want to use Git' + #
13 +
327 'from a Cygwin Prompt (make sure to not have Cygwin''s Git installed).';
335 RdbPath
[GP_CmdTools
]:=TRadioButton
.Create(PathPage
);
336 with RdbPath
[GP_CmdTools
] do begin
337 Parent
:=PathPage
.Surface
;
338 Caption
:='Run Git and included Unix tools from the Windows Command Prompt';
343 Font
.Style
:=[fsBold
];
346 LblGitCmdTools
:=TLabel
.Create(PathPage
);
347 with LblGitCmdTools
do begin
348 Parent
:=PathPage
.Surface
;
349 Caption
:='Both Git and its accompanying Unix tools will be added to your PATH.';
355 LblGitCmdToolsWarn
:=TLabel
.Create(PathPage
);
356 with LblGitCmdToolsWarn
do begin
357 Parent
:=PathPage
.Surface
;
359 'Warning: This will override Windows tools like find.exe and' + #
13 +
360 'sort.exe. Select this option only if you understand the implications.';
366 Font
.Style
:=[fsBold
];
369 // Restore the setting chosen during a previous install
.
370 Data
:=GetPreviousData('Path Option','BashOnly');
371 if Data
='BashOnly' then begin
372 RdbPath
[GP_BashOnly
].Checked
:=True;
373 end else if Data
='Cmd' then begin
374 RdbPath
[GP_Cmd
].Checked
:=True;
375 end else if Data
='CmdTools' then begin
376 RdbPath
[GP_CmdTools
].Checked
:=True;
380 * Create a custom page for using (Tortoise)Plink instead of OpenSSH
381 * if at least one PuTTY session is found in the Registry.
384 if RegGetSubkeyNames(HKEY_CURRENT_USER
,'Software\SimonTatham\PuTTY\Sessions',PuTTYSessions
) and (GetArrayLength(PuTTYSessions
)>0) then begin
385 PuTTYPage
:=CreateCustomPage(
387 'Choosing the SSH executable',
388 'Which Secure Shell client program would you like Git to use?'
390 PrevPageID
:=PuTTYPage
.ID
;
393 RdbSSH
[GS_OpenSSH
]:=TRadioButton
.Create(PuTTYPage
);
394 with RdbSSH
[GS_OpenSSH
] do begin
395 Parent
:=PuTTYPage
.Surface
;
396 Caption
:='Use OpenSSH';
401 Font
.Style
:=[fsBold
];
405 LblOpenSSH
:=TLabel
.Create(PuTTYPage
);
406 with LblOpenSSH
do begin
407 Parent
:=PuTTYPage
.Surface
;
409 'This uses ssh.exe that comes with Git. The GIT_SSH and SVN_SSH' + #
13 +
410 'environment variables will not be modified.';
418 RdbSSH
[GS_Plink
]:=TRadioButton
.Create(PuTTYPage
);
419 with RdbSSH
[GS_Plink
] do begin
420 Parent
:=PuTTYPage
.Surface
;
421 Caption
:='Use (Tortoise)Plink';
426 Font
.Style
:=[fsBold
];
429 LblPlink
:=TLabel
.Create(PuTTYPage
);
430 with LblPlink
do begin
431 Parent
:=PuTTYPage
.Surface
;
433 'PuTTY sessions were found in your Registry. You may specify the path' + #
13 +
434 'to an existing copy of (Tortoise)Plink.exe from the TortoiseSVN/CVS' + #
13 +
435 'or PuTTY applications. The GIT_SSH and SVN_SSH environment' + #
13 +
436 'variables will be adjusted to point to the following executable:';
442 EdtPlink
:=TEdit
.Create(PuTTYPage
);
443 with EdtPlink
do begin
444 Parent
:=PuTTYPage
.Surface
;
445 Text:=GetPuTTYLocation
;
446 if not FileExists(Text) then begin
454 BtnPlink
:=TButton
.Create(PuTTYPage
);
455 with BtnPlink
do begin
456 Parent
:=PuTTYPage
.Surface
;
458 OnClick
:=@BrowseForPuTTYFolder
;
465 // Restore the setting chosen during a previous install
.
466 Data
:=GetPreviousData('SSH Option','OpenSSH');
467 if Data
='OpenSSH' then begin
468 RdbSSH
[GS_OpenSSH
].Checked
:=True;
469 end else if Data
='Plink' then begin
470 RdbSSH
[GS_Plink
].Checked
:=True;
477 * Create a custom page for the core.autocrlf setting.
480 CRLFPage
:=CreateCustomPage(
482 'Configuring the line ending conversions',
483 'How should Git treat line endings in text files?'
485 PrevPageID
:=CRLFPage
.ID
;
488 RdbCRLF
[GC_CRLFAlways
]:=TRadioButton
.Create(CRLFPage
);
489 with RdbCRLF
[GC_CRLFAlways
] do begin
490 Parent
:=CRLFPage
.Surface
;
491 Caption
:='Checkout Windows-style, commit Unix-style line endings';
496 Font
.Style
:=[fsBold
];
500 LblCRLFAlways
:=TLabel
.Create(CRLFPage
);
501 with LblCRLFAlways
do begin
502 Parent
:=CRLFPage
.Surface
;
504 'Git will convert LF to CRLF when checking out text files. When committing' + #
13 +
505 'text files, CRLF will be converted to LF. For cross-platform projects,' + #
13 +
506 'this is the recommended setting on Windows ("core.autocrlf" is set to "true").';
514 RdbCRLF
[GC_LFOnly
]:=TRadioButton
.Create(CRLFPage
);
515 with RdbCRLF
[GC_LFOnly
] do begin
516 Parent
:=CRLFPage
.Surface
;
517 Caption
:='Checkout as-is, commit Unix-style line endings';
522 Font
.Style
:=[fsBold
];
526 LblLFOnly
:=TLabel
.Create(CRLFPage
);
527 with LblLFOnly
do begin
528 Parent
:=CRLFPage
.Surface
;
530 'Git will not perform any conversion when checking out text files. When' + #
13 +
531 'committing text files, CRLF will be converted to LF. For cross-platform projects,' + #
13 +
532 'this is the recommended setting on Unix ("core.autocrlf" is set to "input").';
540 RdbCRLF
[GC_CRLFCommitAsIs
]:=TRadioButton
.Create(CRLFPage
);
541 with RdbCRLF
[GC_CRLFCommitAsIs
] do begin
542 Parent
:=CRLFPage
.Surface
;
543 Caption
:='Checkout as-is, commit as-is';
548 Font
.Style
:=[fsBold
];
552 LblCRLFCommitAsIs
:=TLabel
.Create(CRLFPage
);
553 with LblCRLFCommitAsIs
do begin
554 Parent
:=CRLFPage
.Surface
;
556 'Git will not perform any conversions when checking out or committing' + #
13 +
557 'text files. Choosing this option is not recommended for cross-platform' + #
13 +
558 'projects ("core.autocrlf" is set to "false").';
565 // Restore the setting chosen during a previous install
.
566 Data
:=GetPreviousData('CRLF Option','CRLFAlways');
567 if Data
='LFOnly' then begin
568 RdbCRLF
[GC_LFOnly
].Checked
:=True;
569 end else if Data
='CRLFAlways' then begin
570 RdbCRLF
[GC_CRLFAlways
].Checked
:=True;
571 end else if Data
='CRLFCommitAsIs' then begin
572 RdbCRLF
[GC_CRLFCommitAsIs
].Checked
:=True;
576 * Create a custom page for finding the processes that lock a module.
579 ProcessesPage
:=CreateCustomPage(
581 'Replacing in-use files',
582 'The following applications use files that need to be replaced, please close them.'
585 ProcessesListBox
:=TListBox
.Create(ProcessesPage
);
586 with ProcessesListBox
do begin
587 Parent
:=ProcessesPage
.Surface
;
588 Width
:=ProcessesPage
.SurfaceWidth
;
589 Height
:=ProcessesPage
.SurfaceHeight
-ScaleY(8);
592 ProcessesRefresh
:=TNewButton
.Create(WizardForm
);
593 with ProcessesRefresh
do begin
595 Width
:=WizardForm
.NextButton
.Width
;
596 Height
:=WizardForm
.NextButton
.Height
;
597 Top
:=WizardForm
.NextButton
.Top
;
598 Left
:=WizardForm
.ClientWidth
-WizardForm
.NextButton
.Left
-WizardForm
.NextButton
.Width
;
600 OnClick
:=@RefreshProcessList
;
603 // Initially hide the Refresh button
, show it when the process page becomes current
.
604 ProcessesRefresh
.Hide
;
607 function ShouldSkipPage(PageID
:Integer):Boolean;
609 if (ProcessesPage
<>NIL) and (PageID
=ProcessesPage
.ID
) then begin
610 Result
:=(not FindProcessesUsingModule(ExpandConstant('{app}\git-cheetah\git_shell_ext.dll'),Processes
))
611 or (GetArrayLength(Processes
)=0);
617 procedure CurPageChanged(CurPageID
:Integer);
619 if (ProcessesPage
<>NIL) and (CurPageID
=ProcessesPage
.ID
) then begin
620 RefreshProcessList(NIL);
621 ProcessesRefresh
.Show
;
623 ProcessesRefresh
.Hide
;
627 function NextButtonClick(CurPageID
:Integer):Boolean;
631 if (PuTTYPage
<>NIL) and (CurPageID
=PuTTYPage
.ID
) then begin
632 Result
:=RdbSSH
[GS_OpenSSH
].Checked
or
633 (RdbSSH
[GS_Plink
].Checked
and FileExists(EdtPlink
.Text));
634 if not Result
then begin
635 MsgBox('Please enter a valid path to (Tortoise)Plink.exe.',mbError
,MB_OK
);
637 end else if (ProcessesPage
<>NIL) and (CurPageID
=ProcessesPage
.ID
) then begin
638 Result
:=(ProcessesListBox
.Items
.Count
=0);
639 if not Result
then begin
641 'If you continue without closing the listed applications you need to log off and on again before changes take effect.' + #
13 +
642 'Are you sure you want to continue anyway?',
652 // Even though the name
of this
procedure suggests otherwise most
of the
653 // code below
is only executed once after the regular installation code
654 // is finished
. This happens because
of the
if-guard right
in the
655 // beginning
of this
procedure.
656 procedure CurStepChanged(CurStep
:TSetupStep
);
658 AppDir
,FileName
,TempName
,Cmd
,Msg
:String;
659 BuiltIns
,EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
665 if CurStep
<>ssPostInstall
then begin
669 AppDir
:=ExpandConstant('{app}');
675 // Load the built
-ins from a
text file.
676 FileName
:=ExpandConstant('{app}\{#emit APP_BUILTINS}');
677 if LoadStringsFromFile(FileName
,BuiltIns
) then begin
678 Count
:=GetArrayLength(BuiltIns
)-1;
680 // Delete those scripts from
"bin" which have been replaced by built
-ins
in "libexec\git-core".
681 for i
:=0 to Count
do begin
682 FileName
:=AppDir
+'\bin\'+ChangeFileExt(ExtractFileName(BuiltIns[i]),'');
683 if FileExists(FileName) and (not DeleteFile(FileName)) then begin
684 Log('Line
{#emit __LINE__}: Unable
to delete script
"'+FileName+'", ignoring
.');
688 // Create built-ins as aliases for git.exe.
689 for i:=0 to Count do begin
690 FileName:=AppDir+'\'+BuiltIns
[i
];
692 // Delete any existing built
-in.
693 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
694 Log('Line {#emit __LINE__}: Unable to delete existing built-in "'+FileName
+'", skipping.');
699 // This will throw an exception on pre
-WinVista systems
.
700 LinkCreated
:=CreateSymbolicLink(FileName
,AppDir
+'\bin\git.exe',0);
703 Log('Line {#emit __LINE__}: Creating symbolic link "'+FileName
+'" failed, will try a hard link.');
706 if not LinkCreated
then begin
708 // This will throw an exception on pre
-Win2k systems
.
709 LinkCreated
:=CreateHardLink(FileName
,AppDir
+'\bin\git.exe',0);
712 Log('Line {#emit __LINE__}: Creating hardlink "'+FileName
+'" failed, will try a copy.');
716 if not LinkCreated
then begin
717 if not FileCopy(AppDir
+'\bin\git.exe',FileName
,False) then begin
718 Log('Line {#emit __LINE__}: Creating copy "'+FileName
+'" failed, giving up.');
719 // This
is not a critical error
, Git could basically be used without the
720 // aliases
for built
-ins
, so we continue
.
725 // Delete any duplicate
files in case we are updating from a non
-libexec
to a libexec directory layout
.
726 if FindFirst(AppDir
+'\libexec\git-core\*',FindRec
) then begin
728 if (FindRec
.Attributes
and FILE_ATTRIBUTE_DIRECTORY
)=0 then begin
729 FileName
:=AppDir
+'\bin\'+FindRec.name;
730 if (Pos(FindRec.name,'git
.exe
')<>1) and FileExists(FileName) and (not DeleteFile(FileName)) then begin
731 Log('Line
{#emit __LINE__}: Unable
to delete dupe
"'+FileName+'", ignoring
.');
734 until not FindNext(FindRec);
738 Msg:='Line
{#emit __LINE__}: Unable
to read file "{#emit APP_BUILTINS}".';
739 MsgBox(Msg,mbError,MB_OK);
741 // This is not a critical error, Git could basically be used without the
742 // aliases for built-ins, so we continue.
749 if RdbCRLF[GC_LFOnly].checked then begin
750 Cmd:='core
.autocrlf input
';
751 end else if RdbCRLF[GC_CRLFAlways].checked then begin
752 Cmd:='core
.autocrlf
true';
754 Cmd:='core
.autocrlf
false';
756 if not Exec(AppDir + '\bin\git
.exe
', 'config
-f gitconfig
' + Cmd,
757 AppDir + '\etc
', SW_HIDE, ewWaitUntilTerminated, i) then begin
758 Msg:='Unable
to configure the line ending conversion
: ' + Cmd;
759 MsgBox(Msg,mbError,MB_OK);
764 Modify the environment
766 This must happen no later than ssPostInstall to make
767 "ChangesEnvironment=yes" not happend before the change!
770 FileName:=AppDir+'\setup
.ini
';
772 // Delete GIT_SSH and SVN_SSH if a previous installation set them (this is required for the GS_OpenSSH case).
773 EnvSSH:=GetEnvStrings('GIT_SSH
',IsAdminLoggedOn);
774 if (GetArrayLength(EnvSSH)=1) and
775 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','GIT_SSH
','',FileName))=0) then begin
776 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,[]) then begin
777 Msg:='Line
{#emit __LINE__}: Unable
to reset GIT_SSH prior
to install
.';
778 MsgBox(Msg,mbError,MB_OK);
780 // This is not a critical error, the user can probably fix it manually,
785 EnvSSH:=GetEnvStrings('SVN_SSH
',IsAdminLoggedOn);
786 if (GetArrayLength(EnvSSH)=1) and
787 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','SVN_SSH
','',FileName))=0) then begin
788 if not SetEnvStrings('SVN_SSH
',IsAdminLoggedOn,True,[]) then begin
789 Msg:='Line
{#emit __LINE__}: Unable
to reset SVN_SSH prior
to install
.';
790 MsgBox(Msg,mbError,MB_OK);
792 // This is not a critical error, the user can probably fix it manually,
797 if (PuTTYPage<>NIL) and RdbSSH[GS_Plink].Checked then begin
798 SetArrayLength(EnvSSH,1);
799 EnvSSH[0]:=EdtPlink.Text;
801 // Set GIT_SSH as specified by the user.
802 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,EnvSSH) then begin
803 Msg:='Line
{#emit __LINE__}: Unable
to set the GIT_SSH environment variable
.';
804 MsgBox(Msg,mbError,MB_OK);
806 // This is not a critical error, the user can probably fix it manually,
810 // Mark that we have changed GIT_SSH by writing its value to a file.
811 if not SetIniString('Environment
','GIT_SSH
',EnvSSH[0],FileName) then begin
812 Msg:='Line
{#emit __LINE__}: Unable
to write
to file "'+FileName+'".';
813 MsgBox(Msg,mbError,MB_OK);
815 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
819 // Set SVN_SSH as specified by the user, but with escaped backslashes and quotes.
820 StringChangeEx(EnvSSH[0],'\','\\',True);
821 EnvSSH
[0]:=AddQuotes(EnvSSH
[0]);
823 if not SetEnvStrings('SVN_SSH',IsAdminLoggedOn
,True,EnvSSH
) then begin
824 Msg
:='Line {#emit __LINE__}: Unable to set the SVN_SSH environment variable.';
825 MsgBox(Msg
,mbError
,MB_OK
);
827 // This
is not a critical error
, the user can probably fix it manually
,
831 // Mark that we have changed SVN_SSH by writing its value
to a
file.
832 if not SetIniString('Environment','SVN_SSH',EnvSSH
[0],FileName
) then begin
833 Msg
:='Line {#emit __LINE__}: Unable to write to file "'+FileName
+'".';
834 MsgBox(Msg
,mbError
,MB_OK
);
836 // This
is not a critical error
, though uninstall
/ reinstall will probably
not run cleanly
,
841 // Get the current user
's directories in PATH.
842 EnvPath:=GetEnvStrings('PATH
',IsAdminLoggedOn);
844 // First, remove the installation directory from PATH in any case.
845 for i:=0 to GetArrayLength(EnvPath)-1 do begin
846 if Pos(AppDir+'\',EnvPath
[i
]+'\')=1 then begin
851 // Delete HOME if a previous installation modified it.
852 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
853 if (GetArrayLength(EnvHome)=1) and
854 (CompareStr(RemoveQuotes(EnvHome[0]),GetIniString('Environment
','HOME
','',FileName))=0) then begin
855 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,[]) then begin
856 Msg:='Line
{#emit __LINE__}: Unable
to reset HOME prior
to install
.';
857 MsgBox(Msg,mbError,MB_OK);
859 // This is not a critical error, the user can probably fix it manually,
864 // Modify the PATH variable as requested by the user.
865 if RdbPath[GP_Cmd].Checked or RdbPath[GP_CmdTools].Checked then begin
866 i:=GetArrayLength(EnvPath);
867 SetArrayLength(EnvPath,i+1);
869 // List \cmd before \bin so \cmd has higher priority and programs in
870 // there will be called in favor of those in \bin.
871 EnvPath[i]:=AppDir+'\cmd
';
873 if RdbPath[GP_CmdTools].Checked then begin
874 SetArrayLength(EnvPath,i+2);
875 EnvPath[i+1]:=AppDir+'\bin
';
877 // Set HOME for the Windows Command Prompt, but only if it has not been set manually before.
878 EnvHome:=GetEnvStrings('HOME
',IsAdminLoggedOn);
879 i:=GetArrayLength(EnvHome);
880 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
881 SetArrayLength(EnvHome,1);
882 EnvHome[0]:=ExpandConstant('{%HOMEDRIVE}{%HOMEPATH}');
883 if not SetEnvStrings('HOME
',IsAdminLoggedOn,True,EnvHome) then begin
884 Msg:='Line
{#emit __LINE__}: Unable
to set the HOME environment variable
.';
885 MsgBox(Msg,mbError,MB_OK);
887 // This is not a critical error, the user can probably fix it manually,
891 // Mark that we have changed HOME.
892 if not SetIniString('Environment
','HOME
',EnvHome[0],FileName) then begin
893 Msg:='Line
{#emit __LINE__}: Unable
to write
to file "'+FileName+'".';
894 MsgBox(Msg,mbError,MB_OK);
896 // This is not a critical error, though uninstall / reinstall will probably not run cleanly,
903 // Set the current user's PATH directories
.
904 if not SetEnvStrings('PATH',IsAdminLoggedOn
,True,EnvPath
) then begin
905 Msg
:='Line {#emit __LINE__}: Unable to set the PATH environment variable.';
906 MsgBox(Msg
,mbError
,MB_OK
);
908 // This
is not a critical error
, the user can probably fix it manually
,
913 Create the Windows Explorer integrations
916 if IsAdminLoggedOn
then begin
917 RootKey
:=HKEY_LOCAL_MACHINE
;
919 RootKey
:=HKEY_CURRENT_USER
;
922 if IsComponentSelected('ext\reg\shellhere') then begin
923 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell','','Git Ba&sh Here')) or
924 (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_shell\command','','wscript "'+AppDir
+'\Git Bash.vbs" "%1"')) then begin
925 Msg
:='Line {#emit __LINE__}: Unable to create "Git Bash Here" shell extension.';
926 MsgBox(Msg
,mbError
,MB_OK
);
928 // This
is not a critical error
, the user can probably fix it manually
,
933 if IsComponentSelected('ext\reg\guihere') then begin
934 if (not RegWriteStringValue(RootKey
,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here')) or
935 (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
936 Msg
:='Line {#emit __LINE__}: Unable to create "Git GUI Here" shell extension.';
937 MsgBox(Msg
,mbError
,MB_OK
);
939 // This
is not a critical error
, the user can probably fix it manually
,
944 // It
is either the Registry
-based context menu entries
, or the shell extension
.
945 if IsComponentSelected('ext\cheetah') then begin
946 DeleteContextMenuEntries
;
948 FileName
:=ExpandConstant('{app}\git-cheetah\git_shell_ext.dll');
949 TempName
:=GenerateUniqueName(ExtractFilePath(FileName
),'.git_shell_ext');
951 // Try to delete any previously renamed old shell extension
files.
952 DelTree(ExtractFilePath(FileName
)+'\*.git_shell_ext',False,True,False);
954 if FileExists(FileName
) then begin
955 if not UnregisterServer(Is64BitInstallMode
,FileName
,False) then begin
956 Msg
:='Line {#emit __LINE__}: Unable to unregister "'+FileName
+'".';
957 MsgBox(Msg
,mbError
,MB_OK
);
959 // This
is not a critical error
, the user can probably fix it manually
,
963 if (not DeleteFile(FileName
)) and (not RenameFile(FileName
,TempName
)) then begin
964 Msg
:='Line {#emit __LINE__}: Unable to delete or rename "'+FileName
+'".';
965 MsgBox(Msg
,mbError
,MB_OK
);
967 // This
is pretty much critical
, but will be catched below when
968 // renaming the new shell extension
file fails
.
972 if not RenameFile(FileName
+'.new',FileName
) then begin
973 Msg
:='Line {#emit __LINE__}: Unable to install git-cheetah. Please do it manually by renaming' + #
13 + #
13 +
974 '"'+FileName
+'.new" to "'+FileName
+'"' + #
13 + #
13 +
975 'and registering the shell extension by typing' + #
13 + #
13 +
976 '"regsvr32 '+ExtractFileName(FileName
)+'"' + #
13 + #
13 +
977 'at the command prompt in the git-cheetah directory.';
978 MsgBox(Msg
,mbError
,MB_OK
);
981 RegisterServer(Is64BitInstallMode
,FileName
,False);
986 procedure RegisterPreviousData(PreviousDataKey
:Integer);
992 if RdbPath
[GP_BashOnly
].Checked
then begin
994 end else if RdbPath
[GP_Cmd
].Checked
then begin
996 end else if RdbPath
[GP_CmdTools
].Checked
then begin
999 SetPreviousData(PreviousDataKey
,'Path Option',Data
);
1003 if (PuTTYPage
=NIL) or RdbSSH
[GS_OpenSSH
].Checked
then begin
1005 end else if RdbSSH
[GS_Plink
].Checked
then begin
1008 SetPreviousData(PreviousDataKey
,'SSH Option',Data
);
1010 // Line ending conversion options
.
1012 if RdbCRLF
[GC_LFOnly
].Checked
then begin
1014 end else if RdbCRLF
[GC_CRLFAlways
].Checked
then begin
1016 end else if RdbCRLF
[GC_CRLFCommitAsIs
].Checked
then begin
1017 Data
:='CRLFCommitAsIs';
1019 SetPreviousData(PreviousDataKey
,'CRLF Option',Data
);
1026 function InitializeUninstall
:Boolean;
1028 FileName
,NewName
,Msg
:String;
1030 FileName
:=ExpandConstant('{app}\bin\ssh-agent.exe');
1031 if FileExists(FileName
) then begin
1032 // Create a temporary copy
of the
file we
try to delete
.
1033 NewName
:=FileName
+'.'+IntToStr(1000+Random(9000));
1034 Result
:=FileCopy(FileName
,NewName
,True) and DeleteFile(FileName
);
1036 if not Result
then begin
1037 Msg
:='Line {#emit __LINE__}: Please stop all ssh-agent processes and run uninstall again.';
1038 MsgBox(Msg
,mbError
,MB_OK
);
1041 // Clean
-up the temporary
copy (ignoring any errors
).
1042 DeleteFile(NewName
);
1044 // Clean
-up the temporary
copy (ignoring any errors
).
1045 RenameFile(NewName
,FileName
);
1054 // Even though the name
of this
function suggests otherwise most
of the
1055 // code below
is only executed right before the actual uninstallation
.
1056 // This happens because
of the
if-guard right
in the beginning
of this
1058 procedure CurUninstallStepChanged(CurUninstallStep
:TUninstallStep
);
1060 AppDir
,FileName
,Msg
:String;
1061 EnvPath
,EnvHome
,EnvSSH
:TArrayOfString
;
1064 if CurUninstallStep
<>usUninstall
then begin
1069 Modify the environment
1071 This must happen no later than usUninstall to make
1072 "ChangesEnvironment=yes" not happend before the change!
1075 AppDir
:=ExpandConstant('{app}');
1076 FileName
:=AppDir
+'\setup.ini';
1078 // Delete the current user
's GIT_SSH and SVN_SSH if we set it.
1079 EnvSSH:=GetEnvStrings('GIT_SSH
',IsAdminLoggedOn);
1080 if (GetArrayLength(EnvSSH)=1) and
1081 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','GIT_SSH
','',FileName))=0) then begin
1082 if not SetEnvStrings('GIT_SSH
',IsAdminLoggedOn,True,[]) then begin
1083 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to GIT_SSH
.';
1084 MsgBox(Msg,mbError,MB_OK);
1086 // This is not a critical error, the user can probably fix it manually,
1091 EnvSSH:=GetEnvStrings('SVN_SSH
',IsAdminLoggedOn);
1092 if (GetArrayLength(EnvSSH)=1) and
1093 (CompareStr(RemoveQuotes(EnvSSH[0]),GetIniString('Environment
','SVN_SSH
','',FileName))=0) then begin
1094 if not SetEnvStrings('SVN_SSH
',IsAdminLoggedOn,True,[]) then begin
1095 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to SVN_SSH
.';
1096 MsgBox(Msg,mbError,MB_OK);
1098 // This is not a critical error, the user can probably fix it manually,
1103 // Get the current user's directories
in PATH
.
1104 EnvPath
:=GetEnvStrings('PATH',IsAdminLoggedOn
);
1106 // Remove the installation directory from PATH
in any
case, even
if it
1107 // was
not added by the installer
.
1108 for i
:=0 to GetArrayLength(EnvPath
)-1 do begin
1109 if Pos(AppDir
+'\',EnvPath[i]+'\')=1 then begin
1114 // Reset the current user
's directories in PATH.
1115 if not SetEnvStrings('PATH
',IsAdminLoggedOn,True,EnvPath) then begin
1116 Msg:='Line
{#emit __LINE__}: Unable
to revert any possible changes
to PATH
.';
1117 MsgBox(Msg,mbError,MB_OK);
1119 // This is not a critical error, the user can probably fix it manually,
1123 // Reset the current user's HOME
if we modified it
.
1124 EnvHome
:=GetEnvStrings('HOME',IsAdminLoggedOn
);
1125 if (GetArrayLength(EnvHome
)=1) and
1126 (CompareStr(RemoveQuotes(EnvHome
[0]),GetIniString('Environment','HOME','',FileName
))=0) then begin
1127 if not SetEnvStrings('HOME',IsAdminLoggedOn
,True,[]) then begin
1128 Msg
:='Line {#emit __LINE__}: Unable to revert any possible changes to HOME.';
1129 MsgBox(Msg
,mbError
,MB_OK
);
1131 // This
is not a critical error
, the user can probably fix it manually
,
1136 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
1137 Msg
:='Line {#emit __LINE__}: Unable to delete file "'+FileName
+'".';
1138 MsgBox(Msg
,mbError
,MB_OK
);
1140 // This
is not a critical error
, the user can probably fix it manually
,
1145 Delete the Windows Explorer integrations
1148 DeleteContextMenuEntries
;
1150 FileName
:=ExpandConstant('{app}\git-cheetah\git_shell_ext.dll');
1151 if FileExists(FileName
) and (not DeleteFile(FileName
)) then begin
1152 Msg
:='Line {#emit __LINE__}: Unable to delete file "'+FileName
+'". Please delete it manually after logging off and on again.';
1153 MsgBox(Msg
,mbError
,MB_OK
);