Browse Source

* Re-factored parsing of configuration-file, to be able to add support for include-files

git-svn-id: trunk@34315 -
joost 9 years ago
parent
commit
5d4682349d

+ 9 - 9
packages/fppkg/src/pkgcommands.pp

@@ -240,17 +240,17 @@ var
 begin
   // Download and load mirrors.xml
   // This can be skipped when a custom RemoteRepository is configured
-  if (GlobalOptions.RemoteMirrorsURL<>'') and
-     (GlobalOptions.RemoteRepository='auto') then
+  if (GlobalOptions.GlobalSection.RemoteMirrorsURL<>'') and
+     (GlobalOptions.GlobalSection.RemoteRepository='auto') then
     begin
-      Log(llCommands,SLogDownloading,[GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile]);
-      DownloadFile(GlobalOptions.RemoteMirrorsURL,GlobalOptions.LocalMirrorsFile);
+      Log(llCommands,SLogDownloading,[GlobalOptions.GlobalSection.RemoteMirrorsURL,GlobalOptions.GlobalSection.LocalMirrorsFile]);
+      DownloadFile(GlobalOptions.GlobalSection.RemoteMirrorsURL,GlobalOptions.GlobalSection.LocalMirrorsFile);
       LoadLocalAvailableMirrors;
     end;
   // Download packages.xml
   PackagesURL:=GetRemoteRepositoryURL(PackagesFileName);
-  Log(llCommands,SLogDownloading,[PackagesURL,GlobalOptions.LocalPackagesFile]);
-  DownloadFile(PackagesURL,GlobalOptions.LocalPackagesFile);
+  Log(llCommands,SLogDownloading,[PackagesURL,GlobalOptions.GlobalSection.LocalPackagesFile]);
+  DownloadFile(PackagesURL,GlobalOptions.GlobalSection.LocalPackagesFile);
   // Read the repository again
   LoadLocalAvailableRepository;
   // no need to log errors again
@@ -260,7 +260,7 @@ end;
 
 procedure TCommandListPackages.Execute;
 begin
-  ListPackages(GlobalOptions.ShowLocation);
+  ListPackages(GlobalOptions.CommandLineSection.ShowLocation);
 end;
 
 
@@ -395,7 +395,7 @@ var
       end
     else
       begin
-        if (IsSuperUser or GlobalOptions.InstallGlobal) then
+        if (IsSuperUser or GlobalOptions.CommandLineSection.InstallGlobal) then
           Result:=CompilerOptions.GlobalUnitDir
         else
           Result:=CompilerOptions.LocalUnitDir;
@@ -420,7 +420,7 @@ var
       end
     else
       begin
-        if (IsSuperUser or GlobalOptions.InstallGlobal) then
+        if (IsSuperUser or GlobalOptions.CommandLineSection.InstallGlobal) then
           Result:=CompilerOptions.GlobalInstallDir
         else
           Result:=CompilerOptions.LocalInstallDir;

+ 3 - 3
packages/fppkg/src/pkgdownload.pp

@@ -76,7 +76,7 @@ procedure DownloadFile(const RemoteFile,LocalFile:String);
 var
   DownloaderClass : TBaseDownloaderClass;
 begin
-  DownloaderClass:=GetDownloader(GlobalOptions.Downloader);
+  DownloaderClass:=GetDownloader(GlobalOptions.GlobalSection.Downloader);
   with DownloaderClass.Create(nil) do
     try
       Download(RemoteFile,LocalFile);
@@ -165,7 +165,7 @@ var
   P : TFPPackage;
 begin
   P:=AvailableRepository.PackageByName(PackageName);
-  DownloaderClass:=GetDownloader(GlobalOptions.Downloader);
+  DownloaderClass:=GetDownloader(GlobalOptions.GlobalSection.Downloader);
   with DownloaderClass.Create(nil) do
     try
       Log(llCommands,SLogDownloading,[PackageRemoteArchive(P),PackageLocalArchive(P)]);
@@ -173,7 +173,7 @@ begin
 
       // Force the existing of the archives-directory if it is being used
       if (P.Name<>CurrentDirPackageName) and (P.Name<>CmdLinePackageName) then
-        ForceDirectories(GlobalOptions.ArchivesDir);
+        ForceDirectories(GlobalOptions.GlobalSection.ArchivesDir);
 
       Download(PackageRemoteArchive(P),PackageLocalArchive(P));
     finally

+ 4 - 4
packages/fppkg/src/pkgfpmake.pp

@@ -241,7 +241,7 @@ begin
       // Call compiler
       If ExecuteProcess(FPMakeCompilerOptions.Compiler,OOptions+' '+FPmakeSrc)<>0 then
         begin
-          if not GlobalOptions.RecoveryMode then
+          if not GlobalOptions.CommandLineSection.RecoveryMode then
             Error(SErrCompileFailureFPMakeTryRecovery)
           else
             Error(SErrCompileFailureFPMake);
@@ -336,10 +336,10 @@ begin
       if CompilerOptions.HasOptions then
         AddOption('--options='+CompilerOptions.Options.DelimitedText);
 
-      if GlobalOptions.CustomFPMakeOptions<>'' then
+      if GlobalOptions.GlobalSection.CustomFPMakeOptions<>'' then
         begin
         AddOption('--ignoreinvalidoption');
-        AddOption(GlobalOptions.CustomFPMakeOptions);
+        AddOption(GlobalOptions.GlobalSection.CustomFPMakeOptions);
         end;
     end;
 
@@ -347,7 +347,7 @@ begin
   AddOption('--compiler='+CompilerOptions.Compiler);
   AddOption('--cpu='+CPUToString(CompilerOptions.CompilerCPU));
   AddOption('--os='+OSToString(CompilerOptions.CompilerOS));
-  if IsSuperUser or GlobalOptions.InstallGlobal then
+  if IsSuperUser or GlobalOptions.CommandLineSection.InstallGlobal then
     begin
       CondAddOption('--prefix',CompilerOptions.GlobalPrefix);
       CondAddOption('--baseinstalldir',CompilerOptions.GlobalInstallDir);

+ 3 - 3
packages/fppkg/src/pkghandler.pp

@@ -138,11 +138,11 @@ begin
         Result:=CurrentDir;
     end
   else if (APackage.Name=CmdLinePackageName) or (APackage.Name=URLPackageName) then
-    Result:=GlobalOptions.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
+    Result:=GlobalOptions.GlobalSection.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'')
   else if (APackage.RecompileBroken) and (APackage.SourcePath<>'') then
     Result:=APackage.SourcePath
   else
-    Result:=GlobalOptions.BuildDir+APackage.Name;
+    Result:=GlobalOptions.GlobalSection.BuildDir+APackage.Name;
 end;
 
 
@@ -166,7 +166,7 @@ begin
   else if APackage.Name=CmdLinePackageName then
     Result:=APackage.LocalFileName
   else
-    Result:=GlobalOptions.ArchivesDir+APackage.FileName;
+    Result:=GlobalOptions.GlobalSection.ArchivesDir+APackage.FileName;
 end;
 
 

+ 15 - 12
packages/fppkg/src/pkgmessages.pp

