HaikuDepot: notify work status from main window
[haiku.git] / src / tools / update_package_requires / update_package_requires.cpp
blobea944d59a218568bc2364fbd4ed30bd7f0decdc0
1 /*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <list>
13 #include <map>
15 #include <package/PackageInfo.h>
16 #include <package/PackageResolvable.h>
17 #include <package/PackageResolvableExpression.h>
18 #include <package/RepositoryCache.h>
21 using namespace BPackageKit;
24 typedef std::list<BPackageResolvable*> ProvidesList;
27 static const char* sProgramName = "update_package_requires";
30 #define DIE(result, msg...) \
31 do { \
32 fprintf(stderr, "*** " msg); \
33 fprintf(stderr, " : %s\n", strerror(result)); \
34 exit(5); \
35 } while(0)
38 static void
39 print_usage_and_exit(bool error)
41 fprintf(error ? stderr : stdout,
42 "Usage: %s <package info> <repository>\n"
43 "Updates the versions in the \"requires\" list of the given package\n"
44 "info file using the available package information from the given\n"
45 "repository cache file <repository>.\n",
46 sProgramName);
47 exit(error ? 1 : 0);
51 static void
52 update_requires_expression(BPackageResolvableExpression& expression,
53 const ProvidesList& providesList)
55 // find the best-matching provides
56 BPackageResolvable* bestProvides = NULL;
57 for (ProvidesList::const_iterator it = providesList.begin();
58 it != providesList.end(); ++it) {
59 BPackageResolvable* provides = *it;
60 if (!expression.Matches(*provides))
61 continue;
63 if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK
64 || (provides->Version().InitCheck() == B_OK
65 && provides->Version().Compare(bestProvides->Version()) > 0)) {
66 bestProvides = provides;
70 if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK)
71 return;
73 // Update the expression. Enforce the minimum found version, if the requires
74 // has no version requirement or also a minimum. Otherwise enforce the exact
75 // version found.
76 BPackageResolvableOperator newOperator = B_PACKAGE_RESOLVABLE_OP_EQUAL;
77 switch (expression.Operator()) {
78 case B_PACKAGE_RESOLVABLE_OP_LESS:
79 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
80 case B_PACKAGE_RESOLVABLE_OP_EQUAL:
81 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
82 break;
83 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
84 case B_PACKAGE_RESOLVABLE_OP_GREATER:
85 case B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT:
86 newOperator = B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL;
87 break;
90 expression.SetTo(expression.Name(), newOperator, bestProvides->Version());
94 int
95 main(int argc, const char* const* argv)
97 if (argc != 3)
98 print_usage_and_exit(true);
100 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
101 print_usage_and_exit(false);
103 const char* const packageInfoPath = argv[1];
104 const char* const repositoryCachePath = argv[2];
106 // read the repository cache
107 BRepositoryCache repositoryCache;
108 status_t error = repositoryCache.SetTo(repositoryCachePath);
109 if (error != B_OK) {
110 DIE(error, "failed to read repository cache file \"%s\"",
111 repositoryCachePath);
114 // create a map for all provides (name -> resolvable list)
115 typedef std::map<BString, ProvidesList> ProvidesMap;
117 ProvidesMap providesMap;
119 for (BRepositoryCache::Iterator it = repositoryCache.GetIterator();
120 const BPackageInfo* info = it.Next();) {
121 const BObjectList<BPackageResolvable>& provides = info->ProvidesList();
122 int32 count = provides.CountItems();
123 for (int32 i = 0; i < count; i++) {
124 BPackageResolvable* resolvable = provides.ItemAt(i);
125 ProvidesList& providesList = providesMap[resolvable->Name()];
126 providesList.push_back(resolvable);
130 // load the package info
131 BPackageInfo packageInfo;
132 error = packageInfo.ReadFromConfigFile(packageInfoPath);
133 if (error != B_OK)
134 DIE(error, "failed to read package info file \"%s\"", packageInfoPath);
136 // clone the package info's requires list
137 typedef std::list<BPackageResolvableExpression> RequiresList;
138 RequiresList requiresList;
139 int32 requiresCount = packageInfo.RequiresList().CountItems();
140 for (int32 i = 0; i < requiresCount; i++)
141 requiresList.push_back(*packageInfo.RequiresList().ItemAt(i));
143 // rebuild the requires list with updated versions
144 packageInfo.ClearRequiresList();
145 for (RequiresList::iterator it = requiresList.begin();
146 it != requiresList.end(); ++it) {
147 BPackageResolvableExpression expression = *it;
148 ProvidesMap::iterator foundIt = providesMap.find(expression.Name());
149 if (foundIt != providesMap.end())
150 update_requires_expression(expression, foundIt->second);
152 error = packageInfo.AddRequires(expression);
153 if (error != B_OK)
154 DIE(error, "failed to add requires item to package info");
157 // write updated package info
158 BString configString;
159 error = packageInfo.GetConfigString(configString);
160 if (error != B_OK)
161 DIE(error, "failed to get updated package info string");
163 FILE* file = fopen(packageInfoPath, "w");
164 if (file == NULL) {
165 DIE(errno, "failed to open package info file \"%s\" for writing",
166 packageInfoPath);
169 if (fwrite(configString.String(), configString.Length(), 1, file) != 1) {
170 DIE(errno, "failed to write updated package info file \"%s\"",
171 packageInfoPath);
174 fclose(file);
176 return 0;