소스 검색

* Added ability to add the location of directories containing packages, to
make all packages in those directories available to fppkg.

git-svn-id: trunk@34625 -

joost 8 년 전
부모
커밋
174163ad81

+ 1 - 0
.gitattributes

@@ -3397,6 +3397,7 @@ packages/fppkg/src/pkgmkconv.pp svneol=native#text/plain
 packages/fppkg/src/pkgoptions.pp svneol=native#text/plain
 packages/fppkg/src/pkgpackagesstructure.pp svneol=native#text/plain
 packages/fppkg/src/pkgrepos.pp svneol=native#text/plain
+packages/fppkg/src/pkguninstalledsourcesrepository.pp svneol=native#text/plain
 packages/fppkg/src/pkgwget.pp svneol=native#text/plain
 packages/fuse/Makefile svneol=native#text/plain
 packages/fuse/Makefile.fpc svneol=native#text/plain

+ 1 - 0
packages/fppkg/fpmake.pp

@@ -71,6 +71,7 @@ begin
     T.Dependencies.AddInclude('fpmkunitsrc.inc');
     T:=P.Targets.AddUnit('pkgcommands.pp');
     T:=P.Targets.AddUnit('pkgpackagesstructure.pp');
+    T:=P.Targets.AddUnit('pkguninstalledsourcesrepository.pp');
 
     T:=P.Targets.AddUnit('pkgwget.pp', TargetsWithWGet);
     T:=P.Targets.AddUnit('pkgfphttp.pp', TargetsWithfpWeb);

+ 28 - 0
packages/fppkg/src/fprepos.pp

@@ -194,6 +194,9 @@ type
     Procedure LoadFromFile(const AFileName : String);
     Procedure SaveToFile(const AFileName : String);
     Procedure Save;
+    // Load packages from Manifest-format
+    Procedure AddPackagesFromManifestFile(const AFileName: String);
+    Procedure AddPackagesFromManifestStream(Stream: TStream);
     // Package management
     Function IndexOfPackage(const APackageName : String) : Integer;
     Function FindPackage(const APackageName : String) : TFPPackage;
@@ -274,6 +277,7 @@ Implementation
 uses
   typinfo,
   pkgglobals,
+  fpxmlrep,
   uriparser;
 
 const
@@ -765,6 +769,30 @@ begin
   SaveToFile(FFileName);
 end;
 
+procedure TFPRepository.AddPackagesFromManifestFile(const AFileName: String);
+var
+  X: TFPXMLRepositoryHandler;
+begin
+  X:=TFPXMLRepositoryHandler.Create;
+  try
+    X.LoadFromXml(FPackages, AFileName);
+  finally
+    X.Free;
+  end;
+end;
+
+procedure TFPRepository.AddPackagesFromManifestStream(Stream: TStream);
+var
+  X: TFPXMLRepositoryHandler;
+begin
+  X:=TFPXMLRepositoryHandler.Create;
+  try
+    X.LoadFromXml(FPackages, Stream);
+  finally
+    X.Free;
+  end;
+end;
+
 
 function TFPRepository.IndexOfPackage(const APackageName: String): Integer;
 begin

+ 13 - 7
packages/fppkg/src/pkgfpmake.pp

@@ -342,15 +342,21 @@ begin
   AddOption('--cpu='+CPUToString(GFPpkg.CompilerOptions.CompilerCPU));
   AddOption('--os='+OSToString(GFPpkg.CompilerOptions.CompilerOS));
 
-  InstallRepo := GFPpkg.RepositoryByName(GFPpkg.Options.CommandLineSection.InstallRepository);
-
-  if not Assigned(InstallRepo.DefaultPackagesStructure) then
+  // While scanning a source-repository it could be necessary to create manifest
+  // files. At this moment the InstallRepo could not be initialized yet. And the
+  // manifest command does not use the --prefix and --baseinstalldir parameters.
+  if (command<>'manifest') then
     begin
-      Error(SErrIllConfRepository,[InstallRepo.RepositoryName]);
-      Exit;
+      InstallRepo := GFPpkg.RepositoryByName(GFPpkg.Options.CommandLineSection.InstallRepository);
+
+      if not Assigned(InstallRepo.DefaultPackagesStructure) then
+        begin
+          Error(SErrIllConfRepository,[InstallRepo.RepositoryName]);
+          Exit;
+        end;
+      CondAddOption('--prefix',InstallRepo.DefaultPackagesStructure.GetPrefix);
+      CondAddOption('--baseinstalldir',InstallRepo.DefaultPackagesStructure.GetBaseInstallDir);
     end;
