/* Resolve dependencies for a given package * @param curl curl handle * @param hashdb hash database * @param curpkg current package we are resolving * @param dep_list pointer to list to store resulting dependencies * @param resolve_lvl level of dep resolution. RESOLVE_THOROUGH forces * downloading of AUR PKGBUILDs * * returns -1 on error, 0 on success */ static int crawl_resolve(CURL *curl, struct pw_hashdb *hashdb, struct pkgpair *curpkg, alpm_list_t **dep_list, int resolve_lvl) { alpm_list_t *i, *depmod_list, *deps = NULL; struct pkgpair *pkgpair; struct pkgpair tmppkg; void *pkg_provides; void *memlist_ptr; const char *cache_result; const char *depname, *final_pkgname; char cwd[PATH_MAX]; char buf[PATH_MAX]; /* Normalize package before doing anything else */ final_pkgname = normalize_package(curl, hashdb, curpkg->pkgname, resolve_lvl); if (!final_pkgname) { return -1; } enum pkgfrom_t *from = hashmap_search(hashdb->pkg_from, (void *) final_pkgname); if (!from) { die("Failed to find out where package \"%s\" is from!\n", final_pkgname); } switch (*from) { case PKG_FROM_LOCAL: tmppkg.pkgname = final_pkgname; pkgpair = hash_search(hashdb->local, &tmppkg); goto get_deps; case PKG_FROM_SYNC: tmppkg.pkgname = final_pkgname; pkgpair = hash_search(hashdb->sync, &tmppkg); goto get_deps; default: goto aur_deps; } aur_uptodate: tmppkg.pkgname = final_pkgname; tmppkg.pkg = NULL; pkgpair = hash_search(hashdb->aur, &tmppkg); get_deps: if (!pkgpair) { /* Shouldn't happen */ die("Unable to find package \"%s\" in local/sync db!", final_pkgname); } depmod_list = alpm_pkg_get_depends(pkgpair->pkg); for (i = depmod_list; i; i = i->next) { char *s = alpm_dep_compute_string(i->data); strncpy(buf, s, sizeof(buf)); free(s); chompversion(buf); depname = normalize_package(curl, hashdb, buf, resolve_lvl); /* Possibility of normalize_package fail due to AUR download failing */ if (!depname) { alpm_list_free(deps); return -1; } deps = alpm_list_add(deps, (void *) depname); } if (dep_list) { *dep_list = deps; } else { alpm_list_free(deps); } return 0; aur_deps: tmppkg.pkgname = final_pkgname; tmppkg.pkg = NULL; /* For installed AUR packages which are up to date */ if (resolve_lvl != RESOLVE_THOROUGH) { if (hash_search(hashdb->aur, &tmppkg) && !hash_search(hashdb->aur_outdated, (void *) final_pkgname)) { /* NOTE: top goto ! */ goto aur_uptodate; } } /* RESOLVE_THOROUGH / out to date AUR package. * Download pkgbuild and extract deps */ if (!getcwd(cwd, PATH_MAX)) { return error(PW_ERR_GETCWD); } if (chdir(final_pkgname)) { return error(PW_ERR_CHDIR); } deps = grab_dependencies("PKGBUILD"); if (chdir(cwd)) { alpm_list_free(deps); return error(PW_ERR_RESTORECWD); } if (dep_list) { const char *normdep; alpm_list_t *new_deps = NULL; /* Transfer control to memlist and normalize packages */ for (i = deps; i; i = i->next) { memlist_ptr = memlist_add(hashdb->strpool, &i->data); normdep = normalize_package(curl, hashdb, memlist_ptr, resolve_lvl); new_deps = alpm_list_add(new_deps, (void *) normdep); } *dep_list = new_deps; } alpm_list_free(deps); return 0; }
alpm_list_t *resolve_dependencies(struct pw_hashdb *hashdb, alpm_list_t *packages) { alpm_list_t *i, *k, *m, *q; alpm_list_t *deps, *newdeps; pmpkg_t *pkg; struct pkgpair pkgpair; struct pkgpair *pkgpair_ptr; char pkgbuild[PATH_MAX]; struct stat st; newdeps = NULL; for (i = packages; i; i = i->next) { snprintf(pkgbuild, PATH_MAX, "%s/PKGBUILD", i->data); /* Grab the list of new dependencies from PKGBUILD */ deps = grab_dependencies(pkgbuild); if (!deps) { continue; } if (config->verbose) { printf("\nResolving dependencies for %s\n", i->data); } for (k = deps; k; k = k->next) { pkgpair.pkgname = k->data; /* Check against newdeps */ if (alpm_list_find_str(newdeps, k->data)) { continue; } /* Check against localdb */ if (hash_search(hashdb->local, &pkgpair)) { if (config->verbose) { printf("%s%s - Already installed\n", TAB, k->data); } continue; } /* Check against sync dbs */ pkgpair_ptr = hash_search(hashdb->sync, &pkgpair); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s can be found in %s repo\n", TAB, k->data, alpm_db_get_name(alpm_pkg_get_db(pkgpair_ptr->pkg))); } continue; } /* Check against provides */ pkgpair_ptr = hashbst_tree_search(hashdb->local_provides, k->data, hashdb->local, provides_search); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s is provided by %s\n", TAB, k->data, pkgpair_ptr->pkgname); } continue; } pkgpair_ptr = hashbst_tree_search(hashdb->sync_provides, k->data, hashdb->sync, provides_search); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s is provided by %s\n", TAB, k->data, pkgpair_ptr->pkgname); } continue; } /* Check the directory for pkg/PKGBUILD */ snprintf(pkgbuild, PATH_MAX, "%s/PKGBUILD", k->data); if (!stat(pkgbuild, &st)) { if (config->verbose) { printf("%s%s has been downloaded\n", TAB, k->data); } continue; } /* Add to newdeps */ newdeps = alpm_list_add(newdeps, strdup(k->data)); if (config->verbose) { printf("%s%s will be downloaded from the AUR\n", TAB, k->data); } } /* Free deps */ FREELIST(deps); } return newdeps; }