diff --git a/src/add-ons/kernel/file_systems/packagefs/Dependency.cpp b/src/add-ons/kernel/file_systems/packagefs/Dependency.cpp index a08ea6dd4c..8bf1c17741 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Dependency.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Dependency.cpp @@ -60,3 +60,23 @@ Dependency::ResolvableVersionMatches(Version* resolvableVersion) const return resolvableVersion != NULL && fVersion->Compare(fVersionOperator, *resolvableVersion); } + + +bool +Dependency::ResolvableCompatibleVersionMatches(Version* resolvableVersion) const +{ + if (fVersion == NULL) + return true; + + // Only compare the versions, if the operator indicates that our version is + // some kind of minimum required version. Only in that case the resolvable's + // actual version is required to be greater (or equal) and the backwards + // compatibility check makes sense. + if (fVersionOperator == B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL + || fVersionOperator == B_PACKAGE_RESOLVABLE_OP_GREATER) { + return resolvableVersion != NULL + && fVersion->Compare(fVersionOperator, *resolvableVersion); + } + + return true; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/Dependency.h b/src/add-ons/kernel/file_systems/packagefs/Dependency.h index 0da11cc3d1..bab31c2d5b 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Dependency.h +++ b/src/add-ons/kernel/file_systems/packagefs/Dependency.h @@ -49,6 +49,8 @@ public: { return fResolvable; } bool ResolvableVersionMatches( Version* resolvableVersion) const; + bool ResolvableCompatibleVersionMatches( + Version* resolvableVersion) const; const char* Name() const { return fName; } diff --git a/src/add-ons/kernel/file_systems/packagefs/Resolvable.cpp b/src/add-ons/kernel/file_systems/packagefs/Resolvable.cpp index 4af0036c42..43a7414d0f 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Resolvable.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Resolvable.cpp @@ -16,7 +16,8 @@ Resolvable::Resolvable(::Package* package) fPackage(package), fFamily(NULL), fName(NULL), - fVersion(NULL) + fVersion(NULL), + fCompatibleVersion(NULL) { } @@ -25,13 +26,16 @@ Resolvable::~Resolvable() { free(fName); delete fVersion; + delete fCompatibleVersion; } status_t -Resolvable::Init(const char* name, ::Version* version) +Resolvable::Init(const char* name, ::Version* version, + ::Version* compatibleVersion) { fVersion = version; + fCompatibleVersion = compatibleVersion; fName = strdup(name); if (fName == NULL) diff --git a/src/add-ons/kernel/file_systems/packagefs/Resolvable.h b/src/add-ons/kernel/file_systems/packagefs/Resolvable.h index 302765e2cf..87d4509f61 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Resolvable.h +++ b/src/add-ons/kernel/file_systems/packagefs/Resolvable.h @@ -24,9 +24,11 @@ public: Resolvable(::Package* package); virtual ~Resolvable(); - status_t Init(const char* name, ::Version* version); - // version is optional; object takes over - // ownership (even in case of error) + status_t Init(const char* name, ::Version* version, + ::Version* compatibleVersion); + // version and compatibleVersion are + // optional; object takes over ownership + // (even in case of error) ::Package* Package() const { return fPackage; } @@ -37,6 +39,8 @@ public: const char* Name() const { return fName; } ::Version* Version() const { return fVersion; } + ::Version* CompatibleVersion() const + { return fCompatibleVersion; } void AddDependency(Dependency* dependency); void RemoveDependency(Dependency* dependency); @@ -48,6 +52,7 @@ private: ResolvableFamily* fFamily; char* fName; ::Version* fVersion; + ::Version* fCompatibleVersion; ResolvableDependencyList fDependencies; public: // conceptually package private diff --git a/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp b/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp index c237cd59db..f396eb6b03 100644 --- a/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/ResolvableFamily.cpp @@ -54,7 +54,9 @@ ResolvableFamily::ResolveDependency(Dependency* dependency) { for (FamilyResolvableList::Iterator it = fResolvables.GetIterator(); Resolvable* resolvable = it.Next();) { - if (dependency->ResolvableVersionMatches(resolvable->Version())) { + if (dependency->ResolvableVersionMatches(resolvable->Version()) + && dependency->ResolvableCompatibleVersionMatches( + resolvable->CompatibleVersion())) { resolvable->AddDependency(dependency); return true; } diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 1733b9a27c..b7cee76095 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -318,6 +318,20 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler { } ObjectDeleter versionDeleter(version); + // create a version object, if a compatible version is specified + Version* compatibleVersion = NULL; + if (value.resolvable.haveCompatibleVersion) { + const BPackageVersionData& versionInfo + = value.resolvable.compatibleVersion; + status_t error = Version::Create(versionInfo.major, + versionInfo.minor, versionInfo.micro, + versionInfo.preRelease, versionInfo.release, version); + if (error != B_OK) + RETURN_ERROR(error); + } + ObjectDeleter compatibleVersionDeleter( + compatibleVersion); + // create the resolvable Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage); if (resolvable == NULL) @@ -325,7 +339,7 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler { ObjectDeleter resolvableDeleter(resolvable); status_t error = resolvable->Init(value.resolvable.name, - versionDeleter.Detach()); + versionDeleter.Detach(), compatibleVersionDeleter.Detach()); if (error != B_OK) RETURN_ERROR(error);