-  CondAddOption('--prefix',InstallRepo.DefaultPackagesStructure.GetPrefix);
-  CondAddOption('--baseinstalldir',InstallRepo.DefaultPackagesStructure.GetBaseInstallDir);
 
   for i := GFPpkg.Options.SectionList.Count -1 downto 0 do
     begin

+ 3 - 12
packages/fppkg/src/pkgfppkg.pp

@@ -83,8 +83,6 @@ procedure TpkgFPpkg.ScanPackagesOnDisk(ACompilerOptions: TCompilerOptions;
   ARepositoryList: TComponentList);
 var
   i: Integer;
-  InstPackages: TFPInstalledPackagesStructure;
-  Path: string;
   RepoOption: TFppkgRepositoryOptionSection;
   Repo: TFPRepository;
 begin
@@ -94,18 +92,11 @@ begin
       if FOptions.SectionList[i] is TFppkgRepositoryOptionSection then
         begin
           RepoOption := TFppkgRepositoryOptionSection(FOptions.SectionList[i]);
-          Path := RepoOption.Path;
-          if Path <> '' then
+          Repo := RepoOption.InitRepository(Self, ACompilerOptions);
+          if Assigned(Repo) then
             begin
-              Repo := TFPRepository.Create(Self);
               ARepositoryList.Add(Repo);
-              Repo.RepositoryType := fprtInstalled;
-              Repo.RepositoryName := RepoOption.RepositoryName;
-              Repo.Description := RepoOption.Description;
-              InstPackages := TFPInstalledPackagesStructure.Create(Self, Path, ACompilerOptions);
-              InstPackages.AddPackagesToRepository(Repo);
-              InstPackages.Prefix:=RepoOption.Prefix;
-              Repo.DefaultPackagesStructure := InstPackages;
+              Repo.DefaultPackagesStructure.AddPackagesToRepository(Repo);
             end;
         end;
     end;

+ 1 - 0
packages/fppkg/src/pkgmessages.pp

@@ -86,6 +86,7 @@ Resourcestring
   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';
+  SLogFailedToCreateManifest = 'Failed to create manifest from fpmake.pp-file (%s) while scanning for available packages: %s';
 
   SLogCfgHeader                      = 'Settings from configuration-files:';
   SLogCfgSectionHeader               = ' %s-section:';

+ 26 - 2
packages/fppkg/src/pkgoptions.pp

@@ -31,6 +31,7 @@ Type
 
   { TFppkgOptionSection }
 
+  TCompilerOptions = class;
   TFppkgOptionSection = class(TPersistent)
   private
     FOptionParser: TTemplateParser;
@@ -127,6 +128,8 @@ Type
     procedure LogValues(ALogLevel: TLogLevel); override;
     function AllowDuplicate: Boolean; override;
 
+    function InitRepository(AParent: TComponent; ACompilerOptions: TCompilerOptions): TFPRepository; virtual;
+
     property RepositoryName: string read FRepositoryName write SetRepositoryName;
     property Description: string read FDescription write SetDescription;
     property Path: string read GetPath write SetPath;
@@ -158,7 +161,6 @@ Type
 
   { TFppkgOptions }
 
-  TCompilerOptions = class;
   TFppkgOptions = class(TPersistent)
   private
     FOptionParser: TTemplateParser;
@@ -234,6 +236,8 @@ Type
 Implementation
 
 uses
+  pkgUninstalledSourcesRepository,
+  pkgPackagesStructure,
   pkgmessages;
 
 Const
@@ -254,6 +258,7 @@ Const
   KeyDeprGlobalSection     = 'Defaults';
   KeyGlobalSection         = 'Global';
   KeyRepositorySection     = 'Repository';
+  KeySrcRepositorySection  = 'UninstalledSourceRepository';
   KeyRemoteMirrorsURL      = 'RemoteMirrors';
   KeyRemoteRepository      = 'RemoteRepository';
   KeyLocalRepository       = 'LocalRepository';
@@ -314,7 +319,7 @@ end;
 procedure TFppkgRepositoryOptionSection.SetPath(AValue: string);
 begin
   if FPath = AValue then Exit;
-  FPath := AValue;
+  FPath := fpmkunit.FixPath(AValue, True);
 end;
 
 procedure TFppkgRepositoryOptionSection.AddKeyValue(const AKey, AValue: string);
@@ -343,6 +348,23 @@ begin
   Result := True;
 end;
 
