From 8777623f90c8c013881f8be8601a11c40cbfde62 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 15 Oct 2007 12:31:36 +0200 Subject: [PATCH] WinGit(Inno): Make installer optionally modify PATH By using a helper script, the installer can now optionally modify the current user's PATH (which will be undone upon uninstall). Options are: - Not to modify PATH at all, - add only Git to PATH (i.e. \cmd), - add Git and UNIX tools to PATH (i.e. \bin and \mingw\bin). The default is to only add Git to PATH which seems to be the best compromise between the convenience to be able to use Git from cmd.exe and avoiding conflicts between programs with matching names (find, sort). --- share/WinGit-InnoSetup/install.iss | 94 ++++++++++++++++------- share/WinGit-InnoSetup/modpath.iss | 150 +++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 29 deletions(-) create mode 100644 share/WinGit-InnoSetup/modpath.iss diff --git a/share/WinGit-InnoSetup/install.iss b/share/WinGit-InnoSetup/install.iss index c8261711..8ef2a13a 100644 --- a/share/WinGit-InnoSetup/install.iss +++ b/share/WinGit-InnoSetup/install.iss @@ -16,6 +16,7 @@ AppName={#emit APP_NAME} AppPublisherURL={#emit APP_URL} AppVersion={#emit APP_VERSION} AppVerName={#emit APP_NAME+' '+APP_VERSION} +ChangesEnvironment=yes DefaultDirName={pf}\{#emit APP_NAME} DefaultGroupName={#emit APP_NAME} DisableReadyPage=yes @@ -27,10 +28,15 @@ SetupIconFile=etc\git.ico WizardSmallImageFile=install.bmp [Tasks] +Name: modifypath; Description: "Modify &PATH environment variable"; Flags: checkedonce +Name: modifypath\git; Description: "Add &only Git"; Flags: exclusive +Name: modifypath\tools; Description: "Add Git and UNIX &tools"; Flags: exclusive unchecked + +Name: shellextension; Description: "Add ""Git &Bash Here"" to Windows Explorer"; Flags: checkedonce +Name: guiextension; Description: "Add ""Git &GUI Here"" to Windows Explorer"; Flags: checkedonce + Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: checkedonce Name: desktopicon; Description: "Create a &Desktop icon"; GroupDescription: "Additional icons:"; Flags: checkedonce -Name: shellextension; Description: "Add ""Git Bash Here"" "; GroupDescription: "Shell extensions:"; Flags: checkedonce -Name: guiextension; Description: "Add ""Git GUI Here"" "; GroupDescription: "Shell extensions:"; Flags: checkedonce [Files] Source: "*"; DestDir: "{app}"; Excludes: "\*.txt, \install.*, \tmp.*, \bin\*install*"; Flags: recursesubdirs @@ -57,6 +63,35 @@ Type: dirifempty; Name: "{app}\home\{username}" Type: dirifempty; Name: "{app}\home" [Code] +function ModPathDir:TArrayOfString; +var + IsModifyPathGit,IsModifyPathTools:Boolean; + SelectedTasks:String; +begin + if IsUninstaller then begin + if LoadStringFromFile(ExpandConstant('{app}')+'\uninsTasks.txt',SelectedTasks) then begin + IsModifyPathGit:=Pos('modifypath\git',SelectedTasks)>0; + IsModifyPathTools:=Pos('modifypath\tools',SelectedTasks)>0; + end else begin + IsModifyPathGit:=False; + IsModifyPathTools:=False; + end; + end else begin + IsModifyPathGit:=IsTaskSelected('modifypath\git'); + IsModifyPathTools:=IsTaskSelected('modifypath\tools'); + end; + + if IsModifyPathGit then begin + setArrayLength(Result,1); + Result[0]:=ExpandConstant('{app}\cmd'); + end else if IsModifyPathTools then begin + setArrayLength(Result,2); + Result[0]:=ExpandConstant('{app}\bin'); + Result[1]:=ExpandConstant('{app}\mingw\bin'); + end; +end; +#include "modpath.iss" + procedure InitializeWizard; begin // Use a mono spaced font in the license dialog. NOTE: This might be too small. @@ -74,36 +109,37 @@ var i:Longint; IsNTFS:Boolean; begin - if CurStep<>ssDone then begin - Exit; - end; - - // Load the built-ins from a text file. - ListFile:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}'); - if not LoadStringsFromFile(ListFile,BuiltIns) then begin - MsgBox('Unable to read file "{#emit APP_BUILTINS}".', mbError, MB_OK); - Exit; - end; - - AppDir:=ExpandConstant('{app}'); + if CurStep=ssPostInstall then begin + if IsTaskSelected('modifypath') then begin + ModPath(); + end; + end else if CurStep=ssDone then begin + // Load the built-ins from a text file. + ListFile:=ExpandConstant('{app}\'+'{#emit APP_BUILTINS}'); + if not LoadStringsFromFile(ListFile,BuiltIns) then begin + MsgBox('Unable to read file "{#emit APP_BUILTINS}".', mbError, MB_OK); + Exit; + end; - // Check if we are running on NTFS. - IsNTFS:=False; - if SetNTFSCompression(AppDir+'\bin\git.exe',true) then begin - IsNTFS:=SetNTFSCompression(AppDir+'\bin\git.exe',false); - end; + AppDir:=ExpandConstant('{app}'); - // Map the built-ins to git.exe. - if IsNTFS then begin - for i:=0 to GetArrayLength(BuiltIns)-1 do begin - // On non-NTFS partitions, create hard links. - CreateHardLink(AppDir+'\'+BuiltIns[i],AppDir+'\bin\git.exe',0); + // Check if we are running on NTFS. + IsNTFS:=False; + if SetNTFSCompression(AppDir+'\bin\git.exe',true) then begin + IsNTFS:=SetNTFSCompression(AppDir+'\bin\git.exe',false); end; - end else begin - for i:=0 to GetArrayLength(BuiltIns)-1 do begin - // On non-NTFS partitions, copy simply the files. - FileCopy(AppDir+'\bin\git.exe',AppDir+'\'+BuiltIns[i],false); + + // Map the built-ins to git.exe. + if IsNTFS then begin + for i:=0 to GetArrayLength(BuiltIns)-1 do begin + // On non-NTFS partitions, create hard links. + CreateHardLink(AppDir+'\'+BuiltIns[i],AppDir+'\bin\git.exe',0); + end; + end else begin + for i:=0 to GetArrayLength(BuiltIns)-1 do begin + // On non-NTFS partitions, copy simply the files. + FileCopy(AppDir+'\bin\git.exe',AppDir+'\'+BuiltIns[i],false); + end; end; end; end; - diff --git a/share/WinGit-InnoSetup/modpath.iss b/share/WinGit-InnoSetup/modpath.iss new file mode 100644 index 00000000..4c172503 --- /dev/null +++ b/share/WinGit-InnoSetup/modpath.iss @@ -0,0 +1,150 @@ +// ---------------------------------------------------------------------------- +// +// Inno Setup Ver: 5.2.1 +// Script Version: 1.3.1 +// Author: Jared Breland +// Homepage: http://www.legroom.net/software +// Modified by: Sebastian Schuberth +// +// Script Function: +// Enable modification of system path directly from Inno Setup installers +// +// Instructions: +// Copy modpath.iss to the same directory as your setup script +// +// Add this statement to your [Setup] section +// ChangesEnvironment=yes +// +// Add this statement to your [Tasks] section +// You can change the Description or Flags, but the Name must be modifypath +// Name: modifypath; Description: &Add application directory to your system path; Flags: unchecked +// +// Add the following to the end of your [Code] section +// setArrayLength must specify the total number of dirs to be added +// Dir[0] contains first directory, Dir[1] contains second, etc. +// function ModPathDir(): TArrayOfString; +// var +// Dir: TArrayOfString; +// begin +// setArrayLength(Dir, 1) +// Dir[0] := ExpandConstant('{app}'); +// Result := Dir; +// end; +// #include "modpath.iss" +// ---------------------------------------------------------------------------- + +procedure ModPath(); +var + oldpath: String; + newpath: String; + pathArr: TArrayOfString; + aExecFile: String; + aExecArr: TArrayOfString; + i, d: Integer; + pathdir: TArrayOfString; +begin + // Get array of new directories and act on each individually + pathdir := ModPathDir(); + for d := 0 to GetArrayLength(pathdir)-1 do begin + + // Modify WinNT path + if UsingWinNT() = true then begin + + // Get current path, split into an array + RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', oldpath); + oldpath := oldpath + ';'; + i := 0; + while (Pos(';', oldpath) > 0) do begin + SetArrayLength(pathArr, i+1); + pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); + oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); + i := i + 1; + + // Check if current directory matches app dir + if pathdir[d] = pathArr[i-1] then begin + // if uninstalling, remove dir from path + if IsUninstaller() = true then begin + continue; + // if installing, abort because dir was already in path + end else begin + abort; + end; + end; + + // Add current directory to new path + if i = 1 then begin + newpath := pathArr[i-1]; + end else begin + newpath := newpath + ';' + pathArr[i-1]; + end; + end; + + // Append app dir to path if not already included + if IsUninstaller() = false then + newpath := newpath + ';' + pathdir[d]; + + // Write new path + RegWriteStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', newpath); + + // Modify Win9x path + end else begin + + // Convert to shortened dirname + pathdir[d] := GetShortName(pathdir[d]); + + // If autoexec.bat exists, check if app dir already exists in path + aExecFile := 'C:\AUTOEXEC.BAT'; + if FileExists(aExecFile) then begin + LoadStringsFromFile(aExecFile, aExecArr); + for i := 0 to GetArrayLength(aExecArr)-1 do begin + if IsUninstaller() = false then begin + // If app dir already exists while installing, abort add + if (Pos(pathdir[d], aExecArr[i]) > 0) then + abort; + end else begin + // If app dir exists and = what we originally set, then delete at uninstall + if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then + aExecArr[i] := ''; + end; + end; + end; + + // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path + if IsUninstaller() = false then begin + SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); + + // If uninstalling, write the full autoexec out + end else begin + SaveStringsToFile(aExecFile, aExecArr, False); + end; + end; + + // Write file to flag modifypath was selected + // Workaround since IsTaskSelected() cannot be called at uninstall and AppName and AppId cannot be "read" in Code section + if IsUninstaller() = false then + SaveStringToFile(ExpandConstant('{app}') + '\uninsTasks.txt', WizardSelectedTasks(False), False); + end; +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + appdir: String; + selectedTasks: String; +begin + appdir := ExpandConstant('{app}') + if CurUninstallStep = usUninstall then begin + if LoadStringFromFile(appdir + '\uninsTasks.txt', selectedTasks) then + if Pos('modifypath', selectedTasks) > 0 then + ModPath(); + DeleteFile(appdir + '\uninsTasks.txt') + end; +end; + +function NeedRestart(): Boolean; +begin + if IsTaskSelected('modifypath') and not UsingWinNT() then begin + Result := True; + end else begin + Result := False; + end; +end; -- 2.11.4.GIT