1unit pkgFppkg; 2 3{$mode objfpc}{$H+} 4 5interface 6 7uses 8 Classes, 9 SysUtils, 10 contnrs, 11 fprepos, 12 pkgmessages, 13 pkgglobals, 14 pkgoptions, 15 pkgPackagesStructure; 16 17type 18 19 { TpkgFPpkg } 20 21 TpkgPackageKind = (pkgpkInstalled, pkgpkAvailable, pkgpkBoth); 22 TpkgFPpkg = class(TComponent) 23 private 24 FInsideFindBrokenPackages: Integer; 25 FBrokenPackagesDictionary: TFPHashList; 26 27 FFPMakeRepositoryList: TComponentList; 28 FRepositoryList: TComponentList; 29 FOptions: TFppkgOptions; 30 FCompilerOptions: TCompilerOptions; 31 FFpmakeCompilerOptions: TCompilerOptions; 32 FCurrentRemoteRepositoryURL: String; 33 FConfigurationFilename: string; 34 function IncludeRepositoryTypeForPackageKind(ARepositoryType: TFPRepositoryType; 35 APackageKind: TpkgPackageKind): Boolean; 36 procedure ScanPackagesOnDisk(ACompilerOptions: TCompilerOptions; APackageKind: TpkgPackageKind; ARepositoryList: TComponentList); 37 function CreateRepository(ARepoOptionSection: TFppkgRepositoryOptionSection; 38 AnOptions: TFppkgOptions; ACompilerOptions: TCompilerOptions): TFPRepository; 39 function FindPackage(ARepositoryList: TComponentList; APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 40 41 function SelectRemoteMirror:string; 42 procedure EnterFindBrokenPackages; 43 procedure LeaveFindBrokenpackages; 44 45 procedure ClearRepositories(ARepositoryList: TComponentList); 46 function GetConfigurationFilename: string; 47 public 48 constructor Create(AOwner: TComponent); override; 49 destructor Destroy; override; 50 51 procedure InitializeGlobalOptions(CfgFile: string); 52 procedure InitializeCompilerOptions; 53 procedure LoadLocalAvailableMirrors; 54 procedure ScanAvailablePackages; 55 procedure ScanPackages; 56 57 function PackageIsBroken(APackage: TFPPackage; out Reason: string; ARepository: TFPRepository): Boolean; 58 59 function FPMakeRepoFindPackage(APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 60 function FindPackage(APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 61 function PackageByName(APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 62 63 function FindRepository(ARepositoryName: string): TFPRepository; 64 function RepositoryByName(ARepositoryName: string): TFPRepository; 65 66 function GetInstallRepository(ASourcePackage: TFPPackage): TFPRepository; 67 function DetermineSourcePackage(APackageName: String): TFPPackage; 68 function PackageLocalArchive(APackage:TFPPackage): String; 69 function PackageBuildPath(APackage:TFPPackage):String; 70 71 function GetRemoteRepositoryURL(const AFileName:string):string; 72 function PackageRemoteArchive(APackage:TFPPackage): String; 73 74 procedure ScanInstalledPackagesForAvailablePackages; 75 procedure CheckFPMakeDependencies; 76 function FindBrokenPackages(SL:TStrings):Boolean; 77 78 property Options: TFppkgOptions read FOptions; 79 property CompilerOptions: TCompilerOptions read FCompilerOptions; 80 property FpmakeCompilerOptions: TCompilerOptions read FFpmakeCompilerOptions; 81 property FPMakeRepositoryList: TComponentList read FFPMakeRepositoryList; 82 property RepositoryList: TComponentList read FRepositoryList; 83 property ConfigurationFilename: string read GetConfigurationFilename; 84 public 85 86 end; 87 88implementation 89 90uses 91 fpmkunit, 92 fpxmlrep, 93 pkgrepos; 94 95{ TpkgFPpkg } 96 97constructor TpkgFPpkg.Create(AOwner: TComponent); 98begin 99 inherited Create(AOwner); 100 FOptions := TFppkgOptions.Create; 101 FCompilerOptions := TCompilerOptions.Create; 102 FFpmakeCompilerOptions := TCompilerOptions.Create; 103 FRepositoryList := TComponentList.Create(False); 104 FFPMakeRepositoryList := TComponentList.Create(False); 105 FBrokenPackagesDictionary := TFPHashList.Create; 106end; 107 108destructor TpkgFPpkg.Destroy; 109begin 110 FBrokenPackagesDictionary.Free; 111 FFPMakeRepositoryList.Free; 112 FRepositoryList.Free; 113 FCompilerOptions.Free; 114 FFpmakeCompilerOptions.Free; 115 FOptions.Free; 116 inherited Destroy; 117end; 118 119function TpkgFPpkg.IncludeRepositoryTypeForPackageKind(ARepositoryType: TFPRepositoryType; 120 APackageKind: TpkgPackageKind): Boolean; 121begin 122 Result := ((APackageKind=pkgpkInstalled) and (ARepositoryType = fprtInstalled)) or 123 ((APackageKind=pkgpkAvailable) and (ARepositoryType = fprtAvailable)) or 124 (APackageKind=pkgpkBoth); 125end; 126 127procedure TpkgFPpkg.ScanPackagesOnDisk(ACompilerOptions: TCompilerOptions; 128 APackageKind: TpkgPackageKind; ARepositoryList: TComponentList); 129var 130 i: Integer; 131 RepoOption: TFppkgRepositoryOptionSection; 132 Repo: TFPRepository; 133begin 134 FOptions.BindToCompilerOptions(ACompilerOptions); 135 for i := 0 to FOptions.SectionList.Count -1 do 136 begin 137 if FOptions.SectionList[i] is TFppkgRepositoryOptionSection then 138 begin 139 RepoOption := TFppkgRepositoryOptionSection(FOptions.SectionList[i]); 140 if IncludeRepositoryTypeForPackageKind(RepoOption.GetRepositoryType, APackageKind) then 141 begin 142 Repo := CreateRepository(RepoOption, FOptions, ACompilerOptions); 143 if Assigned(Repo) then 144 begin 145 ARepositoryList.Add(Repo); 146 if Assigned(Repo.DefaultPackagesStructure) then 147 Repo.DefaultPackagesStructure.AddPackagesToRepository(Repo); 148 end; 149 end; 150 end; 151 end; 152end; 153 154function TpkgFPpkg.CreateRepository(ARepoOptionSection: TFppkgRepositoryOptionSection; 155 AnOptions: TFppkgOptions; ACompilerOptions: TCompilerOptions): TFPRepository; 156begin 157 Result := TFPRepository.Create(Self); 158 Result.InitializeWithOptions(ARepoOptionSection, AnOptions, ACompilerOptions); 159end; 160 161procedure TpkgFPpkg.InitializeGlobalOptions(CfgFile: string); 162var 163 GeneratedConfig: boolean; 164 FirstRepoConf: TFppkgOptionSection; 165begin 166 GeneratedConfig:=false; 167 // First try specified config file 168 if (CfgFile<>'') then 169 begin 170 if not FileExists(cfgfile) then 171 Error(SErrNoSuchFile,[cfgfile]); 172 end 173 else 174 begin 175 // Now try if a local config-file exists 176 cfgfile:=GetFppkgConfigFile(Options.PreferGlobal,False); 177 if not FileExists(cfgfile) then 178 begin 179 // If not, try to find a global configuration file 180 cfgfile:=GetFppkgConfigFile(not Options.PreferGlobal,False); 181 if not FileExists(cfgfile) then 182 begin 183 // Create a new configuration file 184 if not IsSuperUser then // Make a local, not global, configuration file 185 cfgfile:=GetFppkgConfigFile(False,False); 186 ForceDirectories(ExtractFilePath(cfgfile)); 187 FOptions.SaveToFile(cfgfile); 188 GeneratedConfig:=true; 189 end; 190 end; 191 end; 192 // Load file or create new default configuration 193 if not GeneratedConfig then 194 begin 195 FOptions.LoadFromFile(cfgfile); 196 end; 197 FOptions.CommandLineSection.CompilerConfig:=FOptions.GlobalSection.CompilerConfig; 198 // Tracing of what we've done above, need to be done after the verbosity is set 199 if GeneratedConfig then 200 pkgglobals.Log(llDebug,SLogGeneratingGlobalConfig,[cfgfile]) 201 else 202 pkgglobals.Log(llDebug,SLogLoadingGlobalConfig,[cfgfile]); 203 FConfigurationFilename := CfgFile; 204 // Log configuration 205 FOptions.LogValues(llDebug); 206end; 207 208procedure TpkgFPpkg.InitializeCompilerOptions; 209var 210 S : String; 211begin 212 // Load default compiler config 213 S:=FOptions.GlobalSection.CompilerConfigDir+FOptions.CommandLineSection.CompilerConfig; 214 FCompilerOptions.UpdateLocalRepositoryOption(FOptions); 215 if FileExists(S) then 216 begin 217 pkgglobals.Log(llDebug,SLogLoadingCompilerConfig,[S]); 218 FCompilerOptions.LoadCompilerFromFile(S); 219 if FCompilerOptions.SaveInifileChanges then 220 // The file is in an old format, try to update the file but ignore 221 // any failures. 222 FCompilerOptions.SaveCompilerToFile(S); 223 end 224 else 225 begin 226 if FCompilerOptions.SaveInifileChanges then 227 // A new fppkg.cfg has been created, try to create a new compiler-configuration 228 // file too. 229 begin 230 pkgglobals.Log(llDebug,SLogGeneratingCompilerConfig,[S]); 231 FCompilerOptions.InitCompilerDefaults; 232 if not FCompilerOptions.SaveCompilerToFile(S) then 233 Error(SErrMissingCompilerConfig,[S]); 234 end 235 else 236 Error(SErrMissingCompilerConfig,[S]); 237 end; 238 // Log compiler configuration 239 FCompilerOptions.LogValues(llDebug,''); 240 // Load FPMake compiler config, this is normally the same config as above 241 S:=FOptions.GlobalSection.CompilerConfigDir+FOptions.GlobalSection.FPMakeCompilerConfig; 242 FFPMakeCompilerOptions.UpdateLocalRepositoryOption(FOptions); 243 if FileExists(S) then 244 begin 245 pkgglobals.Log(llDebug,SLogLoadingFPMakeCompilerConfig,[S]); 246 FFPMakeCompilerOptions.LoadCompilerFromFile(S); 247 if FFPMakeCompilerOptions.SaveInifileChanges then 248 // The file is in an old format, try to update the file but ignore 249 // any failures. 250 FFPMakeCompilerOptions.SaveCompilerToFile(S); 251 end 252 else 253 Error(SErrMissingCompilerConfig,[S]); 254 // Log compiler configuration 255 FFPMakeCompilerOptions.LogValues(llDebug,'fpmake-building'); 256end; 257 258procedure TpkgFPpkg.LoadLocalAvailableMirrors; 259var 260 S : String; 261 X : TFPXMLMirrorHandler; 262begin 263 if assigned(AvailableMirrors) then 264 AvailableMirrors.Free; 265 AvailableMirrors:=TFPMirrors.Create(TFPMirror); 266 267 // Repository 268 S:=Options.GlobalSection.LocalMirrorsFile; 269 log(llDebug,SLogLoadingMirrorsFile,[S]); 270 if not FileExists(S) then 271 exit; 272 try 273 X:=TFPXMLMirrorHandler.Create; 274 With X do 275 try 276 LoadFromXml(AvailableMirrors,S); 277 finally 278 Free; 279 end; 280 except 281 on E : Exception do 282 begin 283 Log(llError,E.Message); 284 Error(SErrCorruptMirrorsFile,[S]); 285 end; 286 end; 287end; 288 289procedure TpkgFPpkg.ScanAvailablePackages; 290var 291 Repo: TFPRepository; 292 InstPackages: TFPCustomPackagesStructure; 293begin 294 if (FOptions.GlobalSection.RemoteMirrorsURL<>'') or 295 ((FOptions.GlobalSection.RemoteRepository<>'') and (FOptions.GlobalSection.RemoteRepository<>'auto')) then 296 begin 297 // In case of a re-scan (for example after an update), remove the old list 298 Repo := FindRepository('Available'); 299 if Assigned(Repo) then 300 begin 301 RepositoryList.Remove(Repo); 302 Repo.Free; 303 end; 304 305 Repo := TFPRepository.Create(Self); 306 FRepositoryList.Add(Repo); 307 Repo.RepositoryName := 'Available'; 308 Repo.Description := 'Packages available for download'; 309 Repo.RepositoryType := fprtAvailable; 310 InstPackages := TFPRemotePackagesStructure.Create(Self); 311 InstPackages.InitializeWithOptions(Nil, FOptions, FCompilerOptions); 312 InstPackages.AddPackagesToRepository(Repo); 313 Repo.DefaultPackagesStructure := InstPackages; 314 end; 315end; 316 317procedure TpkgFPpkg.ScanPackages; 318begin 319 // There is no need to scan for available packages and add them to the 320 // FPMakeRepositoryList. Beside that it could lead to problems 321 // when the scan of one of the available-repositories tries to compile an 322 // fpmake-executable. (Like TFPUninstalledSourcesAvailablePackagesStructure does) 323 ClearRepositories(FPMakeRepositoryList); 324 ScanPackagesOnDisk(FFpmakeCompilerOptions, pkgpkInstalled, FPMakeRepositoryList); 325 326 CheckFPMakeDependencies; 327 328 ClearRepositories(RepositoryList); 329 ScanPackagesOnDisk(FCompilerOptions, pkgpkBoth, RepositoryList); 330 ScanAvailablePackages; 331end; 332 333function TpkgFPpkg.PackageIsBroken(APackage: TFPPackage; out Reason: string; ARepository: TFPRepository): Boolean; 334var 335 j, i, ThisRepositoryIndex: Integer; 336 Dependency: TFPDependency; 337 Repository: TFPRepository; 338 DepPackage: TFPPackage; 339 HashPtr: PtrInt; 340begin 341 result:=false; 342 Reason := ''; 343 if Assigned(APackage.Repository) and (APackage.Repository.RepositoryType <> fprtInstalled) then 344 begin 345 Exit; 346 end; 347 348 EnterFindBrokenPackages; 349 try 350 HashPtr := PtrInt(FBrokenPackagesDictionary.Find(APackage.Name)); 351 if HashPtr<>0 then 352 begin 353 // Package is already evaluated 354 Result := (HashPtr = 1); 355 Exit; 356 end; 357 if not Assigned(ARepository) then 358 begin 359 // Check with all repositories 360 ThisRepositoryIndex := RepositoryList.Count -1; 361 end 362 else 363 begin 364 // We should only check for dependencies in this repository, or repositories 365 // with a lower priority. 366 367 // This behaviour seems obsolete. The idea behind it was that each repository 368 // should be useable, only using other repositories with a lower priority. 369 // In practice this does not work, you have to consider the installation 370 // as a whole, using all repositories. One specific user might not be able 371 // to 'fix' the global fpc-repository, and so end up with broken packages 372 // which he/she can not fix. Or packages may be forced to be installed in 373 // a specific repository. 374 // The functionality is kept for now, maybe there is a need for it in the 375 // future... But for now, ARepository will be always nil. 376 ThisRepositoryIndex := -1; 377 for i := RepositoryList.Count -1 downto 0 do 378 begin 379 if RepositoryList.Items[i] = ARepository then 380 ThisRepositoryIndex := i; 381 end; 382 end; 383 384 for j:=0 to APackage.Dependencies.Count-1 do 385 begin 386 Dependency:=APackage.Dependencies[j]; 387 if (CompilerOptions.CompilerOS in Dependency.OSes) and 388 (CompilerOptions.CompilerCPU in Dependency.CPUs) then 389 begin 390 DepPackage := nil; 391 for i := ThisRepositoryIndex downto 0 do 392 begin 393 Repository := RepositoryList.Items[i] as TFPRepository; 394 if Repository.RepositoryType=fprtInstalled then 395 DepPackage := Repository.FindPackage(Dependency.PackageName); 396 if Assigned(DepPackage) then 397 Break; 398 end; 399 400 if assigned(DepPackage) then 401 begin 402 if PackageIsBroken(DepPackage, Reason, ARepository) then 403 begin 404 log(llInfo,SLogPackageDepBroken,[APackage.Name,APackage.Repository.RepositoryName,Dependency.PackageName,Repository.RepositoryName]); 405 result:=true; 406 Reason := Format(SInfoPackageDepBroken, [Dependency.PackageName, Repository.RepositoryName]); 407 FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1)); 408 exit; 409 end; 410 if (Dependency.RequireChecksum<>$ffffffff) and (DepPackage.Checksum<>Dependency.RequireChecksum) then 411 begin 412 log(llInfo,SLogPackageChecksumChanged,[APackage.Name,APackage.Repository.RepositoryName,Dependency.PackageName,Repository.RepositoryName]); 413 result:=true; 414 Reason := Format(SInfoPackageChecksumChanged, [Dependency.PackageName, Repository.RepositoryName]); 415 FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1)); 416 exit; 417 end; 418 end 419 else 420 begin 421 log(llInfo,SDbgObsoleteDependency,[APackage.Name,Dependency.PackageName]); 422 result:=true; 423 Reason :=Format(SInfoObsoleteDependency, [Dependency.PackageName]); 424 FBrokenPackagesDictionary.Add(APackage.Name, Pointer(1)); 425 exit; 426 end; 427 end; 428 end; 429 FBrokenPackagesDictionary.Add(APackage.Name, Pointer(2)); 430 finally 431 LeaveFindBrokenpackages; 432 end; 433end; 434 435function TpkgFPpkg.FPMakeRepoFindPackage(APackageName: string; 436 APackageKind: TpkgPackageKind): TFPPackage; 437begin 438 Result := FindPackage(FPMakeRepositoryList, APackageName, APackageKind); 439end; 440 441function TpkgFPpkg.FindPackage(APackageName: string; 442 APackageKind: TpkgPackageKind): TFPPackage; 443begin 444 Result := FindPackage(RepositoryList, APackageName, APackageKind); 445end; 446 447function TpkgFPpkg.FindPackage(ARepositoryList: TComponentList; APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 448var 449 i: Integer; 450 Repo: TFPRepository; 451begin 452 Result := nil; 453 for i := ARepositoryList.Count-1 downto 0 do 454 begin 455 Repo := ARepositoryList.Items[i] as TFPRepository; 456 if IncludeRepositoryTypeForPackageKind(Repo.RepositoryType, APackageKind) then 457 begin 458 Result := repo.FindPackage(APackageName); 459 if Assigned(Result) then 460 Break; 461 end; 462 end; 463end; 464 465function TpkgFPpkg.SelectRemoteMirror: string; 466var 467 i,j : Integer; 468 Bucket, 469 BucketCnt : Integer; 470 M : TFPMirror; 471begin 472 Result:=''; 473 M:=nil; 474 if assigned(AvailableMirrors) then 475 begin 476 // Create array for selection 477 BucketCnt:=0; 478 for i:=0 to AvailableMirrors.Count-1 do 479 inc(BucketCnt,AvailableMirrors[i].Weight); 480 // Select random entry 481 Bucket:=Random(BucketCnt); 482 M:=nil; 483 for i:=0 to AvailableMirrors.Count-1 do 484 begin 485 for j:=0 to AvailableMirrors[i].Weight-1 do 486 begin 487 if Bucket=0 then 488 begin 489 M:=AvailableMirrors[i]; 490 break; 491 end; 492 Dec(Bucket); 493 end; 494 if assigned(M) then 495 break; 496 end; 497 end; 498 if assigned(M) then 499 begin 500 log(llInfo,SLogSelectedMirror,[M.Name]); 501 Result:=M.URL; 502 end 503 else 504 Error(SErrFailedToSelectMirror); 505end; 506 507procedure TpkgFPpkg.EnterFindBrokenPackages; 508begin 509 Assert((FInsideFindBrokenPackages>0) or (FBrokenPackagesDictionary.Count=0)); 510 Inc(FInsideFindBrokenPackages) 511end; 512 513procedure TpkgFPpkg.LeaveFindBrokenpackages; 514begin 515 Assert(FInsideFindBrokenPackages>0); 516 Dec(FInsideFindBrokenPackages); 517 if FInsideFindBrokenPackages=0 then 518 FBrokenPackagesDictionary.Clear; 519end; 520 521procedure TpkgFPpkg.ClearRepositories(ARepositoryList: TComponentList); 522var 523 i: Integer; 524 Repo: TFPRepository; 525begin 526 for i := ARepositoryList.Count -1 downto 0 do 527 begin 528 Repo := ARepositoryList.Items[i] as TFPRepository; 529 if Repo.Name <> 'Available' then 530 begin 531 ARepositoryList.Delete(i); 532 Repo.Free; 533 end; 534 end; 535end; 536 537function TpkgFPpkg.PackageByName(APackageName: string; APackageKind: TpkgPackageKind): TFPPackage; 538var 539 ErrStr: string; 540begin 541 Result := FindPackage(APackageName, APackageKind); 542 If Result=Nil then 543 begin 544 case APackageKind of 545 pkgpkInstalled : ErrStr:=SErrMissingInstallPackage; 546 pkgpkAvailable : ErrStr:=SErrMissingAvailablePackage; 547 pkgpkBoth : ErrStr:=SErrMissingPackage; 548 end; 549 Raise EPackage.CreateFmt(ErrStr,[APackageName]); 550 end; 551end; 552 553function TpkgFPpkg.FindRepository(ARepositoryName: string): TFPRepository; 554var 555 i: Integer; 556 Repo: TFPRepository; 557begin 558 Result := nil; 559 for i := FRepositoryList.Count-1 downto 0 do 560 begin 561 Repo := FRepositoryList.Items[i] as TFPRepository; 562 if Repo.RepositoryName = ARepositoryName then 563 begin 564 Result := Repo; 565 Break; 566 end; 567 end; 568end; 569 570function TpkgFPpkg.RepositoryByName(ARepositoryName: string): TFPRepository; 571begin 572 Result := FindRepository(ARepositoryName); 573 If Result=Nil then 574 Raise EPackage.CreateFmt(SErrMissingInstallRepo,[ARepositoryName]); 575end; 576 577function TpkgFPpkg.GetInstallRepository(ASourcePackage: TFPPackage): TFPRepository; 578var 579 SourceRepository: TFPRepository; 580 RepoName: string; 581 i: Integer; 582begin 583 // Determine the repository to install a package into. See the 584 // repositorylogics.dia file. 585 pkgglobals.Log(llDebug, SLogDetermineInstallRepo, [ASourcePackage.GetDebugName]); 586 RepoName := Options.CommandLineSection.InstallRepository; 587 if RepoName <> '' then 588 // If an install-repository is given on the command line, this overrides 589 // everything. 590 pkgglobals.Log(llDebug, SLogUseCommandLineRepo, [RepoName]) 591 else 592 begin 593 // The source-repository is already determined by the source-package, which 594 // is a member of the source-repository. 595 SourceRepository := ASourcePackage.Repository; 596 Assert(Assigned(SourceRepository)); 597 Assert(SourceRepository.RepositoryType = fprtAvailable); 598 599 // For now, skip the check for original sources of already installed packages. 600 601 Assert(Assigned(SourceRepository.DefaultPackagesStructure)); 602 RepoName := SourceRepository.DefaultPackagesStructure.InstallRepositoryName; 603 if RepoName<>'' then 604 pkgglobals.Log(llDebug, SLogUseSourceRepoInstRepo, [RepoName, SourceRepository.RepositoryName]) 605 else 606 begin 607 RepoName := Options.GlobalSection.InstallRepository; 608 if RepoName<>'' then 609 pkgglobals.Log(llDebug, SLogUseConfigurationRepo, [RepoName]) 610 else 611 begin 612 for i := RepositoryList.Count-1 downto 0 do 613 begin 614 if (RepositoryList[i] as TFPRepository).RepositoryType = fprtInstalled then 615 begin 616 Result := TFPRepository(RepositoryList[i]); 617 pkgglobals.Log(llDebug, SLogUseLastRepo, [Result.RepositoryName]); 618 Exit; 619 end; 620 end; 621 raise EPackage.Create(SErrNoInstallRepoAvailable); 622 end; 623 end; 624 end; 625 Result := RepositoryByName(RepoName); 626end; 627 628function TpkgFPpkg.DetermineSourcePackage(APackageName: String): TFPPackage; 629begin 630 Result := FindPackage(APackageName, pkgpkAvailable); 631end; 632 633function TpkgFPpkg.PackageLocalArchive(APackage: TFPPackage): String; 634begin 635 if APackage.Name=CurrentDirPackageName then 636 Error(SErrNoPackageSpecified) 637 else if APackage.Name=CmdLinePackageName then 638 Result:=APackage.LocalFileName 639 else 640 Result:=Options.GlobalSection.ArchivesDir+APackage.FileName; 641end; 642 643procedure TpkgFPpkg.ScanInstalledPackagesForAvailablePackages; 644var 645 i: Integer; 646 Repo, AvailableRepo: TFPRepository; 647 AvailStruc: TFPOriginalSourcePackagesStructure; 648begin 649 for i := 0 to FRepositoryList.Count-1 do 650 begin 651 Repo := FRepositoryList.Items[i] as TFPRepository; 652 if Repo.RepositoryType = fprtInstalled then 653 begin 654 AvailableRepo := TFPRepository.Create(Self); 655 FRepositoryList.Add(AvailableRepo); 656 AvailableRepo.RepositoryType := fprtAvailable; 657 AvailableRepo.RepositoryName := Repo.RepositoryName + '_source'; 658 AvailableRepo.Description := Repo.Description + ' (original sources)'; 659 AvailStruc := TFPOriginalSourcePackagesStructure.Create(Self, Repo); 660 AvailStruc.InitializeWithOptions(nil, FOptions, FCompilerOptions); 661 AvailStruc.InstallRepositoryName := Repo.RepositoryName; 662 AvailStruc.AddPackagesToRepository(AvailableRepo); 663 AvailableRepo.DefaultPackagesStructure := AvailStruc; 664 end; 665 end; 666end; 667 668procedure TpkgFPpkg.CheckFPMakeDependencies; 669var 670 i : Integer; 671 P,AvailP : TFPPackage; 672 AvailVerStr : string; 673 ReqVer : TFPVersion; 674begin 675 // Reset availability 676 for i:=0 to high(FPMKUnitDeps) do 677 FPMKUnitDeps[i].available:=false; 678 // Not version check needed in Recovery mode, we always need to use 679 // the internal bootstrap procedure 680 if Options.CommandLineSection.RecoveryMode then 681 exit; 682 // Check for fpmkunit dependencies 683 for i:=0 to high(FPMKUnitDeps) do 684 begin 685 P:=FPMakeRepoFindPackage(FPMKUnitDeps[i].package, pkgpkInstalled); 686 if P<>nil then 687 begin 688 AvailP:=FindPackage(FPMKUnitDeps[i].package, pkgpkAvailable); 689 if AvailP<>nil then 690 AvailVerStr:=AvailP.Version.AsString 691 else 692 AvailVerStr:='<not available>'; 693 ReqVer:=TFPVersion.Create; 694 try 695 ReqVer.AsString:=FPMKUnitDeps[i].ReqVer; 696 log(llDebug,SLogFPMKUnitDepVersion,[P.Name,ReqVer.AsString,P.Version.AsString,AvailVerStr]); 697 if ReqVer.CompareVersion(P.Version)<=0 then 698 FPMKUnitDeps[i].available:=true 699 else 700 log(llDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]); 701 finally 702 ReqVer.Free; 703 end; 704 end 705 else 706 log(llDebug,SLogFPMKUnitDepTooOld,[FPMKUnitDeps[i].package]); 707 end; 708end; 709 710function TpkgFPpkg.FindBrokenPackages(SL: TStrings): Boolean; 711var 712 i,j,k : integer; 713 P : TFPPackage; 714 s : string; 715 Repo: TFPRepository; 716begin 717 SL.Clear; 718 EnterFindBrokenPackages; 719 try 720 for i:=0 to RepositoryList.Count-1 do 721 begin 722 Repo := TFPRepository(RepositoryList[i]); 723 if Repo.RepositoryType = fprtInstalled then 724 begin 725 for j := 0 to Repo.PackageCount-1 do 726 begin 727 P := Repo.Packages[j]; 728 if (P = FindPackage(P.Name, pkgpkInstalled)) and PackageIsBroken(P, s, nil) then 729 begin 730 if P.IsFPMakeAddIn then 731 // Make sure that FPMakeAddIn's are fixed first, so 732 // as much packages are compiled with them. 733 SL.Insert(0, P.Name) 734 else 735 SL.Add(P.Name); 736 end; 737 end; 738 end; 739 end; 740 finally 741 LeaveFindBrokenpackages; 742 end; 743 Result:=(SL.Count>0); 744end; 745 746function TpkgFPpkg.PackageBuildPath(APackage: TFPPackage): String; 747begin 748 if (APackage.Name=CmdLinePackageName) or (APackage.Name=URLPackageName) then 749 Result:=Options.GlobalSection.BuildDir+ChangeFileExt(ExtractFileName(APackage.LocalFileName),'') 750 else if Assigned(APackage.PackagesStructure) and (APackage.PackagesStructure.GetBuildPathDirectory(APackage)<>'') then 751 Result:=APackage.PackagesStructure.GetBuildPathDirectory(APackage) 752 else 753 Result:=Options.GlobalSection.BuildDir+APackage.Name; 754end; 755 756function TpkgFPpkg.GetRemoteRepositoryURL(const AFileName: string): string; 757begin 758 if FCurrentRemoteRepositoryURL='' then 759 begin 760 if Options.GlobalSection.RemoteRepository='auto' then 761 FCurrentRemoteRepositoryURL:=SelectRemoteMirror 762 else 763 FCurrentRemoteRepositoryURL:=Options.GlobalSection.RemoteRepository; 764 end; 765 result := FCurrentRemoteRepositoryURL; 766 if result <> '' then 767 begin 768 if result[length(result)]<>'/' then 769 result := result + '/'; 770 Result:=Result+CompilerOptions.CompilerVersion+'/'+AFileName; 771 end; 772end; 773 774function TpkgFPpkg.PackageRemoteArchive(APackage: TFPPackage): String; 775begin 776 if APackage.Name=CurrentDirPackageName then 777 Error(SErrNoPackageSpecified) 778 else if APackage.Name=CmdLinePackageName then 779 Error(SErrPackageIsLocal); 780 if APackage.DownloadURL<>'' then 781 Result:=APackage.DownloadURL 782 else 783 Result:=GetRemoteRepositoryURL(APackage.FileName); 784end; 785 786function TpkgFPpkg.GetConfigurationFilename: string; 787begin 788 Result := FConfigurationFilename; 789end; 790 791end. 792 793