@@ -42,7 +42,7 @@ Resourcestring
   SErrPackageIsLocal         = 'Operation not supported for local packages';
   SErrConvertFPMakeExists    = 'Found existing fpmake.pp, aborting conversion';
   SErrFailedToSelectMirror   = 'Could not select a mirror, run update and retry';
-  SErrUnsupportedConfigVersion = 'Configuration file "%s" is too old, delete file manual and retry';
+  SErrUnsupportedConfigVersion = 'Configuration file is too old, delete file manual and retry';
   SErrPackageDoesNotSupportTarget = 'Package %s does not support %s';
   SErrHTTPGetFailed          = 'HTTP Download failed.';
   SErrLoginFailed            = 'FTP LOGIN command failed.';
@@ -60,7 +60,7 @@ Resourcestring
   SLogDownloading            = 'Downloading "%s" to "%s"';
   SLogUnzippping             = 'Unzipping "%s"';
   SLogZippping               = 'Zipping "%s"';
-  SLogLoadingGlobalConfig    = 'Loading global configuration from "%s"';
+  SLogLoadingGlobalConfig    = 'Loaded global configuration from "%s"';
   SLogLoadingCompilerConfig  = 'Loading compiler configuration from "%s"';
   SLogLoadingFPMakeCompilerConfig = 'Loading compiler configuration for fpmake building from "%s"';
   SLogGeneratingGlobalConfig = 'Generating default global configuration in "%s"';
@@ -76,21 +76,24 @@ Resourcestring
   SLogFPMKUnitDepVersion     = 'Checking for %s %s, installed %s, available %s';
   SLogFPMKUnitDepTooOld      = 'Minimum version of %s is not installed, using internal fpmkunit with limited functionality';
   SLogSelectedMirror         = 'Selected mirror "%s"';
+  SLogStartLoadingConfFile   = 'Start loading configuration file "%s"';
   SLogUpgradingConfig        = 'Configuration file "%s" is updated with new configuration settings';
+  SLogOldConfigFileFormat    = 'Configuration file is in an old format';
   SLogPackageDependency      = 'Dependency on package %s %s, installed %s, available %s  (%s)';
   SLogPackageChecksumChanged = 'Package %s needs to be rebuild, dependency %s is modified';
   SLogCheckBrokenDependenvies= 'Checking for broken dependencies';
 
-  SLogGlobalCfgHeader                = 'Using global configuration from file "%s":';
-  SLogGlobalCfgRemoteMirrorsURL      = ' RemoteMirrorsURL:      %s';
-  SLogGlobalCfgRemoteRepository      = ' RemoteRepository:      %s';
-  SLogGlobalCfgLocalRepository       = ' LocalRepository:       "%s" -> "%s"';
-  SLogGlobalCfgBuildDir              = ' BuildDir:              "%s" -> "%s"';
-  SLogGlobalCfgArchivesDir           = ' ArchivesDir:           "%s" -> "%s"';
-  SLogGlobalCfgCompilerConfigDir     = ' CompilerConfigDir:     "%s" -> "%s"';
-  SLogGlobalCfgDefaultCompilerConfig = ' DefaultCompilerConfig: "%s"';
-  SLogGlobalCfgFPMakeCompilerConfig  = ' FPMakeCompilerConfig:  "%s"';
-  SLogGlobalCfgDownloader            = ' Downloader:            %s';
+  SLogCfgHeader                      = 'Settings from configuration-files:';
+  SLogCfgSectionHeader               = ' %s-section:';
+  SLogGlobalCfgRemoteMirrorsURL      = '  RemoteMirrorsURL:      %s';
+  SLogGlobalCfgRemoteRepository      = '  RemoteRepository:      %s';
+  SLogGlobalCfgLocalRepository       = '  LocalRepository:       "%s" -> "%s"';
+  SLogGlobalCfgBuildDir              = '  BuildDir:              "%s" -> "%s"';
+  SLogGlobalCfgArchivesDir           = '  ArchivesDir:           "%s" -> "%s"';
+  SLogGlobalCfgCompilerConfigDir     = '  CompilerConfigDir:     "%s" -> "%s"';
+  SLogGlobalCfgDefaultCompilerConfig = '  DefaultCompilerConfig: "%s"';
+  SLogGlobalCfgFPMakeCompilerConfig  = '  FPMakeCompilerConfig:  "%s"';
+  SLogGlobalCfgDownloader            = '  Downloader:            %s';
   SLogCompilerCfgHeader           = 'Using %scompiler configuration file "%s":';
   SLogCompilerCfgCompiler         = ' Compiler:         "%s"';
   SLogCompilerCfgTarget           = ' Target:           %s';

+ 429 - 223
packages/fppkg/src/pkgoptions.pp

@@ -17,83 +17,137 @@ unit pkgoptions;
 interface
 
 // pkgglobals must be AFTER fpmkunit
-uses Classes, Sysutils, Inifiles, fprepos, fpTemplate, fpmkunit, pkgglobals;
+uses Classes, Sysutils, Inifiles, fprepos, fpTemplate, fpmkunit, pkgglobals, fgl;
 
 Const
   UnitConfigFileName   = 'fpunits.cfg';
   ManifestFileName     = 'manifest.xml';
   MirrorsFileName      = 'mirrors.xml';
   PackagesFileName     = 'packages.xml';
-  VersionsFileName     = 'versions-%s.dat';
-  CurrentConfigVersion = 4;
+  MinSupportedConfigVersion = 4;
+  CurrentConfigVersion = 5;
 
 Type
 
-  { TGlobalOptions }
+  { TFppkgOptionSection }
 
-  TGlobalOptions = Class(TPersistent)
+  TFppkgOptionSection = class(TPersistent)
   private
-    FConfigFilename: string;
-    FSaveInifileChanges : Boolean;
-    FConfigVersion : Integer;
-    FRemoteMirrorsURL,
-    FRemoteRepository,
-    FLocalRepository,
-    FCompilerConfigDir,
-    FArchivesDir,
-    FBuildDir,
-    FDownloader,
-    FDefaultCompilerConfig,
-    FFPMakeCompilerConfig : String;
-    // Parameter options
-    FCompilerConfig : String;
-    FAllowBroken,
-    FInstallGlobal,
-    FRecoveryMode   : Boolean;
+    FName: string;
+  public
+    procedure AddKeyValue(const AKey, AValue: string); virtual;
+    procedure SaveToStrings(AStrings: TStrings); virtual;
+    procedure LogValues(ALogLevel: TLogLevel); virtual;
+    function AllowDuplicate: Boolean; virtual;
+
+    property Name: string read FName write FName;
+  end;
+  TFppkgOptionSectionList = specialize TFPGObjectList<TFppkgOptionSection>;
+
+  { TFppkgGLobalOptionSection }
+
+  TFppkgGlobalOptionSection = class(TFppkgOptionSection)
+  private
+    FCustomFPMakeOptions: string;
     FOptionParser: TTemplateParser;
