2 * Copyright 2013, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
16 #include <package/RepositoryCache.h>
17 #include <package/manager/Exceptions.h>
18 #include <package/manager/RepositoryBuilder.h>
19 #include <package/solver/Solver.h>
20 #include <package/solver/SolverPackageSpecifier.h>
21 #include <package/solver/SolverPackageSpecifierList.h>
22 #include <package/solver/SolverProblem.h>
23 #include <package/solver/SolverProblemSolution.h>
24 #include <package/solver/SolverRepository.h>
25 #include <package/solver/SolverResult.h>
28 using namespace BPackageKit
;
29 using namespace BPackageKit::BManager::BPrivate
;
32 static const char* sProgramName
= "get_package_dependencies";
35 #define DIE(result, msg...) \
37 fprintf(stderr, "*** " msg); \
38 fprintf(stderr, " : %s\n", strerror(result)); \
44 print_usage_and_exit(bool error
)
46 fprintf(error
? stderr
: stdout
,
47 "Usage: %s <repository> ... -- <package> ...\n"
48 "Resolves the dependencies of the given packages using the given\n"
49 "repositories and prints the URLs of the packages that are also\n"
50 "needed to satisfy all requirements. Fails, if there are conflicts\n"
51 "or some requirements cannot be satisfied.\n",
58 main(int argc
, const char* const* argv
)
61 print_usage_and_exit(true);
63 if (strcmp(argv
[1], "-h") == 0 || strcmp(argv
[1], "--help") == 0)
64 print_usage_and_exit(false);
66 // get lists of repositories and packages
68 const char* const* repositories
= argv
+ argIndex
;
69 while (argIndex
< argc
&& strcmp(argv
[argIndex
], "--") != 0)
71 int repositoryCount
= argv
+ argIndex
- repositories
;
73 if (repositoryCount
== 0 || argIndex
== argc
)
74 print_usage_and_exit(true);
76 const char* const* packages
= argv
+ argIndex
+ 1;
77 int packageCount
= argv
+ argc
- packages
;
81 status_t error
= BSolver::Create(solver
);
83 DIE(error
, "failed to create solver");
85 // add the "installed" repository with the given packages
86 BSolverRepository installedRepository
;
88 BRepositoryBuilder
installedRepositoryBuilder(installedRepository
, "installed");
89 for (int i
= 0; i
< packageCount
; i
++)
90 installedRepositoryBuilder
.AddPackage(packages
[i
]);
91 installedRepositoryBuilder
.AddToSolver(solver
, true);
92 } catch (BFatalErrorException e
) {
93 DIE(e
.Error(), "%s %s", e
.Message().String(), e
.Details().String());
96 // add external repositories
97 std::map
<BSolverRepository
*, BRepositoryInfo
> repositoryInfos
;
98 for (int i
= 0; i
< repositoryCount
; i
++) {
99 BSolverRepository
* repository
= new BSolverRepository
;
100 BRepositoryCache cache
;
101 error
= cache
.SetTo(repositories
[i
]);
103 DIE(error
, "failed to read repository file '%s'", repositories
[i
]);
104 BRepositoryBuilder(*repository
, cache
)
105 .AddToSolver(solver
, false);
106 repositoryInfos
[repository
] = cache
.Info();
110 error
= solver
->VerifyInstallation();
112 DIE(error
, "failed to compute packages to install");
114 // print problems (and fail), if any
115 if (solver
->HasProblems()) {
116 fprintf(stderr
, "Encountered problems:\n");
118 int32 problemCount
= solver
->CountProblems();
119 for (int32 i
= 0; i
< problemCount
; i
++) {
120 // print problem and possible solutions
121 BSolverProblem
* problem
= solver
->ProblemAt(i
);
122 fprintf(stderr
, "problem %" B_PRId32
": %s\n", i
+ 1,
123 problem
->ToString().String());
125 int32 solutionCount
= problem
->CountSolutions();
126 for (int32 k
= 0; k
< solutionCount
; k
++) {
127 const BSolverProblemSolution
* solution
= problem
->SolutionAt(k
);
128 fprintf(stderr
, " solution %" B_PRId32
":\n", k
+ 1);
129 int32 elementCount
= solution
->CountElements();
130 for (int32 l
= 0; l
< elementCount
; l
++) {
131 const BSolverProblemSolutionElement
* element
132 = solution
->ElementAt(l
);
133 fprintf(stderr
, " - %s\n", element
->ToString().String());
141 // print URL of packages that additionally need to be installed
142 BSolverResult result
;
143 error
= solver
->GetResult(result
);
145 DIE(error
, "failed to compute packages to install");
147 bool duplicatePackage
= false;
148 for (int32 i
= 0; const BSolverResultElement
* element
= result
.ElementAt(i
);
150 BSolverPackage
* package
= element
->Package();
152 switch (element
->Type()) {
153 case BSolverResultElement::B_TYPE_INSTALL
:
154 if (package
->Repository() != &installedRepository
) {
155 const BRepositoryInfo
& info
156 = repositoryInfos
[package
->Repository()];
157 BString url
= info
.OriginalBaseURL();
158 url
<< "/packages/" << package
->Info().CanonicalFileName();
159 printf("%s\n", url
.String());
163 case BSolverResultElement::B_TYPE_UNINSTALL
:
164 fprintf(stderr
, "Error: would need to uninstall package %s\n",
165 package
->VersionedName().String());
166 duplicatePackage
= true;
171 return duplicatePackage
? 1 : 0;