WinGit(Inno): Rename shell extension to "Git Bash Here"
[git/jnareb-git.git] / share / WinGit / install.iss
blobacf303072cec309f14b9ecc58b6ff39c828ec6e7
1 #define APP_NAME 'Git'
2 #define APP_VERSION '%APPVERSION%'
3 #define APP_URL 'http://code.google.com/p/msysgit/'
4 #define APP_BUILTINS 'etc\fileList-builtins.txt'
6 [Setup]
7 ; Compiler-related
8 InternalCompressLevel=max
9 OutputBaseFilename={#emit APP_NAME+'-'+APP_VERSION}
10 OutputDir=%OUTPUTDIR%
11 SolidCompression=yes
13 ; Installer-related
14 AllowNoIcons=yes
15 AppName={#emit APP_NAME}
16 AppPublisherURL={#emit APP_URL}
17 AppVersion={#emit APP_VERSION}
18 AppVerName={#emit APP_NAME+' '+APP_VERSION}
19 ChangesEnvironment=yes
20 DefaultDirName={pf}\{#emit APP_NAME}
21 DefaultGroupName={#emit APP_NAME}
22 DisableReadyPage=yes
23 LicenseFile=gpl-2.0.rtf
24 PrivilegesRequired=none
25 UninstallDisplayIcon=etc\git.ico
27 ; Cosmetic
28 SetupIconFile=etc\git.ico
29 WizardSmallImageFile=git.bmp
31 [Tasks]
32 Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
33 Name: desktopicon; Description: "Create a &Desktop icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
34 Name: shellextension; Description: "Add ""Git &Bash Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce
35 Name: guiextension; Description: "Add ""Git &GUI Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce
37 [Files]
38 Source: "*"; DestDir: "{app}"; Excludes: "\*.bmp, gpl-2.0.txt, \install.*, \tmp.*, \bin\*install*"; Flags: recursesubdirs
40 [Icons]
41 Name: "{group}\Git GUI"; Filename: "{app}\bin\wish.exe"; Parameters: """{app}\bin\git-gui"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"
42 Name: "{group}\Git Bash"; Filename: "{app}\bin\sh.exe"; Parameters: "--login -i"; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"
43 Name: "{group}\Uninstall Git"; Filename: "{uninstallexe}"
44 Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Git Bash"; Filename: "{app}\bin\sh.exe"; Parameters: "--login -i"; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: quicklaunchicon
45 Name: "{code:GetShellFolder|desktop}\Git Bash"; Filename: "{app}\bin\sh.exe"; Parameters: "--login -i"; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: desktopicon
47 [Messages]
48 BeveledLabel={#emit APP_URL}
50 [UninstallDelete]
51 Type: files; Name: "{app}\bin\git-*.exe"
52 Type: dirifempty; Name: "{app}\home\{username}"
53 Type: dirifempty; Name: "{app}\home"
55 [Code]
57 Helper methods
60 function GetShellFolder(Param:string):string;
61 begin
62 if IsAdminLoggedOn then begin
63 Param:='{common'+Param+'}';
64 end else begin
65 Param:='{user'+Param+'}';
66 end;
67 Result:=ExpandConstant(Param);
68 end;
70 function CreateHardLink(lpFileName,lpExistingFileName:string;lpSecurityAttributes:Integer):Boolean;
71 external 'CreateHardLinkA@Kernel32.dll';
73 function GetEnvStrings(VarName:string;AllUsers:Boolean):TArrayOfString;
74 var
75 Path:string;
76 i:Longint;
77 p:Integer;
78 begin
79 Path:='';
81 // See http://www.jrsoftware.org/isfaq.php#env
82 if AllUsers then begin
83 RegQueryStringValue(HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName,Path);
84 end else begin
85 RegQueryStringValue(HKEY_CURRENT_USER,'Environment',VarName,Path);
86 end;
88 // Make sure we have at least one semicolon.
89 Path:=Path+';';
91 // Split the directories in PATH into an array of strings.
92 i:=0;
93 SetArrayLength(Result,0);
95 p:=Pos(';',Path);
96 while p>0 do begin
97 SetArrayLength(Result,i+1);
98 if p>1 then begin
99 Result[i]:=Copy(Path,1,p-1);
100 i:=i+1;
101 end;
102 Path:=Copy(Path,p+1,Length(Path));
103 p:=Pos(';',Path);
104 end;
105 end;
107 function SetEnvStrings(VarName:string;AllUsers,DeleteIfEmpty:Boolean;DirStrings:TArrayOfString):Boolean;
109 Path,KeyName:string;
110 i:Longint;
111 begin
112 // Merge all non-empty directory strings into a PATH variable.
113 Path:='';
114 for i:=0 to GetArrayLength(DirStrings)-1 do begin
115 if Length(DirStrings[i])>0 then begin
116 if Length(Path)>0 then begin
117 Path:=Path+';'+DirStrings[i];
118 end else begin
119 Path:=DirStrings[i];
120 end;
121 end;
122 end;
124 // See http://www.jrsoftware.org/isfaq.php#env
125 if AllUsers then begin
126 KeyName:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
127 if DeleteIfEmpty and (Length(Path)=0) then begin
128 Result:=(not RegValueExists(HKEY_LOCAL_MACHINE,KeyName,VarName))
129 or RegDeleteValue(HKEY_LOCAL_MACHINE,KeyName,VarName);
130 end else begin
131 Result:=RegWriteStringValue(HKEY_LOCAL_MACHINE,KeyName,VarName,Path);
132 end;
133 end else begin
134 KeyName:='Environment';
135 if DeleteIfEmpty and (Length(Path)=0) then begin
136 Result:=(not RegValueExists(HKEY_CURRENT_USER,KeyName,VarName))
137 or RegDeleteValue(HKEY_CURRENT_USER,KeyName,VarName);
138 end else begin
139 Result:=RegWriteStringValue(HKEY_CURRENT_USER,KeyName,VarName,Path);
140 end;
141 end;
142 end;
145 Installer code
149 EnvPage:TWizardPage;
150 RdbGitBash,RdbGitCmd,RdbGitCmdTools:TRadioButton;
152 procedure InitializeWizard;
154 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
155 begin
156 // Create a custom page for modifying the environment.
157 EnvPage:=CreateCustomPage(
158 wpSelectTasks,
159 'Adjusting your PATH environment',
160 'How would you like to use Git from the command line?'
163 // 1st choice
164 RdbGitBash:=TRadioButton.Create(EnvPage);
165 with RdbGitBash do begin
166 Parent:=EnvPage.Surface;
167 Caption:='Use Git Bash only';
168 Left:=ScaleX(4);
169 Top:=ScaleY(8);
170 Width:=ScaleX(129);
171 Height:=ScaleY(17);
172 Font.Style:=[fsBold];
173 TabOrder:=0;
174 Checked:=True;
175 end;
176 LblGitBash:=TLabel.Create(EnvPage);
177 with LblGitBash do begin
178 Parent:=EnvPage.Surface;
179 Caption:=
180 'This is the most conservative choice if you are concerned about the' + #13 +
181 'stability of your system. Your PATH will not be modified.';
182 Left:=ScaleX(28);
183 Top:=ScaleY(32);
184 Width:=ScaleX(324);
185 Height:=ScaleY(26);
186 end;
188 // 2nd choice
189 RdbGitCmd:=TRadioButton.Create(EnvPage);
190 with RdbGitCmd do begin
191 Parent:=EnvPage.Surface;
192 Caption:='Run Git from the Windows Command Prompt';
193 Left:=ScaleX(4);
194 Top:=ScaleY(76);
195 Width:=ScaleX(281);
196 Height:=ScaleY(17);
197 Font.Style:=[fsBold];
198 TabOrder:=1;
199 end;
200 LblGitCmd:=TLabel.Create(EnvPage);
201 with LblGitCmd do begin
202 Parent:=EnvPage.Surface;
203 Caption:=
204 'This option is considered safe and no conflicts with other tools are' + #13 +
205 'known. Only Git will be added to your PATH.';
206 Left:=ScaleX(28);
207 Top:=ScaleY(100);
208 Width:=ScaleX(316);
209 Height:=ScaleY(26);
210 end;
212 // 3rd choice
213 RdbGitCmdTools:=TRadioButton.Create(EnvPage);
214 with RdbGitCmdTools do begin
215 Parent:=EnvPage.Surface;
216 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
217 Left:=ScaleX(4);
218 Top:=ScaleY(152);
219 Width:=ScaleX(405);
220 Height:=ScaleY(17);
221 Font.Style:=[fsBold];
222 TabOrder:=2;
223 end;
224 LblGitCmdTools:=TLabel.Create(EnvPage);
225 with LblGitCmdTools do begin
226 Parent:=EnvPage.Surface;
227 Caption:='Both Git and the Unix tools will be added to your PATH.';
228 Left:=ScaleX(28);
229 Top:=ScaleY(176);
230 Width:=ScaleX(280);
231 Height:=ScaleY(13);
232 end;
233 LblGitCmdToolsWarn:=TLabel.Create(EnvPage);
234 with LblGitCmdToolsWarn do begin
235 Parent:=EnvPage.Surface;
236 Caption:=
237 'Warning: This will override Windows tools like find.exe and' + #13 +
238 'sort.exe. Select this option only if you understand the implications.';
239 Left:=ScaleX(28);
240 Top:=ScaleY(192);
241 Width:=ScaleX(376);
242 Height:=ScaleY(26);
243 Font.Color:=255;
244 Font.Style:=[fsBold];
245 end;
246 end;
248 procedure CurStepChanged(CurStep:TSetupStep);
250 AppDir,FileName:string;
251 BuiltIns,EnvPath,EnvHome:TArrayOfString;
252 Count,i:Longint;
253 IsNTFS:Boolean;
254 RootKey:Integer;
255 begin
256 if CurStep<>ssPostInstall then begin
257 Exit;
258 end;
260 AppDir:=ExpandConstant('{app}');
263 Create the built-ins
266 // Load the built-ins from a text file.
267 FileName:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}');
268 if not LoadStringsFromFile(FileName,BuiltIns) then begin
269 MsgBox('Unable to read file "{#emit APP_BUILTINS}".',mbError,MB_OK);
270 Exit;
271 end;
273 // Check if we are running on NTFS.
274 IsNTFS:=False;
275 if SetNTFSCompression(AppDir+'\bin\git.exe',true) then begin
276 IsNTFS:=SetNTFSCompression(AppDir+'\bin\git.exe',false);
277 end;
279 Count:=GetArrayLength(BuiltIns)-1;
281 // Map the built-ins to git.exe.
282 if IsNTFS then begin
283 for i:=0 to Count do begin
284 FileName:=AppDir+'\'+BuiltIns[i];
286 // On non-NTFS partitions, create hard links.
287 CreateHardLink(FileName,AppDir+'\bin\git.exe',0);
288 end;
289 end else begin
290 for i:=0 to GetArrayLength(BuiltIns)-1 do begin
291 FileName:=AppDir+'\'+BuiltIns[i];
293 // On non-NTFS partitions, copy simply the files.
294 FileCopy(AppDir+'\bin\git.exe',FileName,false);
295 end;
296 end;
299 Modify the environment
301 This must happen no later than ssPostInstall to make
302 "ChangesEnvironment=yes" not happend before the change!
305 // Get the current user's directories in PATH.
306 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
308 // First, remove the installation directory from PATH in any case.
309 for i:=0 to GetArrayLength(EnvPath)-1 do begin
310 if Pos(AppDir,EnvPath[i])=1 then begin
311 EnvPath[i]:='';
312 end;
313 end;
315 // Delete HOME if a previous installation modified it.
316 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
317 if (GetArrayLength(EnvHome)=1) and
318 (CompareStr(EnvHome[0],GetIniString('Environment','HOME','',AppDir+'\setup.ini'))=0) then begin
319 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
320 MsgBox('Unable to reset HOME prior to install.',mbError,MB_OK);
321 end;
322 end;
324 // Modify the PATH variable as requested by the user.
325 if RdbGitCmd.Checked or RdbGitCmdTools.Checked then begin
326 i:=GetArrayLength(EnvPath);
327 SetArrayLength(EnvPath,i+1);
329 // List \cmd before \bin so \cmd has higher priority and programs in
330 // there will be called in favor of those in \bin.
331 EnvPath[i]:=ExpandConstant('{app}\cmd');
333 if RdbGitCmdTools.Checked then begin
334 SetArrayLength(EnvPath,i+2);
335 EnvPath[i+1]:=ExpandConstant('{app}\bin');
337 // Set HOME for the Windows Command Prompt.
338 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
339 i:=GetArrayLength(EnvHome);
340 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
341 SetArrayLength(EnvHome,1);
342 EnvHome[0]:=ExpandConstant('{%USERPROFILE}');
343 SetEnvStrings('HOME',IsAdminLoggedOn,True,EnvHome);
345 // Mark that we have changed HOME.
346 SetIniString('Environment','HOME',EnvHome[0],AppDir+'\setup.ini');
347 end;
348 end;
349 end;
351 // Set the current user's directories in PATH.
352 SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath);
355 Create the Windows Explorer shell extensions
358 if IsAdminLoggedOn then begin
359 RootKey:=HKEY_LOCAL_MACHINE;
360 end else begin
361 RootKey:=HKEY_CURRENT_USER;
362 end;
364 if IsTaskSelected('shellextension') then begin
365 RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell','','Git &Bash Here');
366 RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','','cmd.exe /c "pushd "%1" && "'+AppDir+'\bin\sh.exe" --login -i"');
367 end;
369 if IsTaskSelected('guiextension') then begin
370 RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui','','Git &GUI Here');
371 RegWriteStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','','"'+AppDir+'\bin\wish.exe" "'+AppDir+'\bin\git-gui" "--working-dir" "%1"');
372 end;
373 end;
376 Uninstaller code
379 function InitializeUninstall:Boolean;
380 begin
381 Result:=DeleteFile(ExpandConstant('{app}')+'\bin\ssh-agent.exe');
382 if not Result then begin
383 MsgBox('Please stop all ssh-agent processes and run uninstall again.',mbError,MB_OK);
384 end;
385 end;
387 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
389 AppDir,Command:string;
390 EnvPath,EnvHome:TArrayOfString;
391 i:Longint;
392 RootKey:Integer;
393 begin
394 if CurUninstallStep<>usUninstall then begin
395 Exit;
396 end;
399 Modify the environment
401 This must happen no later than usUninstall to make
402 "ChangesEnvironment=yes" not happend before the change!
405 AppDir:=ExpandConstant('{app}');
407 // Get the current user's directories in PATH.
408 EnvPath:=GetEnvStrings('PATH',IsAdminLoggedOn);
410 // Remove the installation directory from PATH in any case, even if it
411 // was not added by the installer.
412 for i:=0 to GetArrayLength(EnvPath)-1 do begin
413 if Pos(AppDir,EnvPath[i])=1 then begin
414 EnvPath[i]:='';
415 end;
416 end;
418 // Reset the current user's directories in PATH.
419 if not SetEnvStrings('PATH',IsAdminLoggedOn,True,EnvPath) then begin
420 MsgBox('Unable to revert any possible changes to PATH.',mbError,MB_OK);
421 end;
423 // Reset the current user's HOME if we modified it.
424 EnvHome:=GetEnvStrings('HOME',IsAdminLoggedOn);
425 if (GetArrayLength(EnvHome)=1) and
426 (CompareStr(EnvHome[0],GetIniString('Environment','HOME','',AppDir+'\setup.ini'))=0) then begin
427 if not SetEnvStrings('HOME',IsAdminLoggedOn,True,[]) then begin
428 MsgBox('Unable to revert any possible changes to HOME.',mbError,MB_OK);
429 end;
430 end;
431 DeleteFile(AppDir+'\setup.ini');
434 Delete the Windows Explorer shell extensions
437 if IsAdminLoggedOn then begin
438 RootKey:=HKEY_LOCAL_MACHINE;
439 end else begin
440 RootKey:=HKEY_CURRENT_USER;
441 end;
443 Command:='';
444 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell\command','',Command);
445 if Pos(AppDir,Command)>0 then begin
446 RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_shell');
447 end;
449 Command:='';
450 RegQueryStringValue(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui\command','',Command);
451 if Pos(AppDir,Command)>0 then begin
452 RegDeleteKeyIncludingSubkeys(RootKey,'SOFTWARE\Classes\Directory\shell\git_gui');
453 end;
454 end;