-    FShowLocation: Boolean;
-    FSkipConfigurationFiles: boolean;
-    FSkipFixBrokenAfterInstall: boolean;
-    FCustomFPMakeOptions : string;
-    function  GetOptString(Index: integer): String;
-    procedure SetOptString(Index: integer; const AValue: String);
-    procedure UpdateLocalRepositoryOption;
-  Public
-    Constructor Create;
+
+    FBuildDir: string;
+    FCompilerConfigDir: string;
+    FConfigVersion: integer;
+    FCompilerConfig: string;
+    FDownloader: string;
+    FFPMakeCompilerConfig: string;
+    FLocalRepository: string;
+    FRemoteMirrorsURL: string;
+    FRemoteRepository: string;
+    FArchivesDir: string;
+    function GetArchivesDir: string;
+    function GetBuildDir: string;
+    function GetCompilerConfigDir: string;
+    function GetLocalRepository: string;
+    procedure SetArchivesDir(AValue: string);
+    procedure SetBuildDir(AValue: string);
+    procedure SetCompilerConfigDir(AValue: string);
+    procedure SetConfigVersion(AValue: integer);
+    procedure SetCompilerConfig(AValue: string);
+    procedure SetCustomFPMakeOptions(AValue: string);
+    procedure SetDownloader(AValue: string);
+    procedure SetFPMakeCompilerConfig(AValue: string);
+    procedure SetLocalRepository(AValue: string);
+    procedure SetRemoteMirrorsURL(AValue: string);
+    procedure SetRemoteRepository(AValue: string);
+  public
+    constructor Create;
     destructor Destroy; override;
-    Procedure InitGlobalDefaults;
-    Procedure LoadGlobalFromFile(const AFileName : String);
-    Procedure SaveGlobalToFile(const AFileName : String);
-    procedure LogValues(ALogLevel: TLogLevel);
-    // Is set when the inifile has an old version number (which is also the case when a new file is generated)
-    Property SaveInifileChanges : Boolean Read FSaveInifileChanges;
-    Property ConfigVersion : Integer read FConfigVersion;
-    function LocalPackagesFile:string;
+    procedure AddKeyValue(const AKey, AValue: string); override;
+    procedure SaveToStrings(AStrings: TStrings); override;
+    procedure LogValues(ALogLevel: TLogLevel); override;
+
     function LocalMirrorsFile:string;
-    function LocalVersionsFile(const ACompilerConfig:String):string;
-  Published
-    Property RemoteMirrorsURL : String Index 0 Read GetOptString Write SetOptString;
-    // 1 is unused
-    Property RemoteRepository : String Index 2 Read GetOptString Write SetOptString;
-    Property LocalRepository : String Index 3 Read GetOptString Write SetOptString;
-    Property BuildDir : String Index 4 Read GetOptString Write SetOptString;
-    Property ArchivesDir : String Index 5 Read GetOptString Write SetOptString;
-    Property CompilerConfigDir : String Index 6 Read GetOptString Write SetOptString;
-    Property DefaultCompilerConfig : String Index 8 Read GetOptString Write SetOptString;
-    Property FPMakeCompilerConfig : String Index 9 Read GetOptString Write SetOptString;
-    Property Downloader: String Index 10 Read GetOptString Write SetOptString;
-    Property CustomFPMakeOptions: String Index 11 Read GetOptString Write SetOptString;
-    // Parameters
-    Property CompilerConfig : String Read FCompilerConfig Write FCompilerConfig;
-    Property InstallGlobal : Boolean Read FInstallGlobal Write FInstallGlobal;
-    Property RecoveryMode : Boolean Read FRecoveryMode Write FRecoveryMode;
-    Property AllowBroken : Boolean Read FAllowBroken Write FAllowBroken;
-    Property ShowLocation : Boolean Read FShowLocation Write FShowLocation;
-    Property SkipConfigurationFiles: boolean read FSkipConfigurationFiles write FSkipConfigurationFiles;
-    Property SkipFixBrokenAfterInstall: boolean read FSkipFixBrokenAfterInstall write FSkipFixBrokenAfterInstall;
+    function LocalPackagesFile:string;
+
+    property ConfigVersion: integer read FConfigVersion write SetConfigVersion;
+    property LocalRepository: string read GetLocalRepository write SetLocalRepository;
+    property BuildDir: string read GetBuildDir write SetBuildDir;
+    property CompilerConfigDir: string read GetCompilerConfigDir write SetCompilerConfigDir;
+    property ArchivesDir: string read GetArchivesDir write SetArchivesDir;
+    property Downloader: string read FDownloader write SetDownloader;
+    property CompilerConfig: string read FCompilerConfig write SetCompilerConfig;
+    property FPMakeCompilerConfig: string read FFPMakeCompilerConfig write SetFPMakeCompilerConfig;
+    property RemoteRepository: string read FRemoteRepository write SetRemoteRepository;
+    property RemoteMirrorsURL: string read FRemoteMirrorsURL write SetRemoteMirrorsURL;
+    Property CustomFPMakeOptions: string read FCustomFPMakeOptions Write SetCustomFPMakeOptions;
+  end;
+
+  { TFppkgCustomOptionSection }
+
+  TFppkgCustomOptionSection = class(TFppkgOptionSection);
+
+  { TFppkgCommandLineOptionSection }
+
+  TFppkgCommandLineOptionSection = class(TFppkgOptionSection)
+  private
+    FAllowBroken: Boolean;
+    FCompilerConfig: string;
+    FInstallGlobal: Boolean;
+    FRecoveryMode: Boolean;
+    FShowLocation: Boolean;
+    FSkipConfigurationFiles: Boolean;
+    FSkipFixBrokenAfterInstall: Boolean;
+  public
+    constructor Create;
+    property RecoveryMode: Boolean read FRecoveryMode write FRecoveryMode;
+    property InstallGlobal: Boolean read FInstallGlobal write FInstallGlobal;
+    property ShowLocation: Boolean read FShowLocation write FShowLocation;
+    property CompilerConfig : string read FCompilerConfig write FCompilerConfig;
+    property SkipConfigurationFiles: Boolean read FSkipConfigurationFiles write FSkipConfigurationFiles;
+    property AllowBroken : Boolean read FAllowBroken write FAllowBroken;
+    property SkipFixBrokenAfterInstall: Boolean read FSkipFixBrokenAfterInstall write FSkipFixBrokenAfterInstall;
   end;
 
 
+  { TFppkgOptions }
+
+  TFppkgOptions = class(TPersistent)
+  private
+    FSectionList: TFppkgOptionSectionList;
+    function GetCommandLineSection: TFppkgCommandLineOptionSection;
+    function GetGlobalSection: TFppkgGLobalOptionSection;
+    function GetSectionList: TFppkgOptionSectionList;
+  public
+    constructor Create();
+    destructor Destroy; override;
+
+    procedure LoadFromFile(const AFileName: string);
+    procedure SaveToFile(const AFileName: string);
+    function GetSectionByName(const SectionName: string): TFppkgOptionSection;
+    procedure LogValues(ALogLevel: TLogLevel);
+
+    property SectionList: TFppkgOptionSectionList read GetSectionList;
+    property GlobalSection: TFppkgGLobalOptionSection read GetGlobalSection;
+    property CommandLineSection: TFppkgCommandLineOptionSection read GetCommandLineSection;
+  end;
+
   { TCompilerOptions }
 
   TCompilerOptions = Class(TPersistent)
