WinGit(Inno): Set HOME if adding \cmd to PATH
[git/jnareb-git.git] / share / WinGit / install.iss
blobd94eaf2f38a243566d74b0deb08a7720e7d36e53
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.txt
24 UninstallDisplayIcon=etc\git.ico
26 ; Cosmetic
27 SetupIconFile=etc\git.ico
28 WizardSmallImageFile=git.bmp
30 [Tasks]
31 Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
32 Name: desktopicon; Description: "Create a &Desktop icon"; GroupDescription: "Additional icons:"; Flags: checkedonce
33 Name: shellextension; Description: "Add ""Git &Bash Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce
34 Name: guiextension; Description: "Add ""Git &GUI Here"""; GroupDescription: "Windows Explorer integration:"; Flags: checkedonce
36 [Files]
37 Source: "*"; DestDir: "{app}"; Excludes: "\*.bmp, \*.txt, \install.*, \tmp.*, \bin\*install*"; Flags: recursesubdirs
39 [Icons]
40 Name: "{group}\Git GUI"; Filename: "{app}\bin\wish.exe"; Parameters: """{app}\bin\git-gui"""; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"
41 Name: "{group}\Git Bash"; Filename: "{app}\bin\sh.exe"; Parameters: "--login -i"; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"
42 Name: "{group}\Uninstall Git"; Filename: "{uninstallexe}"
43 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
44 Name: "{userdesktop}\Git Bash"; Filename: "{app}\bin\sh.exe"; Parameters: "--login -i"; WorkingDir: "%USERPROFILE%"; IconFilename: "{app}\etc\git.ico"; Tasks: desktopicon
46 [Messages]
47 BeveledLabel={#emit APP_URL}
49 [Registry]
50 Root: HKLM; Subkey: "SOFTWARE\Classes\Directory\shell\git_shell"; ValueType: string; ValueData: "Git &Shell Here"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: shellextension
51 Root: HKLM; Subkey: "SOFTWARE\Classes\Directory\shell\git_shell\command"; ValueType: string; ValueData: "cmd.exe /c ""pushd ""%1"" && ""{app}\bin\sh.exe"" --login -i"""; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: shellextension
52 Root: HKLM; Subkey: "SOFTWARE\Classes\Directory\shell\git_gui"; ValueType: string; ValueData: "Git &GUI Here"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: guiextension
53 Root: HKLM; Subkey: "SOFTWARE\Classes\Directory\shell\git_gui\command"; ValueType: string; ValueData: """{app}\bin\wish.exe"" ""{app}\bin\git-gui"" ""--working-dir"" ""%1"""; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: guiextension
55 [UninstallDelete]
56 Type: files; Name: "{app}\bin\git-*.exe"
57 Type: dirifempty; Name: "{app}\home\{username}"
58 Type: dirifempty; Name: "{app}\home"
60 [Code]
61 var
62 EnvPage:TWizardPage;
63 RdbGitBash,RdbGitCmd,RdbGitCmdTools:TRadioButton;
65 procedure InitializeWizard;
66 var
67 LblGitBash,LblGitCmd,LblGitCmdTools,LblGitCmdToolsWarn:TLabel;
68 begin
69 // Use a mono spaced font in the license dialog. NOTE: This might be too small.
70 WizardForm.LicenseMemo.Font.Name:='Lucida Console';
71 WizardForm.LicenseMemo.Font.Size:=7;
73 // Create a custom page for modifying the environment.
74 EnvPage:=CreateCustomPage(
75 wpSelectTasks,
76 'Adjusting your PATH environment',
77 'How would you like to use Git from the command line?'
80 // 1st choice
81 RdbGitBash:=TRadioButton.Create(EnvPage);
82 with RdbGitBash do begin
83 Parent:=EnvPage.Surface;
84 Caption:='Use Git Bash only';
85 Left:=ScaleX(4);
86 Top:=ScaleY(8);
87 Width:=ScaleX(129);
88 Height:=ScaleY(17);
89 Font.Style:=[fsBold];
90 TabOrder:=0;
91 Checked:=True;
92 end;
93 LblGitBash:=TLabel.Create(EnvPage);
94 with LblGitBash do begin
95 Parent:=EnvPage.Surface;
96 Caption:=
97 'This is the most conservative choice if you are concerned about the' + #13 +
98 'stability of your system. Your PATH will not be modified.';
99 Left:=ScaleX(28);
100 Top:=ScaleY(32);
101 Width:=ScaleX(324);
102 Height:=ScaleY(26);
103 end;
105 // 2nd choice
106 RdbGitCmd:=TRadioButton.Create(EnvPage);
107 with RdbGitCmd do begin
108 Parent:=EnvPage.Surface;
109 Caption:='Run Git from the Windows Command Prompt';
110 Left:=ScaleX(4);
111 Top:=ScaleY(76);
112 Width:=ScaleX(281);
113 Height:=ScaleY(17);
114 Font.Style:=[fsBold];
115 TabOrder:=1;
116 end;
117 LblGitCmd:=TLabel.Create(EnvPage);
118 with LblGitCmd do begin
119 Parent:=EnvPage.Surface;
120 Caption:=
121 'This option is considered safe and no conflicts with other tools are' + #13 +
122 'known. Only Git will be added to your PATH.';
123 Left:=ScaleX(28);
124 Top:=ScaleY(100);
125 Width:=ScaleX(316);
126 Height:=ScaleY(26);
127 end;
129 // 3rd choice
130 RdbGitCmdTools:=TRadioButton.Create(EnvPage);
131 with RdbGitCmdTools do begin
132 Parent:=EnvPage.Surface;
133 Caption:='Run Git and included Unix tools from the Windows Command Prompt';
134 Left:=ScaleX(4);
135 Top:=ScaleY(152);
136 Width:=ScaleX(405);
137 Height:=ScaleY(17);
138 Font.Style:=[fsBold];
139 TabOrder:=2;
140 end;
141 LblGitCmdTools:=TLabel.Create(EnvPage);
142 with LblGitCmdTools do begin
143 Parent:=EnvPage.Surface;
144 Caption:='Both Git and the Unix tools will be added to your PATH.';
145 Left:=ScaleX(28);
146 Top:=ScaleY(176);
147 Width:=ScaleX(280);
148 Height:=ScaleY(13);
149 end;
150 LblGitCmdToolsWarn:=TLabel.Create(EnvPage);
151 with LblGitCmdToolsWarn do begin
152 Parent:=EnvPage.Surface;
153 Caption:=
154 'Warning: This will override Windows tools like find.exe and' + #13 +
155 'sort.exe. Select this option only if you understand the implications.';
156 Left:=ScaleX(28);
157 Top:=ScaleY(192);
158 Width:=ScaleX(376);
159 Height:=ScaleY(26);
160 Font.Color:=255;
161 Font.Style:=[fsBold];
162 end;
163 end;
165 function GetEnvStrings(VarName:string;CurrentUser:Boolean):TArrayOfString;
167 Path:string;
168 i:Longint;
169 p:Integer;
170 begin
171 Path:='';
173 // See http://www.jrsoftware.org/isfaq.php#env
174 if CurrentUser then begin
175 RegQueryStringValue(HKEY_CURRENT_USER,'Environment',VarName,Path);
176 end else begin
177 RegQueryStringValue(HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',VarName,Path);
178 end;
180 // Make sure we have at least one semicolon.
181 Path:=Path+';';
183 // Split the directories in PATH into an array of strings.
184 i:=0;
185 SetArrayLength(Result,0);
187 p:=Pos(';',Path);
188 while p>0 do begin
189 SetArrayLength(Result,i+1);
190 if p>1 then begin
191 Result[i]:=Copy(Path,1,p-1);
192 i:=i+1;
193 end;
194 Path:=Copy(Path,p+1,Length(Path));
195 p:=Pos(';',Path);
196 end;
197 end;
199 function SetEnvStrings(VarName:string;CurrentUser,DeleteIfEmpty:Boolean;DirStrings:TArrayOfString):Boolean;
201 Path,KeyName:string;
202 i:Longint;
203 begin
204 // Merge all non-empty directory strings into a PATH variable.
205 Path:='';
206 for i:=0 to GetArrayLength(DirStrings)-1 do begin
207 if Length(DirStrings[i])>0 then begin
208 if Length(Path)>0 then begin
209 Path:=Path+';'+DirStrings[i];
210 end else begin
211 Path:=DirStrings[i];
212 end;
213 end;
214 end;
216 // See http://www.jrsoftware.org/isfaq.php#env
217 if CurrentUser then begin
218 KeyName:='Environment';
219 if DeleteIfEmpty and (Length(Path)=0) then begin
220 Result:=(not RegValueExists(HKEY_CURRENT_USER,KeyName,VarName))
221 or RegDeleteValue(HKEY_CURRENT_USER,KeyName,VarName);
222 end else begin
223 Result:=RegWriteStringValue(HKEY_CURRENT_USER,KeyName,VarName,Path);
224 end;
225 end else begin
226 KeyName:='SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
227 if DeleteIfEmpty and (Length(Path)=0) then begin
228 Result:=RegDeleteValue(HKEY_LOCAL_MACHINE,KeyName,VarName);
229 end else begin
230 Result:=RegWriteStringValue(HKEY_LOCAL_MACHINE,KeyName,VarName,Path);
231 end;
232 end;
233 end;
235 function CreateHardLink(lpFileName,lpExistingFileName:string;lpSecurityAttributes:Integer):Boolean;
236 external 'CreateHardLinkA@Kernel32.dll';
238 procedure CurStepChanged(CurStep:TSetupStep);
240 AppDir,FileName:string;
241 BuiltIns,EnvPath,EnvHome:TArrayOfString;
242 Count,i:Longint;
243 IsNTFS:Boolean;
244 begin
245 if CurStep<>ssPostInstall then begin
246 Exit;
247 end;
249 AppDir:=ExpandConstant('{app}');
252 Create the built-ins
255 // Load the built-ins from a text file.
256 FileName:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}');
257 if not LoadStringsFromFile(FileName,BuiltIns) then begin
258 MsgBox('Unable to read file "{#emit APP_BUILTINS}".',mbError,MB_OK);
259 Exit;
260 end;
262 // Check if we are running on NTFS.
263 IsNTFS:=False;
264 if SetNTFSCompression(AppDir+'\bin\git.exe',true) then begin
265 IsNTFS:=SetNTFSCompression(AppDir+'\bin\git.exe',false);
266 end;
268 Count:=GetArrayLength(BuiltIns)-1;
270 // Map the built-ins to git.exe.
271 if IsNTFS then begin
272 for i:=0 to Count do begin
273 FileName:=AppDir+'\'+BuiltIns[i];
275 // On non-NTFS partitions, create hard links.
276 CreateHardLink(FileName,AppDir+'\bin\git.exe',0);
277 end;
278 end else begin
279 for i:=0 to GetArrayLength(BuiltIns)-1 do begin
280 FileName:=AppDir+'\'+BuiltIns[i];
282 // On non-NTFS partitions, copy simply the files.
283 FileCopy(AppDir+'\bin\git.exe',FileName,false);
284 end;
285 end;
288 Modify the environment
290 This must happen no later than ssPostInstall to make
291 "ChangesEnvironment=yes" not happend before the change!
294 // Get the current user's directories in PATH.
295 EnvPath:=GetEnvStrings('PATH',True);
297 // First, remove the installation directory from PATH in any case.
298 for i:=0 to GetArrayLength(EnvPath)-1 do begin
299 if Pos(AppDir,EnvPath[i])=1 then begin
300 EnvPath[i]:='';
301 end;
302 end;
304 // Modify the PATH variable as requested by the user.
305 if RdbGitCmd.Checked or RdbGitCmdTools.Checked then begin
306 i:=GetArrayLength(EnvPath);
307 SetArrayLength(EnvPath,i+1);
309 // List \cmd before \bin so \cmd has higher priority and programs in
310 // there will be called in favor of those in \bin.
311 EnvPath[i]:=ExpandConstant('{app}\cmd');
313 if RdbGitCmdTools.Checked then begin
314 SetArrayLength(EnvPath,i+2);
315 EnvPath[i+1]:=ExpandConstant('{app}\bin');
316 end;
318 // Set HOME for the Windows Command Prompt.
319 EnvHome:=GetEnvStrings('HOME',True);
320 i:=GetArrayLength(EnvHome);
321 if (i=0) or ((i=1) and (Length(EnvHome[0])=0)) then begin
322 SetArrayLength(EnvHome,1);
323 EnvHome[0]:=ExpandConstant('{%USERPROFILE}');
324 SetEnvStrings('HOME',True,True,EnvHome);
326 // Mark that we have changed HOME.
327 SetIniString('Environment','HOME',EnvHome[0],AppDir+'\setup.ini');
328 end;
329 end;
331 // Set the current user's directories in PATH.
332 SetEnvStrings('PATH',True,True,EnvPath);
333 end;
335 procedure CurUninstallStepChanged(CurUninstallStep:TUninstallStep);
337 AppDir,a,b:string;
338 EnvPath,EnvHome:TArrayOfString;
339 i:Longint;
340 begin
341 if CurUninstallStep<>usUninstall then begin
342 Exit;
343 end;
346 Modify the environment
348 This must happen no later than usUninstall to make
349 "ChangesEnvironment=yes" not happend before the change!
352 AppDir:=ExpandConstant('{app}');
354 // Get the current user's directories in PATH.
355 EnvPath:=GetEnvStrings('PATH',True);
357 // Remove the installation directory from PATH in any case, even if it
358 // was not added by the installer.
359 for i:=0 to GetArrayLength(EnvPath)-1 do begin
360 if Pos(AppDir,EnvPath[i])=1 then begin
361 EnvPath[i]:='';
362 end;
363 end;
365 // Reset the current user's directories in PATH.
366 if not SetEnvStrings('PATH',True,True,EnvPath) then begin
367 MsgBox('Unable to revert any possible changes to PATH.',mbError,MB_OK);
368 end;
370 // Reset the current user's HOME if we modified it.
371 EnvHome:=GetEnvStrings('HOME',True);
372 if (GetArrayLength(EnvHome)=1) and
373 (CompareStr(EnvHome[0],GetIniString('Environment','HOME','',AppDir+'\setup.ini'))=0) then begin
374 if not SetEnvStrings('HOME',True,True,[]) then begin
375 MsgBox('Unable to revert any possible changes to HOME.',mbError,MB_OK);
376 end;
377 end;
378 DeleteFile(AppDir+'\setup.ini');
379 end;