Win-Installer: fixes/rewrite for ability to create secondary installations.

git-svn-id: trunk@42527 -
This commit is contained in:
martin 2013-08-30 14:49:13 +00:00
parent 4e1b98a5f2
commit cac49d63f6
5 changed files with 226 additions and 85 deletions

View File

@ -5,7 +5,7 @@ function GetAppId(param:string): String;
var
s: String;
begin
if ( (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) ) or IsSecondaryUpdate then
if (IsSecondaryCheckBoxChecked) or IsSecondaryUpdate then
begin
// Secondary
s := RemoveBackslashUnlessRoot(Lowercase(WizardDirValue));
@ -23,7 +23,7 @@ function GetPCPForDelete(param:string): String;
// Name: {code:GetPCPForDelete}*.xml; Type: files; Tasks: delusersettings
// ... delete primary conf
begin
if ( (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) ) then
if (IsSecondaryCheckBoxChecked) then // or IsSecondaryUpdate
begin
if SecondPCP = '' then
Result := AddBackslash(WizardDirValue) // some fallback

View File

@ -1,10 +1,4 @@
type
TCfgFileState = (csNoFile, csUnreadable, csParsedOk);
var
NewCFGFile: TStringList;
function LoadCFGFile(AFolder: String; var AList: TStringList): Boolean;
var
cfgfile: String;
@ -32,30 +26,19 @@ begin
AList.add('--primary-config-path=' + APCP);
end;
function ParseCFGFile(AFolder: String; var APrimConfDir: String): TCfgFileState;
function ParseCFGList(AConfig: TStringList; var APrimConfDir: String): TCfgFileState;
var
s, cfgfile: String;
s: String;
i: Integer;
l: TStringList;
begin
cfgfile := AddBackslash(AFolder) + 'lazarus.cfg';
Result := csNoFile;
if not FileExists(cfgfile) then begin
Log('ParseCFGFile not existent');
exit;
end;
Result := csUnreadable;
l := TStringList.Create;
l.LoadFromFile(cfgfile);
for i := 0 to l.Count - 1 do
if copy(l[i], 1, 6) = '--pcp=' then
s := copy(l[i], 7, length(l[i]))
for i := 0 to AConfig.Count - 1 do
if copy(AConfig[i], 1, 6) = '--pcp=' then
s := copy(AConfig[i], 7, length(AConfig[i]))
else
if copy(l[i], 1, 22) = '--primary-config-path=' then
s := copy(l[i], 23, length(l[i]));
l.Free;
if copy(AConfig[i], 1, 22) = '--primary-config-path=' then
s := copy(AConfig[i], 23, length(AConfig[i]));
// AConfig.Free;
if s = '' then
exit;
@ -81,3 +64,23 @@ begin
Log('ParseCFGFile OK');
end;
function ParseCFGFile(AFolder: String; var APrimConfDir: String): TCfgFileState;
var
s, cfgfile: String;
i: Integer;
l: TStringList;
begin
cfgfile := AddBackslash(AFolder) + 'lazarus.cfg';
Result := csNoFile;
if not FileExists(cfgfile) then begin
Log('ParseCFGFile not existent');
exit;
end;
l := TStringList.Create;
l.LoadFromFile(cfgfile);
Result := ParseCFGList(l, APrimConfDir);
l.Free;
end;

View File