@@ -145,7 +199,8 @@ Type
   end;
 
 var
-  GlobalOptions : TGlobalOptions;
+  GlobalOptions : TFppkgOptions;
+
   CompilerOptions : TCompilerOptions;
   FPMakeCompilerOptions : TCompilerOptions;
 
@@ -173,7 +228,9 @@ Const
   KeyConfigVersion         = 'ConfigVersion';
 
   // Global config
-  KeyRemoteMirrorsURL = 'RemoteMirrors';
+  KeyDeprGlobalSection     = 'Defaults';
+  KeyGlobalSection         = 'Global';
+  KeyRemoteMirrorsURL      = 'RemoteMirrors';
   KeyRemoteRepository      = 'RemoteRepository';
   KeyLocalRepository       = 'LocalRepository';
   KeyArchivesDir           = 'ArchivesDir';
@@ -225,7 +282,7 @@ begin
               if not IsSuperUser then // Make a local, not global, configuration file
                 cfgfile:=GetAppConfigFile(False,False);
               ForceDirectories(ExtractFilePath(cfgfile));
-              GlobalOptions.SaveGlobalToFile(cfgfile);
+              GlobalOptions.SaveToFile(cfgfile);
               GeneratedConfig:=true;
             end;
         end;
@@ -233,11 +290,9 @@ begin
   // Load file or create new default configuration
   if not GeneratedConfig then
     begin
-      GlobalOptions.LoadGlobalFromFile(cfgfile);
-      if GlobalOptions.SaveInifileChanges and (not UseGlobalConfig or IsSuperUser) then
-        GlobalOptions.SaveGlobalToFile(cfgfile);
+      GlobalOptions.LoadFromFile(cfgfile);
     end;
-  GlobalOptions.CompilerConfig:=GlobalOptions.DefaultCompilerConfig;
+  GlobalOptions.CommandLineSection.CompilerConfig:=GlobalOptions.GlobalSection.CompilerConfig;
   // Tracing of what we've done above, need to be done after the verbosity is set
   if GeneratedConfig then
     pkgglobals.Log(llDebug,SLogGeneratingGlobalConfig,[cfgfile])
@@ -260,7 +315,7 @@ var
   S : String;
 begin
   // Load default compiler config
-  S:=GlobalOptions.CompilerConfigDir+GlobalOptions.CompilerConfig;
+  S:=GlobalOptions.GlobalSection.CompilerConfigDir+GlobalOptions.GlobalSection.CompilerConfig;
   CompilerOptions.UpdateLocalRepositoryOption;
   if FileExists(S) then
     begin
@@ -270,7 +325,7 @@ begin
   else
     begin
       // Generate a default configuration if it doesn't exists
-      if GlobalOptions.CompilerConfig='default' then
+      if GlobalOptions.GlobalSection.CompilerConfig='default' then
         begin
           pkgglobals.Log(llDebug,SLogGeneratingCompilerConfig,[S]);
           CompilerOptions.InitCompilerDefaults;
@@ -284,7 +339,7 @@ begin
   // Log compiler configuration
   CompilerOptions.LogValues(llDebug,'');
   // Load FPMake compiler config, this is normally the same config as above
-  S:=GlobalOptions.CompilerConfigDir+GlobalOptions.FPMakeCompilerConfig;
+  S:=GlobalOptions.GlobalSection.CompilerConfigDir+GlobalOptions.GlobalSection.FPMakeCompilerConfig;
   FPMakeCompilerOptions.UpdateLocalRepositoryOption;
   if FileExists(S) then
     begin
@@ -299,232 +354,383 @@ begin
   FPMakeCompilerOptions.LogValues(llDebug,'fpmake-building ');
 end;
 
+{ TFppkgCommandLineOptionSection }
+
+constructor TFppkgCommandLineOptionSection.Create;
+begin
+  // Parameter defaults
+  FInstallGlobal:=False;
+  FRecoveryMode:=False;
+  FAllowBroken:=False;
+end;
+
+{ TFppkgOptionSection }
+
+procedure TFppkgOptionSection.AddKeyValue(const AKey, AValue: string);
+begin
+  // Do nothing
+end;
+
+procedure TFppkgOptionSection.SaveToStrings(AStrings: TStrings);
+begin
+  // Do nothing
+end;
+
+procedure TFppkgOptionSection.LogValues(ALogLevel: TLogLevel);
+begin
+  log(ALogLevel,SLogCfgSectionHeader, [Trim(Name)]);
+end;
+
+function TFppkgOptionSection.AllowDuplicate: Boolean;
+begin
+  Result:=False;
+end;
 
 {*****************************************************************************
-                           TGlobalOptions
+                      TFppkgGlobalOptionSection
 *****************************************************************************}
 
-constructor TGlobalOptions.Create;
+procedure TFppkgGlobalOptionSection.SetBuildDir(AValue: string);
 begin
-  FOptionParser := TTemplateParser.Create;
-  FOptionParser.Values['AppConfigDir'] := GetAppConfigDir(false);
-  FOptionParser.Values['UserDir'] := GetUserDir;
-  InitGlobalDefaults;
+  if FBuildDir = AValue then Exit;
+  FBuildDir := fpmkunit.FixPath(AValue, True);
 end;
 
-destructor TGlobalOptions.Destroy;
+function TFppkgGlobalOptionSection.GetCompilerConfigDir: string;
 begin
-  FOptionParser.Free;
-  inherited Destroy;
+  Result := FOptionParser.ParseString(FCompilerConfigDir);
 end;
 
+function TFppkgGlobalOptionSection.GetLocalRepository: string;
+begin
+  Result := FOptionParser.ParseString(FLocalRepository);
+end;
 
-function TGlobalOptions.GetOptString(Index: integer): String;
+procedure TFppkgGlobalOptionSection.SetArchivesDir(AValue: string);
 begin
-  Case Index of
-    0 : Result:=FRemoteMirrorsURL;
-    2 : Result:=FRemoteRepository;
-    3 : Result:=FOptionParser.ParseString(FLocalRepository);
-    4 : Result:=FOptionParser.ParseString(FBuildDir);
-    5 : Result:=FOptionParser.ParseString(FArchivesDir);
-    6 : Result:=FOptionParser.ParseString(FCompilerConfigDir);
-    8 : Result:=FDefaultCompilerConfig;
-    9 : Result:=FFPMakeCompilerConfig;
-   10 : Result:=FDownloader;
-   11 : Result:=FCustomFPMakeOptions;
-    else
-      Error('Unknown option');
-  end;
+  if FArchivesDir = AValue then Exit;
+  FArchivesDir := fpmkunit.FixPath(AValue, True);
 end;
 
-procedure TGlobalOptions.SetOptString(Index: integer; const AValue: String);
+function TFppkgGlobalOptionSection.GetBuildDir: string;
 begin