+function TFppkgRepositoryOptionSection.InitRepository(AParent: TComponent;
+  ACompilerOptions: TCompilerOptions): TFPRepository;
+var
+  InstPackages: TFPInstalledPackagesStructure;
+begin
+  if Path <> '' then
+    begin
+      Result := TFPRepository.Create(AParent);
+      Result.RepositoryType := fprtInstalled;
+      Result.RepositoryName := RepositoryName;
+      Result.Description := Description;
+      InstPackages := TFPInstalledPackagesStructure.Create(AParent, Path, ACompilerOptions);
+      Result.DefaultPackagesStructure := InstPackages;
+      InstPackages.Prefix:=Prefix;
+    end;
+end;
+
 { TFppkgCommandLineOptionSection }
 
 constructor TFppkgCommandLineOptionSection.Create(AnOptionParser: TTemplateParser);
@@ -667,6 +689,8 @@ begin
                   CurrentSection := TFppkgGlobalOptionSection.Create(FOptionParser)
                 else if SameText(s, KeyRepositorySection) then
                   CurrentSection := TFppkgRepositoryOptionSection.Create(FOptionParser)
+                else if SameText(s, KeySrcRepositorySection) then
+                  CurrentSection := TFppkgUninstalledSourceRepositoryOptionSection.Create(FOptionParser)
                 else
                   CurrentSection := TFppkgCustomOptionSection.Create(FOptionParser);
                 FSectionList.Add(CurrentSection);

+ 44 - 1
packages/fppkg/src/pkgpackagesstructure.pp

@@ -67,6 +67,20 @@ type
     function GetBuildPathDirectory(APackage: TFPPackage): string; override;
   end;
 
+  { TFPTemporaryDirectoryPackagesStructure }
+
+  TFPTemporaryDirectoryPackagesStructure = class(TFPCustomFileSystemPackagesStructure)
+  private
+    FPackage: TFPPackage;
+    function GetTempPackageName: string;
+    procedure SetTempPackageName(AValue: string);
+  public
+    function AddPackagesToRepository(ARepository: TFPRepository): Boolean; override;
+    function GetBuildPathDirectory(APackage: TFPPackage): string; override;
+    procedure SetTempPath(APath: string);
+    property TempPackageName: string read GetTempPackageName write SetTempPackageName;
+  end;
+
 implementation
 
 uses
@@ -75,6 +89,35 @@ uses
   pkgrepos,
   pkgglobals;
 