@ -2,6 +2,83 @@
var
wpAskConfDir: TInputDirWizardPage;
// Additional Elements on TargetDir wizard page
CheckSecondInstall: TCheckBox; // Also used by GetAppId
CheckSecondLabel: TLabel;
CfgLoadedFromDir: String; // The directory from which lazarus was uninstalled
CFGFileForLoadedFromDir: TStringList;
CFGPathForLoadedFromDir: String; // the PCP
CFGStateForLoadedFromDir: TCfgFileState;
Procedure ClearExistingConfigForFolder;
begin
CfgLoadedFromDir := '';
if CFGFileForLoadedFromDir <> nil then
CFGFileForLoadedFromDir.Clear;
CFGPathForLoadedFromDir := '';
CFGStateForLoadedFromDir := csNoFile;
end;
Procedure LoadExistingConfigForFolder(AFolder: String);
begin
CfgLoadedFromDir := AFolder;
LoadCFGFile(AFolder, CFGFileForLoadedFromDir);
CFGStateForLoadedFromDir := ParseCFGList(CFGFileForLoadedFromDir, CFGPathForLoadedFromDir);
end;
function HasConfigLoadedFromDir(AFolder: String; FallBackToUninstallDir: Boolean): Boolean;
begin
Result := (CfgLoadedFromDir = AFolder) and
(CFGFileForLoadedFromDir <> nil) and
(CFGFileForLoadedFromDir.Count > 0); // only if content
if (not Result) and FallBackToUninstallDir then
Result := HasSavedConfigFromUninstall(AFolder);
end;
// Did the loadedconf contain a pcp?
function HasPCPLoadedFromDir(AFolder: String; FallBackToUninstallDir: Boolean): Boolean;
begin
Result := False;
if HasConfigLoadedFromDir(AFolder, False) then
Result := CFGPathForLoadedFromDir <> ''
else
if FallBackToUninstallDir and HasSavedConfigFromUninstall(AFolder) then
Result := GetSavedPCPFromUninstall(AFolder) <> '';
end;
function GetConfigLoadedFromDir(AFolder: String; FallBackToUninstallDir: Boolean): TStringList;
begin
Result := nil;
if HasConfigLoadedFromDir(AFolder, False) then
Result := CFGFileForLoadedFromDir
else
if FallBackToUninstallDir and HasSavedConfigFromUninstall(AFolder) then
Result := GetSavedConfigFromUninstall(AFolder);
end;
function GetPCPLoadedFromDir(AFolder: String; FallBackToUninstallDir: Boolean): String;
begin
Result := '';
if HasConfigLoadedFromDir(AFolder, False) then
Result := CFGPathForLoadedFromDir
else
if FallBackToUninstallDir and HasSavedConfigFromUninstall(AFolder) then
Result := GetSavedPCPFromUninstall(AFolder);
end;
function GetStateLoadedFromDir(AFolder: String; FallBackToUninstallDir: Boolean): TCfgFileState;
begin
Result := csNoFile;
if HasConfigLoadedFromDir(AFolder, False) then
Result := CFGStateForLoadedFromDir
else
if FallBackToUninstallDir and HasSavedConfigFromUninstall(AFolder) then
Result := GetSavedStateFromUninstall(AFolder);
end;
Procedure AddSecondaryCheckBoxToTargetDirWizzard;
begin
if (CheckSecondInstall <> nil) then
@ -40,12 +117,26 @@ begin
wpAskConfDir.Add('Folder for config');
end;
Procedure CreateOrSaveConfigFile;
function IsSecondaryCheckBoxChecked: Boolean;
begin
if (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) then begin
if (NewCFGFile <> nil) then
Result := (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked);
end;
Procedure CreateOrSaveConfigFile;
var
CfgFile: TStringList;
begin
if not (IsSecondaryCheckBoxChecked or IsSecondaryUpdate) then
exit;
if IsSecondaryCheckBoxChecked then begin
CfgFile := GetConfigLoadedFromDir(WizardDirValue, True);
if (GetPCPLoadedFromDir(WizardDirValue, True) <> SecondPCP) or (CfgFile = nil) then
CreateCFGFile(SecondPCP, CfgFile);
if (SecondPCP <> '') then
try
NewCFGFile.SaveToFile(AddBackslash(WizardDirValue) + 'lazarus.cfg')
CfgFile.SaveToFile(AddBackslash(WizardDirValue) + 'lazarus.cfg')
ForceDirectories(SecondPCP);
except
MsgBox('Internal Error (1): Could not save CFG for secondary install', mbConfirmation, MB_OK);
@ -54,30 +145,35 @@ begin
MsgBox('Internal Error (2): Could not save CFG for secondary install', mbConfirmation, MB_OK);
end;
end
else
if (UninstallDoneState <> uiUnknown) and (IsSecondaryUpdate) and
// NO checkbox.checked
if (DidRunUninstaller) and (IsSecondaryUpdate) and
(not FileExists(AddBackslash(WizardDirValue) + 'lazarus.cfg'))
then begin
// cfg was uninstalled / restore
if (NewCFGFile <> nil) then
CfgFile := GetConfigLoadedFromDir(WizardDirValue, True);
if (CfgFile <> nil) then
try
NewCFGFile.SaveToFile(AddBackslash(WizardDirValue) + 'lazarus.cfg')
CfgFile.SaveToFile(AddBackslash(WizardDirValue) + 'lazarus.cfg')
except
MsgBox('Internal Error (3): Could not restore CFG for secondary install', mbConfirmation, MB_OK);
end
else
if (UninstDir = WizardDirValue) and (CFGFileForUninstDir <> nil) and
(CFGFileForUninstDir.count > 0)
then begin
try
CFGFileForUninstDir.SaveToFile(AddBackslash(WizardDirValue) + 'lazarus.cfg')
except
MsgBox('Internal Error (4): Could not restore CFG for secondary install', mbConfirmation, MB_OK);
end
end
else begin
begin
MsgBox('Internal Error (5): Could not restore CFG for secondary install', mbConfirmation, MB_OK);
end;
end;
end
else
// NO checkbox.checked
if (IsSecondaryUpdate) and
(not FileExists(AddBackslash(WizardDirValue) + 'lazarus.cfg'))
then begin
// where is the config gone ???????
MsgBox('Internal Error (4): Pre-Existing Configfile was removed?', mbConfirmation, MB_OK);
end
;
end;