-  If AValue=GetOptString(Index) then
-    Exit;
-  Case Index of
-    1 : FRemoteMirrorsURL:=AValue;
-    2 : FRemoteRepository:=AValue;
-    3 : begin
-          FLocalRepository:=AValue;
-          UpdateLocalRepositoryOption;
-        end;
-    4 : FBuildDir:=fpmkunit.FixPath(AValue, True);
-    5 : FArchivesDir:=fpmkunit.FixPath(AValue, True);
-    6 : FCompilerConfigDir:=fpmkunit.FixPath(AValue, True);
-    8 : FDefaultCompilerConfig:=AValue;
-    9 : FFPMakeCompilerConfig:=AValue;
-    10 : FDownloader:=AValue;
-    11 : FCustomFPMakeOptions:=AValue;
-    else
-      Error('Unknown option');
-  end;
+  Result := FOptionParser.ParseString(FBuildDir);
 end;
 
+function TFppkgGlobalOptionSection.GetArchivesDir: string;
+begin
+  Result := FOptionParser.ParseString(FArchivesDir);
+end;
 
-procedure TGlobalOptions.UpdateLocalRepositoryOption;
+procedure TFppkgGlobalOptionSection.SetCompilerConfigDir(AValue: string);
 begin
-  FOptionParser.Values['LocalRepository'] := LocalRepository;
+  if FCompilerConfigDir = AValue then Exit;
+  FCompilerConfigDir := fpmkunit.FixPath(AValue, True);
+end;
+
+procedure TFppkgGlobalOptionSection.SetConfigVersion(AValue: integer);
+begin
+  if FConfigVersion = AValue then Exit;
+  FConfigVersion := AValue;
 end;
 
+procedure TFppkgGlobalOptionSection.SetCompilerConfig(AValue: string);
+begin
+  if FCompilerConfig = AValue then Exit;
+  FCompilerConfig := AValue;
+end;
 
-function TGlobalOptions.LocalPackagesFile:string;
+procedure TFppkgGlobalOptionSection.SetCustomFPMakeOptions(AValue: string);
 begin
-  Result:=LocalRepository+PackagesFileName;
+  if FCustomFPMakeOptions = AValue then Exit;
+  FCustomFPMakeOptions := AValue;
 end;
 
+procedure TFppkgGlobalOptionSection.SetDownloader(AValue: string);
+begin
+  if FDownloader = AValue then Exit;
+  FDownloader := AValue;
+end;
 
-function TGlobalOptions.LocalMirrorsFile:string;
+procedure TFppkgGlobalOptionSection.SetFPMakeCompilerConfig(AValue: string);
 begin
-  Result:=LocalRepository+MirrorsFileName;
+  if FFPMakeCompilerConfig = AValue then Exit;
+  FFPMakeCompilerConfig := AValue;
 end;
 
+procedure TFppkgGlobalOptionSection.SetLocalRepository(AValue: string);
+begin
+  if FLocalRepository = AValue then Exit;
+  FLocalRepository := AValue;
+  FOptionParser.Values['LocalRepository'] := LocalRepository;
+end;
 
-function TGlobalOptions.LocalVersionsFile(const ACompilerConfig:String):string;
+procedure TFppkgGlobalOptionSection.SetRemoteMirrorsURL(AValue: string);
 begin
-  Result:=LocalRepository+Format(VersionsFileName,[ACompilerConfig]);
+  if FRemoteMirrorsURL = AValue then Exit;
+  FRemoteMirrorsURL := AValue;
 end;
 
+procedure TFppkgGlobalOptionSection.SetRemoteRepository(AValue: string);
+begin
+  if FRemoteRepository = AValue then Exit;
+  FRemoteRepository := AValue;
+end;
 
-Procedure TGlobalOptions.InitGlobalDefaults;
-var
-  i: Integer;
+constructor TFppkgGlobalOptionSection.Create;
 begin
-  FConfigVersion:=CurrentConfigVersion;
+  FOptionParser := TTemplateParser.Create;
+  FOptionParser.Values['AppConfigDir'] := GetAppConfigDir(false);
+  FOptionParser.Values['UserDir'] := GetUserDir;
+
   // Retrieve Local fppkg directory
 {$ifdef unix}
   if IsSuperUser then
     begin
       if DirectoryExists('/usr/local/lib/fpc') then
-        FLocalRepository:='/usr/local/lib/fpc/fppkg/'
+        LocalRepository:='/usr/local/lib/fpc/fppkg/'
       else
-        FLocalRepository:='/usr/lib/fpc/fppkg/';
+        LocalRepository:='/usr/lib/fpc/fppkg/';
     end
   else
-    FLocalRepository:='{UserDir}.fppkg/';
+    LocalRepository:='{UserDir}.fppkg/';
 {$else}
   if IsSuperUser then
-    FLocalRepository:=IncludeTrailingPathDelimiter(GetAppConfigDir(true))
+    LocalRepository:=IncludeTrailingPathDelimiter(GetAppConfigDir(true))
   else
-    FLocalRepository:='{AppConfigDir}';
+    LocalRepository:='{AppConfigDir}';
 {$endif}
-  UpdateLocalRepositoryOption;
-  // Directories
-  FBuildDir:='{LocalRepository}build'+PathDelim;
-  FArchivesDir:='{LocalRepository}archives'+PathDelim;
-  FCompilerConfigDir:='{LocalRepository}config'+PathDelim;
-  // Remote
+
+  ConfigVersion := CurrentConfigVersion;
+  CompilerConfig := 'default';
+  FPMakeCompilerConfig := 'default';
+  RemoteRepository := DefaultRemoteRepository;
   FRemoteMirrorsURL:=DefaultMirrorsURL;
-  FRemoteRepository:=DefaultRemoteRepository;
-  // Other config
-  FDefaultCompilerConfig:='default';
-  FFPMakeCompilerConfig:='default';
-  // Downloader
+
+  // Directories
+  BuildDir:='{LocalRepository}build'+PathDelim;
+  ArchivesDir:='{LocalRepository}archives'+PathDelim;
+  CompilerConfigDir:='{LocalRepository}config'+PathDelim;
 {$if defined(unix) or defined(windows)}
-  FDownloader:='lnet';
+  Downloader:='lnet';
 {$else}
-  FDownloader:='base';
+  Downloader:='base';
 {$endif}
-  // Parameter defaults
-  FCompilerConfig:=FDefaultCompilerConfig;
-  FInstallGlobal:=False;
-  FRecoveryMode:=False;
-  FAllowBroken:=False;
+end;
 
-  SetLength(FPMKUnitDeps,FPMKUnitDepDefaultCount);
-  for i := 0 to FPMKUnitDepDefaultCount-1 do
-    FPMKUnitDeps[i]:=FPMKUnitDepsDefaults[i];
+destructor TFppkgGlobalOptionSection.Destroy;
+begin
+  FOptionParser.Free;
+  inherited Destroy;
 end;
 
