/* Generates the list of packages we are going to install from the AUR, in * topological order. * * @param hashdb hash database * @param graph graph of package strings * @param topost stack containing topological order of packages */ static alpm_list_t *topo_get_targets(struct pw_hashdb *hashdb, struct graph *graph, struct stack *topost) { int curVertex, cnt = 0; const char *pkgname; enum pkgfrom_t *from = NULL; struct pkgpair pkgpair; alpm_list_t *final_targets = NULL; pw_printf(PW_LOG_VDEBUG, "\n%sDependency graph:\n%s", color.bold, color.nocolor); while (!stack_empty(topost)) { stack_pop(topost, &curVertex); pkgname = graph_get_vertex_data(graph, curVertex); from = hashmap_search(hashdb->pkg_from, (void *) pkgname); if (!from) { alpm_list_free(final_targets); return NULL; } if (cnt++) { pw_printf(PW_LOG_VDEBUG, " -> "); } switch (*from) { case PKG_FROM_LOCAL: pw_printf(PW_LOG_VDEBUG, "%s%s (installed)%s", color.bgreen, pkgname, color.nocolor); break; case PKG_FROM_SYNC: pw_printf(PW_LOG_VDEBUG, "%s%s (found in sync)%s", color.bblue, pkgname, color.nocolor); break; case PKG_FROM_AUR: /* Magic happens here */ if (hash_search(hashdb->aur_outdated, (void *) pkgname)) { pw_printf(PW_LOG_VDEBUG, "%s%s (AUR target)%s", color.bred, pkgname, color.nocolor); final_targets = alpm_list_add(final_targets, (void *) pkgname); } else { pkgpair.pkgname = pkgname; if (hash_search(hashdb->aur, &pkgpair)) { pw_printf(PW_LOG_VDEBUG, "%s%s (installed AUR)%s", color.bblue, pkgname, color.nocolor); } else { /* New AUR package */ pw_printf(PW_LOG_VDEBUG, "%s%s (AUR dep)%s", color.bmag, pkgname, color.nocolor); final_targets = alpm_list_add(final_targets, (void *) pkgname); } } break; } } pw_printf(PW_LOG_VDEBUG, "\n"); print_immediate_deps(hashdb); return final_targets; }
var_p_t hashmap_put(var_p_t map, const char *key, int length) { Node *node = hashmap_search(map, key, length); if (node->key == NULL) { node->key = v_new(); node->value = v_new(); v_setstrn(node->key, key, length); map->v.m.count++; } return node->value; }
/* Prints immediate dependencies */ static void print_immediate_deps(struct pw_hashdb *hashdb) { alpm_list_t *i; enum pkgfrom_t *from = NULL; if (!hashdb->immediate_deps) { pw_printf(PW_LOG_NORM, "\nNo dependencies found.\n\n"); return; } printf("\n"); pw_printf(PW_LOG_INFO, "Dependencies:\n"); for (i = hashdb->immediate_deps; i; i = i->next) { from = hashmap_search(hashdb->pkg_from, i->data); switch (*from) { case PKG_FROM_LOCAL: pw_printf(PW_LOG_NORM, "%s%s (installed)%s\n", color.bgreen, i->data, color.nocolor); break; case PKG_FROM_SYNC: pw_printf(PW_LOG_NORM, "%s%s (found in sync)%s\n", color.bblue, i->data, color.nocolor); break; case PKG_FROM_AUR: /* Magic happens here */ if (hash_search(hashdb->aur_outdated, (void *) i->data)) { pw_printf(PW_LOG_NORM, "%s%s (AUR target)%s\n", color.bred, i->data, color.nocolor); } else { struct pkgpair pkgpair; pkgpair.pkgname = i->data; if (hash_search(hashdb->aur, &pkgpair)) { pw_printf(PW_LOG_NORM, "%s%s (installed AUR)%s\n", color.bblue, i->data, color.nocolor); } else { /* New AUR package */ pw_printf(PW_LOG_NORM, "%s%s (AUR dep)%s\n", color.bmag, i->data, color.nocolor); } } break; default: /* Shouldn't happen */ pw_printf(PW_LOG_NORM, "Unknown\n"); break; } } printf("\n"); }
var_p_t hashmap_putv(var_p_t map, const var_p_t key) { // hashmap takes ownership of key if (key->type != V_STR) { // keys are always strings v_tostr(key); } Node *node = hashmap_search(map, key->v.p.ptr, key->v.p.length); if (node->key == NULL) { node->key = key; node->value = v_new(); map->v.m.count++; } else { // discard unused key v_free(key); v_detach(key); } return node->value; }
/* Adds immediate dependencies to hashdb->immediate_deps * This enables us to print the immediate deps instead of the entire huge * dependency graph. */ static void add_immediate_deps(struct pw_hashdb *hashdb, const char *pkgname, alpm_list_t *deps, struct hash_table *immediate) { enum pkgfrom_t *from = NULL; alpm_list_t *i; struct pkgpair pkgpair; from = hashmap_search(hashdb->pkg_from, (void *) pkgname); if (!from) { return; } else if (*from == PKG_FROM_AUR) { pkgpair.pkgname = pkgname; /* Applies to new AUR packages and outdated AUR packages */ if (!hash_search(hashdb->aur, &pkgpair) || hash_search(hashdb->aur_outdated, (void *) pkgname)) { for (i = deps; i; i = i->next) { if (!hash_search(immediate, (void *) i->data)) { hashdb->immediate_deps = alpm_list_add(hashdb->immediate_deps, i->data); hash_insert(immediate, (void *) i->data); } } } } }
/* 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; }
/* Change provided package to a package which provides it. * For AUR packages, this also downloads and extracts PKGBUILD in cwd. * In addition, the "normalized" packages will be cached in hashdb->pkg_from * * @param curl curl handle * @param hashdb hash database * @param pkg package name * @param resolve_lvl level of dep resolution. RESOLVE_THOROUGH forces * downloading of AUR PKGBUILDs * * returns the "normalized" package if present, NULL on failure */ static const char *normalize_package(CURL *curl, struct pw_hashdb *hashdb, const char *pkgname, int resolve_lvl) { const char *provided = NULL; struct pkgpair pkgpair; struct pkgpair *pkgptr; enum pkgfrom_t *pkgfrom; pkgpair.pkgname = pkgname; pkgpair.pkg = NULL; /* If we know where pkg is from and it's not AUR / it's from AUR and * already downloaded, done */ pkgfrom = hashmap_search(hashdb->pkg_from, (void *) pkgname); if (pkgfrom) { if (*pkgfrom != PKG_FROM_AUR || hash_search(hashdb->aur_downloaded, (void *) pkgname)) { return pkgname; } goto search_aur; } /* If it's in local db and not AUR, done */ if (hash_search(hashdb->local, &pkgpair)) { if (hash_search(hashdb->aur, &pkgpair)) { goto search_aur; } hashmap_insert(hashdb->pkg_from, (void *) pkgname, &hashdb->pkg_from_local); return pkgname; } /* Search provides cache */ provided = hashmap_search(hashdb->provides_cache, (void *) pkgname); if (provided) { return provided; } /* Search local provides */ pkgptr = hashbst_tree_search(hashdb->local_provides, (void *) pkgname, hashdb->local, provides_search); if (pkgptr) { /* Cache in provides and pkg_from */ hashmap_insert(hashdb->provides_cache, (void *) pkgname, (void *) pkgptr->pkgname); hashmap_insert(hashdb->pkg_from, (void *) pkgptr->pkgname, &hashdb->pkg_from_local); return pkgptr->pkgname; } /* Search sync provides tree in local db * TODO: Is there a meaning to this? * local provides are obtained from local packages. * sync provides are obtained from sync packages. * So searching for sync provides in local database is kind of... */ pkgptr = hashbst_tree_search(hashdb->sync_provides, (void *) pkgname, hashdb->local, provides_search); if (pkgptr) { /* Cache in pkg_from */ hashmap_insert(hashdb->pkg_from, (void *) pkgptr->pkgname, &hashdb->pkg_from_local); return pkgptr->pkgname; } /* Search sync db */ if (hash_search(hashdb->sync, &pkgpair)) { hashmap_insert(hashdb->pkg_from, (void *) pkgname, &hashdb->pkg_from_sync); return pkgname; } /* Sync provides */ pkgptr = hashbst_tree_search(hashdb->sync_provides, (void *) pkgname, hashdb->sync, provides_search); if (pkgptr) { hashmap_insert(hashdb->pkg_from, (void *) pkgptr->pkgname, &hashdb->pkg_from_sync); hashmap_insert(hashdb->provides_cache, (void *) pkgname, (void *) pkgptr->pkgname); return pkgptr->pkgname; } search_aur: pkgpair.pkgname = pkgname; pkgpair.pkg = NULL; /* For non RESOLVE_THOROUGH, don't bother downloading PKGBUILD of updated * AUR packages */ if (resolve_lvl != RESOLVE_THOROUGH) { if (hash_search(hashdb->aur, &pkgpair) && !hash_search(hashdb->aur_outdated, (void *) pkgname)) { goto done; } } /* Download and extract from AUR */ if (dl_extract_single_package(curl, pkgname, NULL, 0)) { return NULL; } hash_insert(hashdb->aur_downloaded, (void *) pkgname); hashmap_insert(hashdb->pkg_from, (void *) pkgname, &hashdb->pkg_from_aur); done: return pkgname; }
void * global_get_plug(int id){ if(id < 0) return NULL; global_init(); return hashmap_search(self.plugs, id); }
void * global_get_device(int id){ if(id < 0) return NULL; global_init(); return hashmap_search(self.devices, id); }