1 /* 2 * Copyright (c) 2011-2013, Ingo Weinhold <ingo_weinhold@gmx.de> 3 * 4 * This program is licensed under the BSD license, read LICENSE.BSD 5 * for further information 6 */ 7 8 #include <package/PackageInfo.h> 9 #include <package/PackageInfoSet.h> 10 #include <package/PackageRoster.h> 11 #include <package/PackageVersion.h> 12 #include <package/RepositoryCache.h> 13 #include <package/RepositoryConfig.h> 14 15 #include "repo_haiku.h" 16 17 using namespace BPackageKit; 18 using namespace BPackageKit::BHPKG; 19 20 static void add_dependency(Repo *repo, Offset &dependencies, const char *name, 21 const char *version, int flags, const char* compatVersion = NULL) 22 { 23 Pool *pool = repo->pool; 24 25 Id dependency = pool_str2id(pool, name, 1); 26 27 if (version && version[0] != '\0') 28 { 29 Id versionId = pool_str2id(pool, version, 1); 30 31 if (compatVersion && compatVersion[0] != '\0') 32 { 33 versionId = pool_rel2id(pool, versionId, pool_str2id(pool, compatVersion, 1), 34 REL_COMPAT, 1); 35 } 36 37 dependency = pool_rel2id(pool, dependency, versionId, flags, 1); 38 } 39 40 dependencies = repo_addid_dep(repo, dependencies, dependency, 0); 41 } 42 43 static void add_dependency(Repo *repo, Offset &dependencies, const char *name, 44 const BPackageVersion &version, int flags) 45 { 46 add_dependency(repo, dependencies, name, version.ToString(), 47 flags); 48 } 49 50 static void add_resolvables(Repo *repo, Offset &dependencies, 51 const BObjectList<BPackageResolvable> &resolvables) 52 { 53 for (int32 i = 0; BPackageResolvable *resolvable = resolvables.ItemAt(i); i++) 54 { 55 add_dependency(repo, dependencies, resolvable->Name(), 56 resolvable->Version().ToString(), REL_EQ, 57 resolvable->CompatibleVersion().ToString()); 58 } 59 } 60 61 static void add_resolvable_expressions(Repo *repo, Offset &dependencies, 62 const BObjectList<BPackageResolvableExpression> &expressions) 63 { 64 for (int32 i = 0; 65 BPackageResolvableExpression *expression = expressions.ItemAt(i); i++) 66 { 67 // It is possible that no version is specified. In that case any version 68 // is acceptable. 69 if (expression->Version().InitCheck() != B_OK) 70 { 71 BPackageVersion version; 72 add_dependency(repo, dependencies, expression->Name(), NULL, 0); 73 continue; 74 } 75 76 int flags = 0; 77 switch (expression->Operator()) 78 { 79 case B_PACKAGE_RESOLVABLE_OP_LESS: 80 flags |= REL_LT; 81 break; 82 case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL: 83 flags |= REL_LT | REL_EQ; 84 break; 85 case B_PACKAGE_RESOLVABLE_OP_EQUAL: 86 flags |= REL_EQ; 87 break; 88 case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL: 89 break; 90 case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL: 91 flags |= REL_GT | REL_EQ; 92 break; 93 case B_PACKAGE_RESOLVABLE_OP_GREATER: 94 flags |= REL_GT; 95 break; 96 } 97 98 add_dependency(repo, dependencies, expression->Name(), 99 expression->Version(), flags); 100 } 101 } 102 103 static void add_replaces_list(Repo *repo, Offset &dependencies, 104 const BStringList &packageNames) 105 { 106 int32 count = packageNames.CountStrings(); 107 for (int32 i = 0; i < count; i++) 108 { 109 const BString &packageName = packageNames.StringAt(i); 110 add_dependency(repo, dependencies, packageName, BPackageVersion(), 0); 111 } 112 } 113 114 static Id add_package_info_to_repo(Repo *repo, Repodata *repoData, 115 const BPackageInfo &packageInfo) 116 { 117 Pool *pool = repo->pool; 118 119 Id solvableId = repo_add_solvable(repo); 120 Solvable *solvable = pool_id2solvable(pool, solvableId); 121 // Prepend "pkg:" to package name, so "provides" don't match unless explicitly 122 // specified this way. 123 BString name("pkg:"); 124 name << packageInfo.Name(); 125 solvable->name = pool_str2id(pool, name, 1); 126 if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY) 127 solvable->arch = ARCH_ANY; 128 else if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_SOURCE) 129 solvable->arch = ARCH_SRC; 130 else 131 solvable->arch = pool_str2id(pool, 132 BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1); 133 solvable->evr = pool_str2id(pool, packageInfo.Version().ToString(), 1); 134 solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1); 135 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY, 136 packageInfo.Summary()); 137 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION, 138 packageInfo.Description()); 139 repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER, 140 packageInfo.Packager()); 141 142 if (!packageInfo.Checksum().IsEmpty()) 143 repodata_set_checksum(repoData, solvable - pool->solvables, 144 SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum()); 145 146 solvable->provides = repo_addid_dep(repo, solvable->provides, 147 pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0); 148 149 add_resolvables(repo, solvable->provides, packageInfo.ProvidesList()); 150 add_resolvable_expressions(repo, solvable->requires, 151 packageInfo.RequiresList()); 152 add_resolvable_expressions(repo, solvable->supplements, 153 packageInfo.SupplementsList()); 154 add_resolvable_expressions(repo, solvable->conflicts, 155 packageInfo.ConflictsList()); 156 add_resolvable_expressions(repo, solvable->enhances, 157 packageInfo.FreshensList()); 158 add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList()); 159 // TODO: Check whether freshens and replaces does indeed work as intended 160 // here. 161 162 // TODO: copyrights, licenses, URLs, source URLs 163 164 return solvableId; 165 } 166 167 static void add_installed_packages(Repo *repo, Repodata *repoData, 168 BPackageInstallationLocation location) 169 { 170 BPackageRoster roster; 171 BPackageInfoSet packageInfos; 172 if (roster.GetActivePackages(location, packageInfos) == B_OK) 173 { 174 BRepositoryCache::Iterator it = packageInfos.GetIterator(); 175 while (const BPackageInfo *packageInfo = it.Next()) 176 add_package_info_to_repo(repo, repoData, *packageInfo); 177 } 178 } 179 180 int repo_add_haiku_installed_packages(Repo *repo, const char *rootdir, 181 int flags) 182 { 183 Repodata *repoData = repo_add_repodata(repo, flags); 184 185 add_installed_packages(repo, repoData, 186 B_PACKAGE_INSTALLATION_LOCATION_SYSTEM); 187 add_installed_packages(repo, repoData, B_PACKAGE_INSTALLATION_LOCATION_HOME); 188 189 if (!(flags & REPO_NO_INTERNALIZE)) 190 repodata_internalize(repoData); 191 192 return 0; 193 } 194 195 Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags) 196 { 197 BPackageInfo packageInfo; 198 if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK) 199 return 0; 200 201 return repo_add_haiku_package_info(repo, packageInfo, flags); 202 } 203 204 int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags) 205 { 206 BPackageRoster roster; 207 BRepositoryCache cache; 208 if (roster.GetRepositoryCache(repoName, &cache) != B_OK) 209 return 0; 210 211 Repodata *repoData = repo_add_repodata(repo, flags); 212 213 BRepositoryCache::Iterator it = cache.GetIterator(); 214 while (const BPackageInfo *packageInfo = it.Next()) 215 add_package_info_to_repo(repo, repoData, *packageInfo); 216 217 if (!(flags & REPO_NO_INTERNALIZE)) 218 repodata_internalize(repoData); 219 220 return 0; 221 } 222 223 Id repo_add_haiku_package_info(Repo *repo, 224 const BPackageKit::BPackageInfo &packageInfo, int flags) 225 { 226 if (packageInfo.InitCheck() != B_OK) 227 return 0; 228 229 Repodata *repoData = repo_add_repodata(repo, flags); 230 231 Id id = add_package_info_to_repo(repo, repoData, packageInfo); 232 233 if (!(flags & REPO_NO_INTERNALIZE)) 234 repodata_internalize(repoData); 235 236 return id; 237 } 238