View File

@ -20,8 +20,10 @@ var
UnInstaller: String; // Registry 'UninstallString'
PathEqual: Boolean;
UninstDir: String;
UninstDir: String; // The directory from which lazarus was uninstalled
CFGFileForUninstDir: TStringList;
CFGPathForUninstDir: String; // the PCP
CFGStateForUninstDir: TCfgFileState;
var
wpAskUnistall: TWizardPage;
@ -40,6 +42,41 @@ begin
end;
end;
function DidRunUninstaller: Boolean;
begin
Result := (UninstallDoneState <> uiUnknown);
end;
// check if: unistall was run, and run in AFolder, and did have a lazarus.cfg file
function HasSavedConfigFromUninstall(AFolder: String): Boolean;
begin
Result := DidRunUninstaller and
(UninstDir = AFolder) and
(CFGFileForUninstDir <> nil) and
(CFGFileForUninstDir.Count > 0); // only if content
end;
function GetSavedConfigFromUninstall(AFolder: String): TStringList;
begin
Result := nil;
if HasSavedConfigFromUninstall(AFolder) then
Result := CFGFileForUninstDir;
end;
function GetSavedPCPFromUninstall(AFolder: String): String;
begin
Result := '';
if HasSavedConfigFromUninstall(AFolder) then
Result := CFGPathForUninstDir;
end;
function GetSavedStateFromUninstall(AFolder: String): TCfgFileState;
begin
Result := csNoFile;
if HasSavedConfigFromUninstall(AFolder) then
Result := CFGStateForUninstDir;
end;
function GetUninstallData(ARegName: String): String; // Get one entry from registry e.g. 'UninstallString'
var
Path: String;
@ -89,7 +126,7 @@ begin
end
else
begin
if ( (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) ) or IsSecondaryUpdate then
if (IsSecondaryCheckBoxChecked) or IsSecondaryUpdate then
begin
ForcePrimaryAppId := True;
Log('REDO UninstallState '+GetUninstallData('Inno Setup: App Path')+' // '+WizardDirValue);
@ -138,7 +175,7 @@ begin
UpdateUninstallInfo;
Log('UnInstUpdateGUI UninstallState='+dbgsUiState(UninstallState)+
' IsSecondaryUpdate='+dbgsBool(IsSecondaryUpdate)+
' Check='+dbgsBool((CheckSecondInstall <> nil) and (CheckSecondInstall.Checked))
' Check='+dbgsBool(IsSecondaryCheckBoxChecked)
);
WizardForm.NextButton.Enabled := (UninstallState = uiDone) or (UninstallState = uiDestNeeded) or wpCheckBox.Checked;
@ -156,7 +193,7 @@ begin
Log('SkipAskUninst UninstallState='+dbgsUiState(UninstallState)+
', OldPath='+OldPath+' OldName='+OldName+' UnInstaller='+UnInstaller +
' IsSecondaryUpdate='+dbgsBool(IsSecondaryUpdate)+
' Check='+dbgsBool((CheckSecondInstall <> nil) and (CheckSecondInstall.Checked))
' Check='+dbgsBool(IsSecondaryCheckBoxChecked)
);
Result := UninstallState = uiDone;
if Result Then exit;
@ -253,8 +290,11 @@ begin
b := (UnInstaller <> '') and FileExists(UnInstaller);
if b then begin
LoadCFGFile(WizardDirValue, CFGFileForUninstDir);
UninstDir := WizardDirValue;
if PathEqual then begin
LoadCFGFile(OldPath, CFGFileForUninstDir);
CFGStateForUninstDir := ParseCFGList(CFGFileForUninstDir, CFGPathForUninstDir);
UninstDir := OldPath;
end;
if UninstallState = uiInconsistent then
b := Exec(UnInstaller, '/VERBOSE /NORESTART','', SW_SHOW, ewWaitUntilTerminated, i)