+procedure TFppkgGlobalOptionSection.AddKeyValue(const AKey, AValue: string);
+begin
+  if SameText(AKey,KeyBuildDir) then
+    BuildDir := AValue
+  else if SameText(AKey,KeyDownloader) then
+    Downloader := AValue
+  else if SameText(AKey,KeyConfigVersion) then
+    begin
+      ConfigVersion := StrToIntDef(AValue,-1);
+      if (FConfigVersion<>CurrentConfigVersion) then
+        begin
+          if (FConfigVersion<MinSupportedConfigVersion) or (FConfigVersion>CurrentConfigVersion) then
+            Error(SErrUnsupportedConfigVersion);
+          log(llWarning,SLogOldConfigFileFormat);
+        end;
+    end
+  else if SameText(AKey,KeyCompilerConfig) then
+    CompilerConfig := AValue
+  else if SameText(AKey,KeyFPMakeCompilerConfig) then
+    FPMakeCompilerConfig := AValue
+  else if SameText(AKey,KeyCompilerConfigDir) then
+    CompilerConfigDir := AValue
+  else if SameText(AKey,KeyRemoteMirrorsURL) then
+    RemoteMirrorsURL := AValue
+  else if SameText(AKey,KeyRemoteRepository) then
+    RemoteRepository := AValue
+  else if SameText(AKey,KeyLocalRepository) then
+    LocalRepository := AValue
+  else if SameText(AKey,KeyArchivesDir) then
+    ArchivesDir := AValue
+  else if SameText(AKey,KeyCustomFPMakeOptions) then
+    CustomFPMakeOptions := AValue
+end;
 
-procedure TGlobalOptions.LoadGlobalFromFile(const AFileName: String);
-Var
-  Ini : TMemIniFile;
+procedure TFppkgGlobalOptionSection.SaveToStrings(AStrings: TStrings);
 begin
-  Ini:=TMemIniFile.Create(AFileName);
+  AStrings.Add('['+KeyGlobalSection+']');
+  AStrings.Add(KeyConfigVersion+'='+IntToStr(CurrentConfigVersion));
+  AStrings.Add(KeyBuildDir+'='+BuildDir);
+  AStrings.Add(KeyDownloader+'='+Downloader);
+  AStrings.Add(KeyCompilerConfig+'='+CompilerConfig);
+  AStrings.Add(KeyFPMakeCompilerConfig+'='+FPMakeCompilerConfig);
+  AStrings.Add(KeyCompilerConfigDir+'='+CompilerConfigDir);
+  AStrings.Add(KeyRemoteMirrorsURL+'='+RemoteMirrorsURL);
+  AStrings.Add(KeyRemoteRepository+'='+RemoteRepository);
+  AStrings.Add(KeyLocalRepository+'='+LocalRepository);
+  AStrings.Add(KeyArchivesDir+'='+ArchivesDir);
+end;
+
+procedure TFppkgGlobalOptionSection.LogValues(ALogLevel: TLogLevel);
+begin
+  inherited LogValues(ALogLevel);
+  log(ALogLevel,SLogGlobalCfgRemoteMirrorsURL,[FRemoteMirrorsURL]);
+  log(ALogLevel,SLogGlobalCfgRemoteRepository,[FRemoteRepository]);
+  log(ALogLevel,SLogGlobalCfgLocalRepository,[FLocalRepository,LocalRepository]);
+  log(ALogLevel,SLogGlobalCfgBuildDir,[FBuildDir,BuildDir]);
+  log(ALogLevel,SLogGlobalCfgArchivesDir,[FArchivesDir,ArchivesDir]);
+  log(ALogLevel,SLogGlobalCfgCompilerConfigDir,[FCompilerConfigDir,CompilerConfigDir]);
+  log(ALogLevel,SLogGlobalCfgDefaultCompilerConfig,[FCompilerConfig]);
+  log(ALogLevel,SLogGlobalCfgFPMakeCompilerConfig,[FPMakeCompilerConfig]);
+  log(ALogLevel,SLogGlobalCfgDownloader,[FDownloader]);
+end;
+
+function TFppkgGlobalOptionSection.LocalMirrorsFile: string;
+begin
+  Result:=LocalRepository+MirrorsFileName;
+end;
+
+function TFppkgGlobalOptionSection.LocalPackagesFile: string;
+begin
+  Result:=LocalRepository+PackagesFileName;
+end;
+
+{*****************************************************************************
+                            TFppkgOptions
+*****************************************************************************}
+
+function TFppkgOptions.GetSectionList: TFppkgOptionSectionList;
+begin
+  Result := FSectionList;
+end;
+
+function TFppkgOptions.GetGlobalSection: TFppkgGLobalOptionSection;
+begin
+  Result := GetSectionByName(KeyGlobalSection) as TFppkgGlobalOptionSection;
+  // Below version 5 the glolbal-section was called 'Defaults'
+  if not Assigned(Result) then
+    Result := GetSectionByName(KeyDeprGlobalSection) as TFppkgGlobalOptionSection;
+
+  if not Assigned(Result) then
+    begin
+      Result := TFppkgGlobalOptionSection.Create;
+      Result.Name := KeyGlobalSection;
+      FSectionList.Add(Result);
+    end;
+end;
+
+function TFppkgOptions.GetCommandLineSection: TFppkgCommandLineOptionSection;
+begin
+  Result := GetSectionByName(' Commandline ') as TFppkgCommandLineOptionSection;
+  if not Assigned(Result) then
+    begin
+      Result := TFppkgCommandLineOptionSection.Create;
+      Result.Name := ' Commandline ';
+      FSectionList.Add(Result);
+    end;
+end;
+
+constructor TFppkgOptions.Create;
+begin
+  FSectionList := TFppkgOptionSectionList.Create;
+end;
+
+destructor TFppkgOptions.Destroy;
+begin
+  FSectionList.Free;
+  inherited Destroy;
+end;
+
+procedure TFppkgOptions.LoadFromFile(const AFileName: string);
+var
+  IniFile: TStringList;
+  CurrentSection: TFppkgOptionSection;
+  s: String;
+  i: Integer;
+  j: SizeInt;
+begin
+  log(llInfo, SLogStartLoadingConfFile, [AFileName]);
+  IniFile:=TStringList.Create;
   try
-    FConfigFileName:=AFileName;
-    With Ini do
+    Inifile.LoadFromFile(AFileName);
+    for i := 0 to Inifile.Count-1 do
       begin
-        FConfigVersion:=ReadInteger(SDefaults,KeyConfigVersion,0);
-        if (FConfigVersion<>CurrentConfigVersion) then
+        s := Trim(IniFile[i]);
+        if s = '' then
+          Continue;
+        if (Copy(s, 1, 1) = '[') and (Copy(s, length(s), 1) = ']') then
           begin
-            log(llDebug,SLogUpgradingConfig,[AFileName]);
-            FSaveInifileChanges:=true;
-            if FConfigVersion<1 then
-              begin
-                FRemoteRepository:='auto';
-              end;
-            if FConfigVersion<3 then
+            s := Trim(Copy(s, 2, Length(s) - 2));
+            CurrentSection := GetSectionByName(s);
+            if not Assigned(CurrentSection) or CurrentSection.AllowDuplicate then
               begin
