hrev46301 adds 4 changesets to branch 'master' old head: f87dd6dceb506ad3c779cd5c095270abf1c051e0 new head: 577411006e688240df57ccb1e358cacf4651a4ce overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5774110+%5Ef87dd6d ---------------------------------------------------------------------------- 79d2983: BPackageInfo::StringBuilder: Fix string escaping 690bccd: BPackageInfo::StringBuilder: Fix writing non-string lists Even a list with only one element needs to be enclosed in {...}. a4bdd98: BPackageInfo::Parser: Fix parsing the requires operator For entries without operator (and version) an invalid enum value would be used for the resulting BPackageResolvableExpression. Now it's B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT in that case. 5774110: Update requires entries for the packages we build * Add build tool update_package_requires. Given a package info file and a repository cache file, it updates the minimum versions of the requires entries of the package info file according to what is provided by the repository. * PreprocessPackageInfo rule: Use update_package_requires (with the HaikuPorts repository file). [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 6 files changed, 223 insertions(+), 19 deletions(-) build/jam/PackageRules | 18 +- src/kits/package/PackageInfoParser.cpp | 8 +- src/kits/package/PackageInfoStringBuilder.h | 25 ++- src/tools/Jamfile | 3 +- src/tools/update_package_requires/Jamfile | 11 ++ .../update_package_requires.cpp | 177 +++++++++++++++++++ ############################################################################ Commit: 79d29839bf2baca4ca1f75b209994796fe23ddaa URL: http://cgit.haiku-os.org/haiku/commit/?id=79d2983 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Oct 30 00:50:00 2013 UTC BPackageInfo::StringBuilder: Fix string escaping ---------------------------------------------------------------------------- diff --git a/src/kits/package/PackageInfoStringBuilder.h b/src/kits/package/PackageInfoStringBuilder.h index a21aa5e..db3b988 100644 --- a/src/kits/package/PackageInfoStringBuilder.h +++ b/src/kits/package/PackageInfoStringBuilder.h @@ -282,7 +282,11 @@ private: replacement[0] = '\\'; _Write(replacement, 2); + start = ++end; } + + if (start < end) + _Write(start, end - start); } else _Write(data); ############################################################################ Commit: 690bccd46abf943e5e269d27863bf531ad0d13a5 URL: http://cgit.haiku-os.org/haiku/commit/?id=690bccd Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Oct 30 00:51:23 2013 UTC BPackageInfo::StringBuilder: Fix writing non-string lists Even a list with only one element needs to be enclosed in {...}. ---------------------------------------------------------------------------- diff --git a/src/kits/package/PackageInfoStringBuilder.h b/src/kits/package/PackageInfoStringBuilder.h index db3b988..4e4c33d 100644 --- a/src/kits/package/PackageInfoStringBuilder.h +++ b/src/kits/package/PackageInfoStringBuilder.h @@ -130,21 +130,16 @@ private: // encapsulating the stringification via templates seems to result in // an Internal Compiler Error with gcc 2. - int32 count = value.CountItems(); - if (count == 1) { - _WriteListElement(value.ItemAt(0)); - } else { - _Write("{\n", 2); - - int32 count = value.CountItems(); - for (int32 i = 0; i < count; i++) { - _Write('\t'); - _WriteListElement(value.ItemAt(i)); - _Write('\n'); - } + _Write("{\n", 2); - _Write('}'); + int32 count = value.CountItems(); + for (int32 i = 0; i < count; i++) { + _Write('\t'); + _WriteListElement(value.ItemAt(i)); + _Write('\n'); } + + _Write('}'); } template<typename Value> ############################################################################ Commit: a4bdd98c7a118f9eab1b3c4e3334a8fcb8d5df74 URL: http://cgit.haiku-os.org/haiku/commit/?id=a4bdd98 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Oct 30 01:07:56 2013 UTC BPackageInfo::Parser: Fix parsing the requires operator For entries without operator (and version) an invalid enum value would be used for the resulting BPackageResolvableExpression. Now it's B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT in that case. ---------------------------------------------------------------------------- diff --git a/src/kits/package/PackageInfoParser.cpp b/src/kits/package/PackageInfoParser.cpp index 377e8e8..1bdc870 100644 --- a/src/kits/package/PackageInfoParser.cpp +++ b/src/kits/package/PackageInfoParser.cpp @@ -600,6 +600,7 @@ BPackageInfo::Parser::_ParseResolvableExprList( BPackageVersion version; Token op = parser._NextToken(); + BPackageResolvableOperator resolvableOperator; if (op.type == TOKEN_OPERATOR_LESS || op.type == TOKEN_OPERATOR_LESS_EQUAL || op.type == TOKEN_OPERATOR_EQUAL @@ -621,18 +622,19 @@ BPackageInfo::Parser::_ParseResolvableExprList( } else parser._RewindTo(base); } + + resolvableOperator = (BPackageResolvableOperator) + (op.type - TOKEN_OPERATOR_LESS); } else if (op.type == TOKEN_ITEM_SEPARATOR || op.type == TOKEN_CLOSE_BRACE) { parser._RewindTo(op); + resolvableOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT; } else { throw ParseError( "expected '<', '<=', '==', '!=', '>=', '>', comma or '}'", op.pos); } - BPackageResolvableOperator resolvableOperator - = (BPackageResolvableOperator)(op.type - TOKEN_OPERATOR_LESS); - value->AddItem(new BPackageResolvableExpression(token.text, resolvableOperator, version)); } ############################################################################ Revision: hrev46301 Commit: 577411006e688240df57ccb1e358cacf4651a4ce URL: http://cgit.haiku-os.org/haiku/commit/?id=5774110 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Oct 30 01:15:45 2013 UTC Update requires entries for the packages we build * Add build tool update_package_requires. Given a package info file and a repository cache file, it updates the minimum versions of the requires entries of the package info file according to what is provided by the repository. * PreprocessPackageInfo rule: Use update_package_requires (with the HaikuPorts repository file). ---------------------------------------------------------------------------- diff --git a/build/jam/PackageRules b/build/jam/PackageRules index 23abfa4..ea0a6ae 100644 --- a/build/jam/PackageRules +++ b/build/jam/PackageRules @@ -58,14 +58,23 @@ rule PreprocessPackageInfo source : directory : architecture } local revisionFile = [ DetermineHaikuRevision ] ; + local updateRequiresFiles ; + local haikuPortsRepositoryFile ; + if ! $(HAIKU_BOOTSTRAP_BUILD) { + updateRequiresFiles = + <build>update_package_requires + [ on <repository>HaikuPorts return $(HAIKU_REPOSITORY_CACHE_FILE) ] + ; + } MakeLocate $(target) : $(directory) ; - Depends $(target) : $(source) $(revisionFile) ; + Depends $(target) : $(source) $(revisionFile) $(updateRequiresFiles) ; CCDEFS on $(target) = [ FDefines $(defines) ] ; HAIKU_SED_REPLACEMENTS on $(target) = "-e s,$(sedReplacements),g" ; - PreprocessPackageInfo1 $(target) : $(source) $(revisionFile) ; + PreprocessPackageInfo1 $(target) : $(source) $(revisionFile) + $(updateRequiresFiles) ; return $(target) ; } @@ -77,6 +86,11 @@ actions PreprocessPackageInfo1 sed $(HAIKU_SED_REPLACEMENTS) \ -e s,%HAIKU_VERSION%,$(HAIKU_VERSION)_${revision:-0}-1, < $(2[1]) \ | $(HOST_CC) -E -w $(CCDEFS) - -o $(1) + + if [ -n "$(2[4]:E)" ]; then + $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) + "$(2[3])" "$(1)" "$(2[4])" || exit 1 + fi } diff --git a/src/tools/Jamfile b/src/tools/Jamfile index e540625..f4014ed 100644 --- a/src/tools/Jamfile +++ b/src/tools/Jamfile @@ -109,7 +109,8 @@ SubInclude HAIKU_TOP src tools remote_disk_server ; SubInclude HAIKU_TOP src tools resattr ; SubInclude HAIKU_TOP src tools rman ; SubInclude HAIKU_TOP src tools translation ; +SubInclude HAIKU_TOP src tools unflatten ; SubInclude HAIKU_TOP src tools unzip ; +SubInclude HAIKU_TOP src tools update_package_requires ; SubInclude HAIKU_TOP src tools vmdkimage ; -SubInclude HAIKU_TOP src tools unflatten ; SubInclude HAIKU_TOP src tools zip ; diff --git a/src/tools/update_package_requires/Jamfile b/src/tools/update_package_requires/Jamfile new file mode 100644 index 0000000..d24f405 --- /dev/null +++ b/src/tools/update_package_requires/Jamfile @@ -0,0 +1,11 @@ +SubDir HAIKU_TOP src tools update_package_requires ; + +UsePrivateBuildHeaders shared ; + +USES_BE_API on <build>update_package_requires = true ; + +BuildPlatformMain <build>update_package_requires : + update_package_requires.cpp + : + libpackage_build.so $(HOST_LIBBE) $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) + ; diff --git a/src/tools/update_package_requires/update_package_requires.cpp b/src/tools/update_package_requires/update_package_requires.cpp new file mode 100644 index 0000000..ea944d5 --- /dev/null +++ b/src/tools/update_package_requires/update_package_requires.cpp @@ -0,0 +1,177 @@ +/* + * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <list> +#include <map> + +#include <package/PackageInfo.h> +#include <package/PackageResolvable.h> +#include <package/PackageResolvableExpression.h> +#include <package/RepositoryCache.h> + + +using namespace BPackageKit; + + +typedef std::list<BPackageResolvable*> ProvidesList; + + +static const char* sProgramName = "update_package_requires"; + + +#define DIE(result, msg...) \ +do { \ + fprintf(stderr, "*** " msg); \ + fprintf(stderr, " : %s\n", strerror(result)); \ + exit(5); \ +} while(0) + + +static void +print_usage_and_exit(bool error) +{ + fprintf(error ? stderr : stdout, + "Usage: %s <package info> <repository>\n" + "Updates the versions in the \"requires\" list of the given package\n" + "info file using the available package information from the given\n" + "repository cache file <repository>.\n", + sProgramName); + exit(error ? 1 : 0); +} + + +static void +update_requires_expression(BPackageResolvableExpression& expression, + const ProvidesList& providesList) +{ + // find the best-matching provides + BPackageResolvable* bestProvides = NULL; + for (ProvidesList::const_iterator it = providesList.begin(); + it != providesList.end(); ++it) { + BPackageResolvable* provides = *it; + if (!expression.Matches(*provides)) + continue; + + if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK + || (provides->Version().InitCheck() == B_OK + && provides->Version().Compare(bestProvides->Version()) > 0)) { + bestProvides = provides; + } + } + + if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK) + return; + + // Update the expression. Enforce the minimum found version, if the requires + // has no version requirement or also a minimum. Otherwise enforce the exact + // version found. + BPackageResolvableOperator newOperator = B_PACKAGE_RESOLVABLE_OP_EQUAL; + switch (expression.Operator()) { + case B_PACKAGE_RESOLVABLE_OP_LESS: + case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL: + case B_PACKAGE_RESOLVABLE_OP_EQUAL: + case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL: + break; + case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL: + case B_PACKAGE_RESOLVABLE_OP_GREATER: + case B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT: + newOperator = B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL; + break; + } + + expression.SetTo(expression.Name(), newOperator, bestProvides->Version()); +} + + +int +main(int argc, const char* const* argv) +{ + if (argc != 3) + print_usage_and_exit(true); + + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) + print_usage_and_exit(false); + + const char* const packageInfoPath = argv[1]; + const char* const repositoryCachePath = argv[2]; + + // read the repository cache + BRepositoryCache repositoryCache; + status_t error = repositoryCache.SetTo(repositoryCachePath); + if (error != B_OK) { + DIE(error, "failed to read repository cache file \"%s\"", + repositoryCachePath); + } + + // create a map for all provides (name -> resolvable list) + typedef std::map<BString, ProvidesList> ProvidesMap; + + ProvidesMap providesMap; + + for (BRepositoryCache::Iterator it = repositoryCache.GetIterator(); + const BPackageInfo* info = it.Next();) { + const BObjectList<BPackageResolvable>& provides = info->ProvidesList(); + int32 count = provides.CountItems(); + for (int32 i = 0; i < count; i++) { + BPackageResolvable* resolvable = provides.ItemAt(i); + ProvidesList& providesList = providesMap[resolvable->Name()]; + providesList.push_back(resolvable); + } + } + + // load the package info + BPackageInfo packageInfo; + error = packageInfo.ReadFromConfigFile(packageInfoPath); + if (error != B_OK) + DIE(error, "failed to read package info file \"%s\"", packageInfoPath); + + // clone the package info's requires list + typedef std::list<BPackageResolvableExpression> RequiresList; + RequiresList requiresList; + int32 requiresCount = packageInfo.RequiresList().CountItems(); + for (int32 i = 0; i < requiresCount; i++) + requiresList.push_back(*packageInfo.RequiresList().ItemAt(i)); + + // rebuild the requires list with updated versions + packageInfo.ClearRequiresList(); + for (RequiresList::iterator it = requiresList.begin(); + it != requiresList.end(); ++it) { + BPackageResolvableExpression expression = *it; + ProvidesMap::iterator foundIt = providesMap.find(expression.Name()); + if (foundIt != providesMap.end()) + update_requires_expression(expression, foundIt->second); + + error = packageInfo.AddRequires(expression); + if (error != B_OK) + DIE(error, "failed to add requires item to package info"); + } + + // write updated package info + BString configString; + error = packageInfo.GetConfigString(configString); + if (error != B_OK) + DIE(error, "failed to get updated package info string"); + + FILE* file = fopen(packageInfoPath, "w"); + if (file == NULL) { + DIE(errno, "failed to open package info file \"%s\" for writing", + packageInfoPath); + } + + if (fwrite(configString.String(), configString.Length(), 1, file) != 1) { + DIE(errno, "failed to write updated package info file \"%s\"", + packageInfoPath); + } + + fclose(file); + + return 0; +}