static void process_one_alternative(const char *altgrname, const char *val) { xbps_dictionary_t d; xbps_array_t a; char *altfiles; bool alloc = false; if ((d = xbps_dictionary_get(pkg_propsd, "alternatives")) == NULL) { d = xbps_dictionary_create(); assert(d); alloc = true; } if ((a = xbps_dictionary_get(d, altgrname)) == NULL) { a = xbps_array_create(); assert(a); } altfiles = strchr(val, ':') + 1; assert(altfiles); xbps_array_add_cstring(a, altfiles); xbps_dictionary_set(d, altgrname, a); xbps_dictionary_set(pkg_propsd, "alternatives", d); if (alloc) { xbps_object_release(a); xbps_object_release(d); } }
ATF_TC_BODY(find_pkg_orphans_test, tc) { struct xbps_handle xh; xbps_array_t a, res; xbps_dictionary_t pkgd; xbps_string_t pstr; const char *pkgver, *tcsdir; unsigned int i; /* get test source dir */ tcsdir = atf_tc_get_config_var(tc, "srcdir"); memset(&xh, 0, sizeof(xh)); xbps_strlcpy(xh.rootdir, tcsdir, sizeof(xh.rootdir)); xbps_strlcpy(xh.metadir, tcsdir, sizeof(xh.metadir)); ATF_REQUIRE_EQ(xbps_init(&xh), 0); a = xbps_array_create(); xbps_array_add_cstring_nocopy(a, "xbps-git"); pstr = xbps_string_create(); res = xbps_find_pkg_orphans(&xh, a); for (i = 0; i < xbps_array_count(res); i++) { pkgd = xbps_array_get(res, i); xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); xbps_string_append_cstring(pstr, pkgver); xbps_string_append_cstring(pstr, "\n"); } ATF_REQUIRE_STREQ(xbps_string_cstring_nocopy(pstr), expected_output); }
static void process_array(const char *key, const char *val) { xbps_array_t array = NULL; char *args, *p = NULL, *saveptr = NULL; assert(key); if (val == NULL) return; array = xbps_array_create(); assert(array); if (strchr(val, ' ') == NULL) { xbps_array_add_cstring_nocopy(array, val); goto out; } args = strdup(val); assert(args); for ((p = strtok_r(args, " ", &saveptr)); p; (p = strtok_r(NULL, " ", &saveptr))) { xbps_array_add_cstring(array, p); } free(args); out: xbps_dictionary_set(pkg_propsd, key, array); xbps_object_release(array); }
static void generate_full_revdeps_tree(struct xbps_handle *xhp) { xbps_object_t obj; xbps_object_iterator_t iter; if (xhp->pkgdb_revdeps) return; xhp->pkgdb_revdeps = xbps_dictionary_create(); assert(xhp->pkgdb_revdeps); iter = xbps_dictionary_iterator(xhp->pkgdb); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { xbps_array_t rundeps; xbps_dictionary_t pkgd; const char *pkgver; pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj); rundeps = xbps_dictionary_get(pkgd, "run_depends"); if (!xbps_array_count(rundeps)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); for (unsigned int i = 0; i < xbps_array_count(rundeps); i++) { xbps_array_t pkg; const char *pkgdep, *vpkgname; char *curpkgname; bool alloc = false; xbps_array_get_cstring_nocopy(rundeps, i, &pkgdep); curpkgname = xbps_pkgpattern_name(pkgdep); if (curpkgname == NULL) curpkgname = xbps_pkg_name(pkgdep); assert(curpkgname); vpkgname = vpkg_user_conf(xhp, curpkgname); if (vpkgname == NULL) vpkgname = curpkgname; pkg = xbps_dictionary_get(xhp->pkgdb_revdeps, vpkgname); if (pkg == NULL) { alloc = true; pkg = xbps_array_create(); } if (!xbps_match_string_in_array(pkg, pkgver)) { xbps_array_add_cstring_nocopy(pkg, pkgver); xbps_dictionary_set(xhp->pkgdb_revdeps, vpkgname, pkg); } free(curpkgname); if (alloc) xbps_object_release(pkg); } } xbps_object_iterator_release(iter); }
static bool store_repo(struct xbps_handle *xhp, const char *repo) { if (xhp->repositories == NULL) xhp->repositories = xbps_array_create(); if (xbps_match_string_in_array(xhp->repositories, repo)) return false; xbps_array_add_cstring(xhp->repositories, repo); return true; }
static void shlib_register(xbps_dictionary_t d, const char *shlib, const char *pkgver) { xbps_array_t array; bool alloc = false; if ((array = xbps_dictionary_get(d, shlib)) == NULL) { alloc = true; array = xbps_array_create(); xbps_dictionary_set(d, shlib, array); } if (!xbps_match_string_in_array(array, pkgver)) xbps_array_add_cstring_nocopy(array, pkgver); if (alloc) xbps_object_release(array); }
static void store_preserved_file(struct xbps_handle *xhp, const char *file) { glob_t globbuf; char *p = NULL, *rfile = NULL; size_t len; int rv = 0; if (xhp->preserved_files == NULL) { xhp->preserved_files = xbps_array_create(); assert(xhp->preserved_files); } rfile = xbps_xasprintf("%s%s", xhp->rootdir, file); rv = glob(rfile, 0, NULL, &globbuf); if (rv == GLOB_NOMATCH) { if (xbps_match_string_in_array(xhp->preserved_files, file)) goto out; xbps_array_add_cstring(xhp->preserved_files, file); xbps_dbg_printf(xhp, "Added preserved file: %s\n", file); goto out; } else if (rv != 0) { goto out; } for (size_t i = 0; i < globbuf.gl_pathc; i++) { if (xbps_match_string_in_array(xhp->preserved_files, globbuf.gl_pathv[i])) continue; len = strlen(globbuf.gl_pathv[i]) - strlen(xhp->rootdir) + 1; p = malloc(len); assert(p); strlcpy(p, globbuf.gl_pathv[i] + strlen(xhp->rootdir), len); xbps_array_add_cstring(xhp->preserved_files, p); xbps_dbg_printf(xhp, "Added preserved file: %s (expanded from %s)\n", p, file); free(p); } out: globfree(&globbuf); free(rfile); }
bool xbps_repo_store(struct xbps_handle *xhp, const char *repo) { char *url = NULL; assert(xhp); assert(repo); if (xhp->repositories == NULL) { xhp->repositories = xbps_array_create(); assert(xhp->repositories); } /* * If it's a local repo and path is relative, make it absolute. */ if (!xbps_repository_is_remote(repo)) { if (repo[0] != '/' && repo[0] != '\0') { if ((url = realpath(repo, NULL)) == NULL) xbps_dbg_printf(xhp, "[repo] %s: realpath %s\n", __func__, repo); } } if (xbps_match_string_in_array(xhp->repositories, url ? url : repo)) { xbps_dbg_printf(xhp, "[repo] `%s' already stored\n", url ? url : repo); if (url) free(url); return false; } if (xbps_array_add_cstring(xhp->repositories, url ? url : repo)) { xbps_dbg_printf(xhp, "[repo] `%s' stored successfully\n", url ? url : repo); if (url) free(url); return true; } if (url) free(url); return false; }
static xbps_array_t merge_filelist(xbps_dictionary_t d) { xbps_array_t a, result; xbps_dictionary_t filed; unsigned int i; result = xbps_array_create(); assert(result); if ((a = xbps_dictionary_get(d, "files"))) { for (i = 0; i < xbps_array_count(a); i++) { filed = xbps_array_get(a, i); xbps_array_add(result, filed); } } if ((a = xbps_dictionary_get(d, "links"))) { for (i = 0; i < xbps_array_count(a); i++) { filed = xbps_array_get(a, i); xbps_array_add(result, filed); } } if ((a = xbps_dictionary_get(d, "conf_files"))) { for (i = 0; i < xbps_array_count(a); i++) { filed = xbps_array_get(a, i); xbps_array_add(result, filed); } } if ((a = xbps_dictionary_get(d, "dirs"))) { for (i = 0; i < xbps_array_count(a); i++) { filed = xbps_array_get(a, i); xbps_array_add(result, filed); } } return result; }
int xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkgd) { xbps_array_t allkeys; xbps_dictionary_t alternatives, pkg_alternatives; const char *pkgver; char *pkgname; int rv = 0; assert(xhp); if (xhp->pkgdb == NULL) return EINVAL; pkg_alternatives = xbps_dictionary_get(pkgd, "alternatives"); if (!xbps_dictionary_count(pkg_alternatives)) return 0; alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_"); if (alternatives == NULL) { alternatives = xbps_dictionary_create(); xbps_dictionary_set(xhp->pkgdb, "_XBPS_ALTERNATIVES_", alternatives); xbps_object_release(alternatives); } alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_"); assert(alternatives); xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); pkgname = xbps_pkg_name(pkgver); if (pkgname == NULL) return EINVAL; allkeys = xbps_dictionary_all_keys(pkg_alternatives); for (unsigned int i = 0; i < xbps_array_count(allkeys); i++) { xbps_array_t array; xbps_object_t keysym; const char *keyname; bool alloc = false; keysym = xbps_array_get(allkeys, i); keyname = xbps_dictionary_keysym_cstring_nocopy(keysym); array = xbps_dictionary_get(alternatives, keyname); if (array == NULL) { alloc = true; array = xbps_array_create(); } else { /* already registered */ if (xbps_match_string_in_array(array, pkgname)) continue; } xbps_array_add_cstring(array, pkgname); xbps_dictionary_set(alternatives, keyname, array); xbps_set_cb_state(xhp, XBPS_STATE_ALTGROUP_ADDED, 0, NULL, "%s: registered '%s' alternatives group", pkgver, keyname); if (alloc) { /* apply alternatives for this group */ rv = create_symlinks(xhp, xbps_dictionary_get(pkg_alternatives, keyname), keyname); xbps_object_release(array); if (rv != 0) break; } } xbps_object_release(allkeys); free(pkgname); return rv; }
static xbps_array_t revdeps_match(struct xbps_repo *repo, xbps_dictionary_t tpkgd, const char *str) { xbps_dictionary_t pkgd; xbps_array_t revdeps = NULL, pkgdeps, provides; xbps_object_iterator_t iter; xbps_object_t obj; const char *pkgver, *tpkgver, *arch, *vpkg; iter = xbps_dictionary_iterator(repo->idx); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { pkgd = xbps_dictionary_get_keysym(repo->idx, obj); if (xbps_dictionary_equals(pkgd, tpkgd)) continue; pkgdeps = xbps_dictionary_get(pkgd, "run_depends"); if (!xbps_array_count(pkgdeps)) continue; /* * Try to match passed in string. */ if (str) { if (!xbps_match_pkgdep_in_array(pkgdeps, str)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); if (!xbps_pkg_arch_match(repo->xhp, arch, NULL)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &tpkgver); /* match */ if (revdeps == NULL) revdeps = xbps_array_create(); if (!xbps_match_string_in_array(revdeps, tpkgver)) xbps_array_add_cstring_nocopy(revdeps, tpkgver); continue; } /* * Try to match any virtual package. */ provides = xbps_dictionary_get(tpkgd, "provides"); for (unsigned int i = 0; i < xbps_array_count(provides); i++) { xbps_array_get_cstring_nocopy(provides, i, &vpkg); if (!xbps_match_pkgdep_in_array(pkgdeps, vpkg)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); if (!xbps_pkg_arch_match(repo->xhp, arch, NULL)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &tpkgver); /* match */ if (revdeps == NULL) revdeps = xbps_array_create(); if (!xbps_match_string_in_array(revdeps, tpkgver)) xbps_array_add_cstring_nocopy(revdeps, tpkgver); } /* * Try to match by pkgver. */ xbps_dictionary_get_cstring_nocopy(tpkgd, "pkgver", &pkgver); if (!xbps_match_pkgdep_in_array(pkgdeps, pkgver)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); if (!xbps_pkg_arch_match(repo->xhp, arch, NULL)) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &tpkgver); /* match */ if (revdeps == NULL) revdeps = xbps_array_create(); if (!xbps_match_string_in_array(revdeps, tpkgver)) xbps_array_add_cstring_nocopy(revdeps, tpkgver); } xbps_object_iterator_release(iter); return revdeps; }
xbps_array_t xbps_find_pkg_obsoletes(struct xbps_handle *xhp, xbps_dictionary_t instd, xbps_dictionary_t newd) { xbps_array_t instfiles, newfiles, obsoletes; xbps_object_t obj, obj2; xbps_string_t oldstr, newstr; unsigned int i, x; const char *oldhash; char *file; int rv = 0; bool found; assert(xbps_object_type(instd) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(newd) == XBPS_TYPE_DICTIONARY); obsoletes = xbps_array_create(); assert(obsoletes); instfiles = merge_filelist(instd); if (xbps_array_count(instfiles) == 0) { /* nothing to check if current pkg does not own any file */ xbps_object_release(instfiles); return obsoletes; } newfiles = merge_filelist(newd); /* * Iterate over files list from installed package. */ for (i = 0; i < xbps_array_count(instfiles); i++) { found = false; obj = xbps_array_get(instfiles, i); if (xbps_object_type(obj) != XBPS_TYPE_DICTIONARY) { /* ignore unexistent files */ continue; } oldstr = xbps_dictionary_get(obj, "file"); if (oldstr == NULL) continue; file = xbps_xasprintf(".%s", xbps_string_cstring_nocopy(oldstr)); oldhash = NULL; xbps_dictionary_get_cstring_nocopy(obj, "sha256", &oldhash); if (oldhash) { rv = xbps_file_hash_check(file, oldhash); if (rv == ENOENT || rv == ERANGE) { /* * Skip unexistent and files that do not * match the hash. */ free(file); continue; } } /* * Check if current file is available in new pkg filelist. */ for (x = 0; x < xbps_array_count(newfiles); x++) { obj2 = xbps_array_get(newfiles, x); newstr = xbps_dictionary_get(obj2, "file"); assert(newstr); /* * Skip files with same path. */ if (xbps_string_equals(oldstr, newstr)) { found = true; break; } } if (found) { free(file); continue; } /* * Do not add required symlinks for the * system transition to /usr. */ if ((strcmp(file, "./bin") == 0) || (strcmp(file, "./bin/") == 0) || (strcmp(file, "./sbin") == 0) || (strcmp(file, "./sbin/") == 0) || (strcmp(file, "./lib") == 0) || (strcmp(file, "./lib/") == 0) || (strcmp(file, "./lib64/") == 0) || (strcmp(file, "./lib64") == 0)) { free(file); continue; } /* * Obsolete found, add onto the array. */ xbps_dbg_printf(xhp, "found obsolete: %s\n", file); xbps_array_add_cstring(obsoletes, file); free(file); } xbps_object_release(instfiles); xbps_object_release(newfiles); return obsoletes; }
static bool repodata_commit(struct xbps_handle *xhp, const char *repodir, xbps_dictionary_t idx, xbps_dictionary_t meta, xbps_dictionary_t stage) { const char *pkgname; xbps_object_iterator_t iter; xbps_object_t keysym; int rv; if(xbps_dictionary_count(stage) == 0) { // Nothing to do. return true; } /* * Find old shlibs-provides */ xbps_dictionary_t oldshlibs = xbps_dictionary_create(); xbps_dictionary_t usedshlibs = xbps_dictionary_create(); iter = xbps_dictionary_iterator(stage); while ((keysym = xbps_object_iterator_next(iter))) { pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym); xbps_dictionary_t oldpkg = xbps_dictionary_get(idx, pkgname); xbps_array_t pkgshlibs = xbps_dictionary_get(oldpkg, "shlib-provides"); for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) { const char *shlib = NULL; xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib); xbps_dictionary_set_cstring(oldshlibs, shlib, pkgname); } } xbps_object_iterator_release(iter); /* * throw away all unused shlibs */ iter = xbps_dictionary_iterator(idx); while ((keysym = xbps_object_iterator_next(iter))) { pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym); xbps_dictionary_t pkg = xbps_dictionary_get(stage, pkgname); if(!pkg) pkg = xbps_dictionary_get_keysym(idx, keysym); xbps_array_t pkgshlibs = xbps_dictionary_get(pkg, "shlib-requires"); for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) { const char *shlib = NULL, *user = NULL; xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib); xbps_dictionary_get_cstring_nocopy(pkg, shlib, &user); if(!user) continue; xbps_array_t users = xbps_dictionary_get(usedshlibs, shlib); if(!users) { users = xbps_array_create(); xbps_dictionary_set(usedshlibs, shlib, users); } xbps_array_add_cstring(users, user); } } xbps_object_iterator_release(iter); /* * purge all packages that are fullfilled by the stage */ iter = xbps_dictionary_iterator(stage); while ((keysym = xbps_object_iterator_next(iter))) { pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym); xbps_dictionary_t newpkg = xbps_dictionary_get(idx, pkgname); xbps_array_t pkgshlibs = xbps_dictionary_get(newpkg, "shlib-provides"); for(unsigned int i = 0; i < xbps_array_count(pkgshlibs); i++) { const char *shlib; xbps_array_get_cstring_nocopy(pkgshlibs, i, &shlib); xbps_dictionary_remove(usedshlibs, shlib); } } xbps_object_iterator_release(iter); if(xbps_dictionary_count(usedshlibs) != 0) { puts("Unfullfilled shlibs:"); iter = xbps_dictionary_iterator(usedshlibs); while ((keysym = xbps_object_iterator_next(iter))) { const char *shlib = xbps_dictionary_keysym_cstring_nocopy(keysym), *provider = NULL; xbps_array_t users = xbps_dictionary_get(usedshlibs, shlib); xbps_dictionary_get_cstring_nocopy(usedshlibs, shlib, &provider); printf(" %s (provided by: %s; used by: ", shlib, provider); const char *pre = ""; for(unsigned int i = 0; i < xbps_array_count(users); i++) { const char *user; xbps_array_get_cstring_nocopy(users, i, &user); xbps_dictionary_remove(usedshlibs, shlib); printf("%s%s",pre, user); pre = ", "; } puts(")"); } puts("Changes are commit to stage."); xbps_object_iterator_release(iter); // TODO FLUSH STAGE rv = true; } else { iter = xbps_dictionary_iterator(stage); while ((keysym = xbps_object_iterator_next(iter))) { pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym); xbps_dictionary_t newpkg = xbps_dictionary_get_keysym(stage, keysym); xbps_dictionary_set(idx, pkgname, newpkg); } xbps_object_iterator_release(iter); rv = repodata_flush(xhp, repodir, idx, meta); } xbps_object_release(usedshlibs); xbps_object_release(oldshlibs); return rv; }
xbps_array_t xbps_find_pkg_obsoletes(struct xbps_handle *xhp, xbps_dictionary_t instd, xbps_dictionary_t newd) { xbps_array_t instfiles, newfiles, obsoletes; /* These are symlinks in Void and must not be removed */ const char *basesymlinks[] = { "./bin", "./sbin", "./lib", "./lib32", "./lib64", "./usr/lib32", "./usr/lib64", "./var/run", }; int rv = 0; assert(xbps_object_type(instd) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(newd) == XBPS_TYPE_DICTIONARY); obsoletes = xbps_array_create(); assert(obsoletes); instfiles = merge_filelist(instd); if (xbps_array_count(instfiles) == 0) { /* nothing to check if current pkg does not own any file */ xbps_object_release(instfiles); return obsoletes; } newfiles = merge_filelist(newd); /* * Iterate over files list from installed package. */ for (unsigned int i = 0; i < xbps_array_count(instfiles); i++) { xbps_object_t obj, obj2; xbps_string_t oldstr, newstr; struct stat st; uint64_t mtime = 0; const char *oldhash; char file[PATH_MAX]; bool found = false; obj = xbps_array_get(instfiles, i); if (xbps_object_type(obj) != XBPS_TYPE_DICTIONARY) { /* ignore unexistent files */ continue; } oldstr = xbps_dictionary_get(obj, "file"); if (oldstr == NULL) continue; snprintf(file, sizeof(file), ".%s", xbps_string_cstring_nocopy(oldstr)); if (xbps_dictionary_get_cstring_nocopy(obj, "sha256", &oldhash)) { rv = xbps_file_hash_check(file, oldhash); if (rv == ENOENT || rv == ERANGE) { /* Skip unexistent and files that do not * match the hash. */ continue; } } /* * Check if current file is available in new pkg filelist. */ for (unsigned int x = 0; x < xbps_array_count(newfiles); x++) { obj2 = xbps_array_get(newfiles, x); newstr = xbps_dictionary_get(obj2, "file"); assert(newstr); /* * Skip files with same path. */ if (xbps_string_equals(oldstr, newstr)) { found = true; break; } } if (found) { continue; } /* * Make sure to not remove any symlink of root directory. */ for (uint8_t x = 0; x < __arraycount(basesymlinks); x++) { if (strcmp(file, basesymlinks[x]) == 0) { found = true; xbps_dbg_printf(xhp, "[obsoletes] ignoring " "%s removal\n", file); break; } } if (found) { continue; } /* * Finally check if file mtime on disk matched what * the installed pkg has stored. */ if (xbps_dictionary_get_uint64(obj, "mtime", &mtime)) { if (lstat(file, &st) == -1) { xbps_dbg_printf(xhp, "[obsoletes] lstat failed " "for %s: %s\n", file, strerror(errno)); continue; } if (mtime != (uint64_t)st.st_mtime) continue; xbps_dbg_printf(xhp, "[obsoletes] %s: matched mtime, adding obsolete.\n", file); } /* * Obsolete found, add onto the array. */ xbps_dbg_printf(xhp, "found obsolete: %s\n", file); xbps_array_add_cstring(obsoletes, file); } xbps_object_release(instfiles); xbps_object_release(newfiles); return obsoletes; }
int xbps_transaction_prepare(struct xbps_handle *xhp) { xbps_array_t array, pkgs, edges; unsigned int i, cnt; int rv = 0; if (xhp->transd == NULL) return ENXIO; /* * Collect dependencies for pkgs in transaction. */ if ((edges = xbps_array_create()) == NULL) return ENOMEM; /* * The edges are also appended after its dependencies have been * collected; the edges at the original array are removed later. */ pkgs = xbps_dictionary_get(xhp->transd, "packages"); assert(xbps_object_type(pkgs) == XBPS_TYPE_ARRAY); cnt = xbps_array_count(pkgs); for (i = 0; i < cnt; i++) { xbps_dictionary_t pkgd; xbps_string_t str; const char *tract = NULL; pkgd = xbps_array_get(pkgs, i); str = xbps_dictionary_get(pkgd, "pkgver"); xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &tract); if ((strcmp(tract, "remove") == 0) || strcmp(tract, "hold") == 0) continue; assert(xbps_object_type(str) == XBPS_TYPE_STRING); if (!xbps_array_add(edges, str)) return ENOMEM; if ((rv = xbps_repository_find_deps(xhp, pkgs, pkgd)) != 0) return rv; if (!xbps_array_add(pkgs, pkgd)) return ENOMEM; } /* ... remove dup edges at head */ for (i = 0; i < xbps_array_count(edges); i++) { const char *pkgver; xbps_array_get_cstring_nocopy(edges, i, &pkgver); xbps_remove_pkg_from_array_by_pkgver(pkgs, pkgver); } xbps_object_release(edges); /* * Check for packages to be replaced. */ if ((rv = xbps_transaction_package_replace(xhp, pkgs)) != 0) { xbps_object_release(xhp->transd); xhp->transd = NULL; return rv; } /* * If there are missing deps or revdeps bail out. */ xbps_transaction_revdeps(xhp, pkgs); array = xbps_dictionary_get(xhp->transd, "missing_deps"); if (xbps_array_count(array)) { if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) { xbps_dbg_printf(xhp, "[trans] continuing with broken reverse dependencies!"); } else { return ENODEV; } } /* * If there are package conflicts bail out. */ xbps_transaction_conflicts(xhp, pkgs); array = xbps_dictionary_get(xhp->transd, "conflicts"); if (xbps_array_count(array)) return EAGAIN; /* * Check for unresolved shared libraries. */ if (xbps_transaction_shlibs(xhp, pkgs, xbps_dictionary_get(xhp->transd, "missing_shlibs"))) { if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) { xbps_dbg_printf(xhp, "[trans] continuing with unresolved shared libraries!"); } else { return ENOEXEC; } } /* * Add transaction stats for total download/installed size, * number of packages to be installed, updated, configured * and removed to the transaction dictionary. */ if ((rv = compute_transaction_stats(xhp)) != 0) { return rv; } /* * Remove now unneeded objects. */ xbps_dictionary_remove(xhp->transd, "missing_shlibs"); xbps_dictionary_remove(xhp->transd, "missing_deps"); xbps_dictionary_remove(xhp->transd, "conflicts"); xbps_dictionary_make_immutable(xhp->transd); return 0; }
int HIDDEN xbps_transaction_init(struct xbps_handle *xhp) { xbps_array_t array; if (xhp->transd != NULL) return 0; if ((xhp->transd = xbps_dictionary_create()) == NULL) return ENOMEM; if ((array = xbps_array_create()) == NULL) { xbps_object_release(xhp->transd); xhp->transd = NULL; return ENOMEM; } if (!xbps_dictionary_set(xhp->transd, "packages", array)) { xbps_object_release(xhp->transd); xhp->transd = NULL; return EINVAL; } xbps_object_release(array); if ((array = xbps_array_create()) == NULL) { xbps_object_release(xhp->transd); xhp->transd = NULL; return ENOMEM; } if (!xbps_dictionary_set(xhp->transd, "missing_deps", array)) { xbps_object_release(xhp->transd); xhp->transd = NULL; return EINVAL; } xbps_object_release(array); if ((array = xbps_array_create()) == NULL) { xbps_object_release(xhp->transd); xhp->transd = NULL; return ENOMEM; } if (!xbps_dictionary_set(xhp->transd, "missing_shlibs", array)) { xbps_object_release(xhp->transd); xhp->transd = NULL; return EINVAL; } xbps_object_release(array); if ((array = xbps_array_create()) == NULL) { xbps_object_release(xhp->transd); xhp->transd = NULL; return ENOMEM; } if (!xbps_dictionary_set(xhp->transd, "conflicts", array)) { xbps_object_release(xhp->transd); xhp->transd = NULL; return EINVAL; } xbps_object_release(array); return 0; }