-                // Directories
-                FBuildDir:=FLocalRepository+'build'+PathDelim;
-                FArchivesDir:=FLocalRepository+'archives'+PathDelim;
-                FCompilerConfigDir:=FLocalRepository+'config'+PathDelim;
-              end;
-            if (FConfigVersion>CurrentConfigVersion) then
-              Error(SErrUnsupportedConfigVersion,[AFileName]);
+                if SameText(s, KeyGlobalSection) or SameText(s, KeyDeprGlobalSection) then
+                  CurrentSection := TFppkgGlobalOptionSection.Create
+                else
+                  CurrentSection := TFppkgCustomOptionSection.Create;
+                FSectionList.Add(CurrentSection);
+                CurrentSection.Name := s;
+              end
+          end
+        else if copy(s,1,1)<>';' then // comment
+          begin
+            // regular key
+            j:=Pos('=', s);
+            if j>0 then
+              CurrentSection.AddKeyValue(Trim(Copy(s, 1,  j - 1)), Trim(Copy(s, j + 1, Length(s) - j)));
           end;
-        FRemoteMirrorsURL:=ReadString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
-        FRemoteRepository:=ReadString(SDefaults,KeyRemoteRepository,FRemoteRepository);
-        FLocalRepository:=ReadString(SDefaults,KeyLocalRepository,FLocalRepository);
-        UpdateLocalRepositoryOption;
-        FBuildDir:=fpmkunit.FixPath(ReadString(SDefaults,KeyBuildDir,FBuildDir), True);
-        FArchivesDir:=fpmkunit.FixPath(ReadString(SDefaults,KeyArchivesDir,FArchivesDir), True);
-        FCompilerConfigDir:=fpmkunit.FixPath(ReadString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir), True);
-        FDefaultCompilerConfig:=ReadString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
-        FFPMakeCompilerConfig:=ReadString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
-        FDownloader:=ReadString(SDefaults,KeyDownloader,FDownloader);
-        FCustomFPMakeOptions:=ReadString(SDefaults,KeyCustomFPMakeOptions,FCustomFPMakeOptions);
       end;
   finally
-    Ini.Free;
+    Inifile.Free;
   end;
 end;
 
-
-procedure TGlobalOptions.SaveGlobalToFile(const AFileName: String);
-Var
-  Ini : TIniFile;
+procedure TFppkgOptions.SaveToFile(const AFileName: string);
+var
+  IniFile: TStringList;
+  CurrentSection: TFppkgOptionSection;
+  s: String;
+  i: Integer;
+  j: SizeInt;
 begin
-  if FileExists(AFileName) then
-    BackupFile(AFileName);
-  Ini:=TIniFile.Create(AFileName);
+  IniFile:=TStringList.Create;
   try
-    With Ini do
-      begin
-        WriteInteger(SDefaults,KeyConfigVersion,CurrentConfigVersion);
-        WriteString(SDefaults,KeyLocalRepository,FLocalRepository);
-        WriteString(SDefaults,KeyBuildDir,FBuildDir);
-        WriteString(SDefaults,KeyArchivesDir,FArchivesDir);
-        WriteString(SDefaults,KeyCompilerConfigDir,FCompilerConfigDir);
-        WriteString(SDefaults,KeyRemoteMirrorsURL,FRemoteMirrorsURL);
-        WriteString(SDefaults,KeyRemoteRepository,FRemoteRepository);
-        WriteString(SDefaults,KeyCompilerConfig,FDefaultCompilerConfig);
-        WriteString(SDefaults,KeyFPMakeCompilerConfig,FFPMakeCompilerConfig);
-        WriteString(SDefaults,KeyDownloader,FDownloader);
-        FSaveInifileChanges:=False;
-      end;
-    Ini.UpdateFile;
+    // Only the Global-section is being written, with some default values
+    CurrentSection := GlobalSection;
+    CurrentSection.SaveToStrings(IniFile);
+    Inifile.SaveToFile(AFileName);
   finally
-    Ini.Free;
+    Inifile.Free;
   end;
 end;
 
-
-procedure TGlobalOptions.LogValues(ALogLevel: TLogLevel);
+function TFppkgOptions.GetSectionByName(const SectionName: string): TFppkgOptionSection;
+var
+  i: Integer;
 begin
-  log(ALogLevel,SLogGlobalCfgHeader,[FConfigFilename]);
-  log(ALogLevel,SLogGlobalCfgRemoteMirrorsURL,[FRemoteMirrorsURL]);
-  log(ALogLevel,SLogGlobalCfgRemoteRepository,[FRemoteRepository]);
-  log(ALogLevel,SLogGlobalCfgLocalRepository,[FLocalRepository,LocalRepository]);
-  log(ALogLevel,SLogGlobalCfgBuildDir,[FBuildDir,BuildDir]);
-  log(ALogLevel,SLogGlobalCfgArchivesDir,[FArchivesDir,ArchivesDir]);
-  log(ALogLevel,SLogGlobalCfgCompilerConfigDir,[FCompilerConfigDir,CompilerConfigDir]);
-  log(ALogLevel,SLogGlobalCfgDefaultCompilerConfig,[FDefaultCompilerConfig]);
-  log(ALogLevel,SLogGlobalCfgFPMakeCompilerConfig,[FPMakeCompilerConfig]);
-  log(ALogLevel,SLogGlobalCfgDownloader,[FDownloader]);
+  Result := nil;
+  for i := 0 to SectionList.Count-1 do
+    begin
+      if SectionList[i].Name=SectionName then
+        begin
+          Result:=SectionList[i];
+          Break;
+        end;
+    end;
 end;
 