View File

@ -266,23 +266,30 @@ Name: ru; MessagesFile: lazarus.ru.isl
Name: sl; MessagesFile: compiler:Languages\Slovenian.isl
[Code]
type
TCfgFileState = (csNoFile, csUnreadable, csParsedOk);
var
ForcePrimaryAppId: Boolean; // GetAppId should ignore secondary
// Additional Elements on TargetDir wizard page
CheckSecondInstall: TCheckBox; // Also used by GetAppId
CheckSecondLabel: TLabel;
IsSecondaryUpdate: Boolean; // Also used by GetAppId
// User Selected
SecondPCP: String; // used by common.GetPCPForDelete
function IsSecondaryCheckBoxChecked: Boolean; forward; // in secondary.pas
function DidRunUninstaller: Boolean; forward; // in uninst.pas
function HasSavedConfigFromUninstall(AFolder: String): Boolean; forward; // in uninst.pas
function GetSavedConfigFromUninstall(AFolder: String): TStringList; forward; // in uninst.pas
function GetSavedPCPFromUninstall(AFolder: String): String; forward; // in uninst.pas
function GetSavedStateFromUninstall(AFolder: String): TCfgFileState; forward; // in uninst.pas
#include "innoscript\common.pas"
#include "innoscript\conffile.pas" ; // Check/Load lazarus.cfg file // Create TStringList data
#include "innoscript\uninst.pas" ; // Uninstall of previous installation
#include "innoscript\about.pas" ; // Info displayed during install progress
#include "innoscript\conffile.pas"
#include "innoscript\secondary.pas"
#include "innoscript\uninst.pas"
#include "innoscript\about.pas"
procedure CurPageChanged(CurPageID: Integer);
@ -311,6 +318,7 @@ begin
begin
Log('NextButton in SelectDir');
IsSecondaryUpdate := False;
ClearExistingConfigForFolder;
folder := WizardDirValue;
if Pos( ' ', folder ) > 0 then
@ -322,16 +330,21 @@ begin
end;
FolderEmpty := IsDirEmpty(folder);
LoadExistingConfigForFolder(folder);
IsSecondaryUpdate := HasPCPLoadedFromDir(folder, True); // check for uninstalled file too
SecondPCP := GetPCPLoadedFromDir(folder, True);
// TODO:
// If we came back AFTER running uninstall,
// AND changed the folder for and back (ending with the uninstall folder selected)
// TEHN we should ask, if the uninstalled (todo uninstall cfg file) should be restored?
UpdateUninstallInfo;
if FolderEmpty then
exit;
if ( (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) ) then
begin
// Secondary
// ALways set "SecondPCP", if avail
case ParseCFGFile(folder, SecondPCP) of
if (IsSecondaryCheckBoxChecked) then
begin // Secondary
case GetStateLoadedFromDir(folder, True) of
csNoFile: begin
Result := False;
MsgBox(Format(CustomMessage('FolderForSecondNoFile'), [#13#10]), mbConfirmation, MB_OK);
@ -355,33 +368,24 @@ begin
(UninstallState = uiInconsistent)
then begin
Result := MsgBox(Format(CustomMessage('FolderForSecondUpgrading'), [#13#10, SecondPCP]), mbConfirmation, MB_YESNO) = IDYES;
IsSecondaryUpdate := True;
UpdateUninstallInfo;
end;
end;
end;
// MUST always be loaded, if leaving this page
LoadCFGFile(folder, NewCFGFile);
end
else
begin
// Dir NOT empty: do not warn, if uiDestNeeded => folder content is updatable lazarus
if ((UninstallState = uiDone) or (UninstallState = UIOtherNeeded)) or
(UninstallState = uiInconsistent)
then
begin
// Dir NOT empty
Result := MsgBox(SaveCustomMessage('FolderNotEmpty', 'The target folder is not empty. Continue with installation?'),
mbConfirmation, MB_YESNO) = IDYES;
end;
if Result and
(ParseCFGFile(folder, SecondPCP) = csParsedOk)
then begin
IsSecondaryUpdate := True;
LoadCFGFile(folder, NewCFGFile);
UpdateUninstallInfo;
end;
if IsSecondaryUpdate then
Result := MsgBox(Format(SaveCustomMessage('FolderForSecondUpgrading', 'The target folder is not empty.%0:sIt contains a secondary Lazarus installation using the following folder for configuration:%0:s%1:s%0:s%0:sContinue with installation?'),
{}[#13#10, SecondPCP]), mbConfirmation, MB_YESNO) = IDYES
else
Result := MsgBox(SaveCustomMessage('FolderNotEmpty', 'The target folder is not empty. Continue with installation?'),
mbConfirmation, MB_YESNO) = IDYES;
end;
end;
end;
@ -395,7 +399,6 @@ begin
end;
SecondPCP := s;
CreateCFGFile(SecondPCP, NewCFGFile);
end;
end;
@ -405,11 +408,10 @@ begin
Result := False
if PageId = wpAskConfDir.ID then begin
Log('ShouldSkip AskConfDir IsSecondaryUpdate='+dbgsBool(IsSecondaryUpdate)+
' Check='+dbgsBool((CheckSecondInstall <> nil) and (CheckSecondInstall.Checked))
' Check='+dbgsBool(IsSecondaryCheckBoxChecked)
);
Result := (IsSecondaryUpdate) or
( (CheckSecondInstall = nil) or (not CheckSecondInstall.Checked) );
Result := (not IsSecondaryCheckBoxChecked) or IsSecondaryUpdate;
end;
// UnInst uses: SkipAskUninst()
end;
@ -431,7 +433,7 @@ begin
Result := Result + MemoGroupInfo + NewLine;
if MemoTasksInfo <> '' then
Result := Result + MemoTasksInfo + NewLine;
if (CheckSecondInstall <> nil) and (CheckSecondInstall.Checked) then begin
if (IsSecondaryCheckBoxChecked) then begin
if IsSecondaryUpdate then
Result := Result + Format(SaveCustomMessage('SecondTaskUpdate', ''), [NewLine, Space, SecondPCP])
else