+{ TFPTemporaryDirectoryPackagesStructure }
+
+function TFPTemporaryDirectoryPackagesStructure.GetTempPackageName: string;
+begin
+  Result := FPackage.Name;
+end;
+
+procedure TFPTemporaryDirectoryPackagesStructure.SetTempPackageName(AValue: string);
+begin
+  FPackage.Name := AValue;
+end;
+
+function TFPTemporaryDirectoryPackagesStructure.AddPackagesToRepository(ARepository: TFPRepository): Boolean;
+begin
+  Result := True;
+  FPackage := ARepository.AddPackage('');
+  FPackage.PackagesStructure := Self;
+end;
+
+function TFPTemporaryDirectoryPackagesStructure.GetBuildPathDirectory(APackage: TFPPackage): string;
+begin
+  Result := FPath;
+end;
+
+procedure TFPTemporaryDirectoryPackagesStructure.SetTempPath(APath: string);
+begin
+  FPath := APath;
+end;
+
 { TFPOriginalSourcePackagesStructure }
 
 constructor TFPOriginalSourcePackagesStructure.Create(AOwner: TComponent;
@@ -274,7 +317,7 @@ constructor TFPCustomFileSystemPackagesStructure.Create(AOwner: TComponent; APat
   ACompilerOptions: TCompilerOptions);
 begin
   Inherited Create(AOwner);
-  FPath := APath;
+  FPath := IncludeTrailingPathDelimiter(APath);
   FCompilerOptions := ACompilerOptions;
 end;
 

+ 148 - 0
packages/fppkg/src/pkguninstalledsourcesrepository.pp

@@ -0,0 +1,148 @@
+unit pkgUninstalledSourcesRepository;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  fpmkunit,
+  fpTemplate,
+  pkgoptions,
+  pkgglobals,
+  pkgmessages,
+  fprepos,
+  pkgrepos,
+  pkghandler,
+  pkgPackagesStructure;
+
+type
+
+  { TFppkgUninstalledSourceRepositoryOptionSection }
+
+  TFppkgUninstalledSourceRepositoryOptionSection = class(TFppkgRepositoryOptionSection)
+  private
+  public
+    constructor Create(AnOptionParser: TTemplateParser); override;
+    procedure AddKeyValue(const AKey, AValue: string); override;
+    function InitRepository(AParent: TComponent; ACompilerOptions: TCompilerOptions): TFPRepository; override;
+  end;
+
+  { TFPUninstalledSourcesAvailablePackagesStructure }
+
+  TFPUninstalledSourcesAvailablePackagesStructure = class(TFPCustomFileSystemPackagesStructure)
+  public
+    function AddPackagesToRepository(ARepository: TFPRepository): Boolean; override;
+    function GetBuildPathDirectory(APackage: TFPPackage): string; override;
+  end;
+
+implementation
+
+const
+  KeyScanForUnits = 'ScanForUnits';
+  KeyUnitPath     = 'UnitPath';
+
+{ TFppkgUninstalledSourceRepositoryOptionSection }
+
+constructor TFppkgUninstalledSourceRepositoryOptionSection.Create(AnOptionParser: TTemplateParser);
+begin
+  inherited Create(AnOptionParser);
+end;
+
+procedure TFppkgUninstalledSourceRepositoryOptionSection.AddKeyValue(const AKey, AValue: string);
+begin
+  inherited AddKeyValue(AKey, AValue);
+end;
+
+function TFppkgUninstalledSourceRepositoryOptionSection.InitRepository(AParent: TComponent;
+  ACompilerOptions: TCompilerOptions): TFPRepository;
+var
+  InstPackages: TFPUninstalledSourcesAvailablePackagesStructure;
+begin
+  if Path <> '' then
+    begin
+      Result := TFPRepository.Create(AParent);
+      Result.RepositoryType := fprtAvailable;
+      Result.RepositoryName := RepositoryName;
+      Result.Description := Description;
+      InstPackages := TFPUninstalledSourcesAvailablePackagesStructure.Create(AParent, Path, ACompilerOptions);
+      Result.DefaultPackagesStructure := InstPackages;
+    end;
+end;
+
+{ TFPUninstalledSourcesPackagesStructure }
+
+function TFPUninstalledSourcesAvailablePackagesStructure.AddPackagesToRepository(ARepository: TFPRepository): Boolean;
+
+var
+  SR : TSearchRec;
+  AManifestFile, AFPMakeFile: String;
+  i: Integer;
+  TempPackagesStructure: TFPTemporaryDirectoryPackagesStructure;
+  TempRepo: TFPRepository;
+  PackageName: string;
+begin
+  Result:=false;
+
+  TempPackagesStructure := TFPTemporaryDirectoryPackagesStructure.Create(Owner, '', FCompilerOptions);
+  TempRepo := TFPRepository.Create(Owner);
+  TempRepo.RepositoryName := 'TempScanUninstPackages';
+  TempRepo.Description := 'Temp list of packages during scanning of source-packages';
+  TempRepo.RepositoryType := fprtAvailable;
+  TempRepo.DefaultPackagesStructure := TempPackagesStructure;
+  TempPackagesStructure.AddPackagesToRepository(TempRepo);
+  GFPpkg.RepositoryList.Add(TempRepo);
+
+  try
+    log(llDebug,SLogFindInstalledPackages,[FPath]);
+    if FindFirst(FPath+AllFiles,faDirectory,SR)=0 then
+      begin
+        repeat
+          if ((SR.Attr and faDirectory)=faDirectory) and (SR.Name<>'.') and (SR.Name<>'..') then
+            begin
+              AFPMakeFile := FPath+SR.Name+PathDelim+FPMakePPFile;
+              if FileExistsLog(AFPMakeFile) then
+                begin
+                  AManifestFile := FPath+SR.Name+PathDelim+ManifestFile;
+                  if not FileExists(AManifestFile) or (FileAge(AManifestFile) < FileAge(AFPMakeFile)) then
+                    begin
+                      // (Re-)create manifest
+                      try
+                        TempPackagesStructure.SetTempPath(FPath+SR.Name);
+                        PackageName :=  SR.Name + '_create_manifest';
+                        TempPackagesStructure.TempPackageName := PackageName;
+                        pkghandler.ExecuteAction(PackageName,'fpmakemanifest');
+                      except
+                        on E: Exception do
+                          begin
+                            log(llWarning, SLogFailedToCreateManifest ,[AFPMakeFile, E.Message]);
+                            Continue;
+                          end;
+                      end;
+                    end;
+                  ARepository.AddPackagesFromManifestFile(AManifestFile);
+                end
+            end;
+        until FindNext(SR)<>0;
+      end;
+    FindClose(SR);
+  finally
+    GFPpkg.RepositoryList.Remove(TempRepo);
+    TempRepo.Free;
+    TempPackagesStructure.Free;
+  end;
+  for i := 0 to ARepository.PackageCount -1 do
+    ARepository.Packages[i].PackagesStructure := Self;
+
+  Result:=true;
+end;
+
+function TFPUninstalledSourcesAvailablePackagesStructure.GetBuildPathDirectory(APackage: TFPPackage): string;
+begin
+  Result := FPath+APackage.Name;
+end;
+
+
+end.
+