+procedure TFppkgOptions.LogValues(ALogLevel: TLogLevel);
+var
+  i: Integer;
+begin
+  log(ALogLevel,SLogCfgHeader);
+  for i := 0 to SectionList.Count-1 do
+    begin
+      SectionList[i].LogValues(ALogLevel);
+    end;
+end;
 
 {*****************************************************************************
                            TCompilerOptions
@@ -616,7 +822,7 @@ end;
 
 procedure TCompilerOptions.UpdateLocalRepositoryOption;
 begin
-  FOptionParser.Values['LocalRepository'] := GlobalOptions.LocalRepository;
+  FOptionParser.Values['LocalRepository'] := GlobalOptions.GlobalSection.LocalRepository;
 end;
 
 procedure TCompilerOptions.CheckCompilerValues;
@@ -810,7 +1016,7 @@ end;
 
 
 initialization
-  GlobalOptions:=TGlobalOptions.Create;
+  GlobalOptions:=TFppkgOptions.Create;
   CompilerOptions:=TCompilerOptions.Create;
   FPMakeCompilerOptions:=TCompilerOptions.Create;
 finalization

+ 5 - 5
packages/fppkg/src/pkgrepos.pp

@@ -81,7 +81,7 @@ begin
   AvailableMirrors:=TFPMirrors.Create(TFPMirror);
 
   // Repository
-  S:=GlobalOptions.LocalMirrorsFile;
+  S:=GlobalOptions.GlobalSection.LocalMirrorsFile;
   log(llDebug,SLogLoadingMirrorsFile,[S]);
   if not FileExists(S) then
     exit;
@@ -150,10 +150,10 @@ function GetRemoteRepositoryURL(const AFileName:string):string;
 begin
   if CurrentRemoteRepositoryURL='' then
     begin
-      if GlobalOptions.RemoteRepository='auto' then
+      if GlobalOptions.GlobalSection.RemoteRepository='auto' then
         CurrentRemoteRepositoryURL:=SelectRemoteMirror
       else
-        CurrentRemoteRepositoryURL:=GlobalOptions.RemoteRepository;
+        CurrentRemoteRepositoryURL:=GlobalOptions.GlobalSection.RemoteRepository;
     end;
   result := CurrentRemoteRepositoryURL;
   if result[length(result)]<>'/' then
@@ -410,7 +410,7 @@ begin
     FPMKUnitDeps[i].available:=false;
   // Not version check needed in Recovery mode, we always need to use
   // the internal bootstrap procedure
-  if GlobalOptions.RecoveryMode then
+  if GlobalOptions.CommandLineSection.RecoveryMode then
     exit;
   // Check for fpmkunit dependencies
   for i:=0 to high(FPMKUnitDeps) do
@@ -454,7 +454,7 @@ begin
     AvailableRepository.Free;
   AvailableRepository:=GetDefaultRepositoryClass.Create(Nil);
   // Repository
-  S:=GlobalOptions.LocalPackagesFile;
+  S:=GlobalOptions.GlobalSection.LocalPackagesFile;
   log(llDebug,SLogLoadingPackagesFile,[S]);
   if not FileExists(S) then
     exit;

+ 31 - 20
utils/fppkg/fppkg.pp

@@ -56,11 +56,18 @@ begin
   // Default verbosity
   LogLevels:=DefaultLogLevels;
   for i:=1 to ParamCount do
-    if (ParamStr(i)='-d') or (ParamStr(i)='--debug') then
-      begin
-        LogLevels:=AllLogLevels+[llDebug];
-        break;
-      end;
+    begin
+      if (ParamStr(i)='-d') or (ParamStr(i)='--debug') then
+        begin
+          LogLevels:=AllLogLevels+[llDebug];
+          break;
+        end;
+      if (ParamStr(i)='-v') or (ParamStr(i)='--verbose') then
+        begin
+          LogLevels:=AllLogLevels+[llDebug];
+          break;
+        end;
+    end;
   // First try config file from command line
   if HasOption('C','config-file') then
     cfgfile:=GetOptionValue('C','config-file')
@@ -72,9 +79,9 @@ end;
 
 procedure TMakeTool.MaybeCreateLocalDirs;
 begin
-  ForceDirectories(GlobalOptions.BuildDir);
-  ForceDirectories(GlobalOptions.ArchivesDir);
-  ForceDirectories(GlobalOptions.CompilerConfigDir);
+  ForceDirectories(GlobalOptions.GlobalSection.BuildDir);
+  ForceDirectories(GlobalOptions.GlobalSection.ArchivesDir);
+  ForceDirectories(GlobalOptions.GlobalSection.CompilerConfigDir);
 end;
 
 
@@ -203,23 +210,23 @@ begin
           OptionArg(I);
         end
       else if CheckOption(I,'c','config') then
-        GlobalOptions.CompilerConfig:=OptionArg(I)
+        GlobalOptions.CommandLineSection.CompilerConfig:=OptionArg(I)
       else if CheckOption(I,'v','verbose') then
         LogLevels:=AllLogLevels
       else if CheckOption(I,'d','debug') then
         LogLevels:=AllLogLevels+[llDebug]
       else if CheckOption(I,'g','global') then
-        GlobalOptions.InstallGlobal:=true
+        GlobalOptions.CommandLineSection.InstallGlobal:=true
       else if CheckOption(I,'r','recovery') then
-        GlobalOptions.RecoveryMode:=true
+        GlobalOptions.CommandLineSection.RecoveryMode:=true
       else if CheckOption(I,'n','') then
-        GlobalOptions.SkipConfigurationFiles:=true
+        GlobalOptions.CommandLineSection.SkipConfigurationFiles:=true
       else if CheckOption(I,'b','broken') then
-        GlobalOptions.AllowBroken:=true
+        GlobalOptions.CommandLineSection.AllowBroken:=true
       else if CheckOption(I,'l','showlocation') then
-        GlobalOptions.ShowLocation:=true
+        GlobalOptions.CommandLineSection.ShowLocation:=true
       else if CheckOption(I,'s','skipbroken') then
-        GlobalOptions.SkipFixBrokenAfterInstall:=true
+        GlobalOptions.CommandLineSection.SkipFixBrokenAfterInstall:=true
       else if CheckOption(I,'o','options') and FirstPass then
         begin
           OptString := OptionArg(I);
@@ -284,6 +291,10 @@ begin
     LoadGlobalDefaults;
     ProcessCommandLine(true);
 
+    SetLength(FPMKUnitDeps,FPMKUnitDepDefaultCount);
+    for i := 0 to FPMKUnitDepDefaultCount-1 do
+      FPMKUnitDeps[i]:=FPMKUnitDepsDefaults[i];
+
     // Scan is special, it doesn't need a valid local setup
     if (ParaAction='scan') then
       begin
@@ -294,7 +305,7 @@ begin
       end;
 
     MaybeCreateLocalDirs;
-    if not GlobalOptions.SkipConfigurationFiles then
+    if not GlobalOptions.CommandLineSection.SkipConfigurationFiles then
       LoadCompilerDefaults
     else
       begin
@@ -316,7 +327,7 @@ begin
     // Load local repository, update first if this is a new installation
     // errors will only be reported as warning. The user can be bootstrapping
     // and do an update later
-    if not FileExists(GlobalOptions.LocalPackagesFile) then
+    if not FileExists(GlobalOptions.GlobalSection.LocalPackagesFile) then
       begin
         try
           pkghandler.ExecuteAction('','update');
@@ -331,14 +342,14 @@ begin
     // We only need to reload the status when we use a different
     // configuration for compiling fpmake or when the CPU, OS or compiler
     // are set in the command-line
-    if (GlobalOptions.CompilerConfig<>GlobalOptions.FPMakeCompilerConfig) or
+    if (GlobalOptions.GlobalSection.CompilerConfig<>GlobalOptions.GlobalSection.FPMakeCompilerConfig) or
        (CompilerOptions.CompilerCPU<>FPMakeCompilerOptions.CompilerCPU) or
        (CompilerOptions.CompilerOS<>FPMakeCompilerOptions.CompilerOS) or
        (CompilerOptions.Compiler<>FPMakeCompilerOptions.Compiler) then
       FindInstalledPackages(CompilerOptions,true);
 
     // Check for broken dependencies
-    if not GlobalOptions.AllowBroken and
+    if not GlobalOptions.CommandLineSection.AllowBroken and
        (((ParaAction='fixbroken') and (ParaPackages.Count>0)) or
         (ParaAction='compile') or
         (ParaAction='build') or
@@ -377,7 +388,7 @@ begin
       end;
 
     // Recompile all packages dependent on this package
-    if (ParaAction='install') and not GlobalOptions.SkipFixBrokenAfterInstall then
+    if (ParaAction='install') and not GlobalOptions.CommandLineSection.SkipFixBrokenAfterInstall then
       pkghandler.ExecuteAction('','fixbroken');
 
     Terminate;