void show_results () { alpm_list_t *i_first; alpm_list_t *i; alpm_list_nav fn_nav=NULL;; alpm_list_fn_cmp fn_cmp=NULL; if (results!=NULL) { switch (config.sort) { case S_NAME: fn_cmp = (alpm_list_fn_cmp) results_cmp; break; case S_VOTE: fn_cmp = (alpm_list_fn_cmp) results_votes_cmp; break; case S_IDATE: fn_cmp = (alpm_list_fn_cmp) results_installdate_cmp; break; case S_ISIZE: fn_cmp = (alpm_list_fn_cmp) results_isize_cmp; break; } if (fn_cmp) results = alpm_list_msort (results, alpm_list_count (results), fn_cmp); if (config.rsort) { fn_nav = (alpm_list_nav) alpm_list_previous; i_first = alpm_list_last (results); } else { fn_nav = (alpm_list_nav) alpm_list_next; i_first = results; } for(i = i_first; i; i = fn_nav(i)) { results_t *r = i->data; if (r->type == R_ALPM_PKG) print_package ("", r->ele, alpm_pkg_get_str); else if (r->type == R_AUR_PKG) print_package ("", r->ele, aur_get_str); } alpm_list_free_inner (results, (alpm_list_fn_free) results_free); alpm_list_free (results); results = NULL; } }
/* Re-order a list of target packages with respect to their dependencies. * * Example (reverse == 0): * A depends on C * B depends on A * Target order is A,B,C,D * * Should be re-ordered to C,A,B,D * * packages listed in ignore will not be used to detect indirect dependencies * * if reverse is > 0, the dependency order will be reversed. * * This function returns the new alpm_list_t* target list. * */ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, alpm_list_t *targets, alpm_list_t *ignore, int reverse) { alpm_list_t *newtargs = NULL; alpm_list_t *vertices = NULL; alpm_list_t *vptr; alpm_graph_t *vertex; if(targets == NULL) { return NULL; } _alpm_log(handle, ALPM_LOG_DEBUG, "started sorting dependencies\n"); vertices = dep_graph_init(handle, targets, ignore); vptr = vertices; vertex = vertices->data; while(vptr) { /* mark that we touched the vertex */ vertex->state = -1; int found = 0; while(vertex->childptr && !found) { alpm_graph_t *nextchild = vertex->childptr->data; vertex->childptr = vertex->childptr->next; if(nextchild->state == 0) { found = 1; nextchild->parent = vertex; vertex = nextchild; } else if(nextchild->state == -1) { /* child is an ancestor of vertex */ alpm_graph_t *transvertex = vertex; if(!alpm_list_find(targets, nextchild->data, ptr_cmp)) { /* child is not part of the transaction, not a problem */ continue; } /* find the nearest parent that's part of the transaction */ while(transvertex) { if(alpm_list_find(targets, transvertex->data, ptr_cmp)) { break; } transvertex = transvertex->parent; } if(!transvertex || transvertex == nextchild) { /* no transaction package in our ancestry or the package has * a circular dependency with itself, not a problem */ } else { alpm_pkg_t *transpkg = transvertex->data; alpm_pkg_t *childpkg = nextchild->data; _alpm_log(handle, ALPM_LOG_WARNING, _("dependency cycle detected:\n")); if(reverse) { _alpm_log(handle, ALPM_LOG_WARNING, _("%s will be removed after its %s dependency\n"), transpkg->name, childpkg->name); } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s will be installed before its %s dependency\n"), transpkg->name, childpkg->name); } } } } if(!found) { if(alpm_list_find(targets, vertex->data, ptr_cmp)) { newtargs = alpm_list_add(newtargs, vertex->data); } /* mark that we've left this vertex */ vertex->state = 1; vertex = vertex->parent; if(!vertex) { /* top level vertex reached, move to the next unprocessed vertex */ for( vptr = vptr->next; vptr; vptr = vptr->next) { vertex = vptr->data; if(vertex->state == 0) { break; } } } } } _alpm_log(handle, ALPM_LOG_DEBUG, "sorting dependencies finished\n"); if(reverse) { /* reverse the order */ alpm_list_t *tmptargs = alpm_list_reverse(newtargs); /* free the old one */ alpm_list_free(newtargs); newtargs = tmptargs; } alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); return newtargs; }
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; int from_sync = 0; int ret = 0; alpm_trans_t *trans = handle->trans; alpm_event_t event; if(data) { *data = NULL; } for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; if (spkg->origin == ALPM_PKG_FROM_SYNCDB){ from_sync = 1; break; } } /* ensure all sync database are valid if we will be using them */ for(i = handle->dbs_sync; i; i = i->next) { const alpm_db_t *db = i->data; if(db->status & DB_STATUS_INVALID) { RET_ERR(handle, ALPM_ERR_DB_INVALID, -1); } /* missing databases are not allowed if we have sync targets */ if(from_sync && db->status & DB_STATUS_MISSING) { RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1); } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { alpm_list_t *resolved = NULL; alpm_list_t *remove = alpm_list_copy(trans->remove); alpm_list_t *localpkgs; /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ event.type = ALPM_EVENT_RESOLVEDEPS_START; EVENT(handle, &event); _alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } } /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } alpm_list_free(localpkgs); alpm_list_free(remove); /* If there were unresolvable top-level packages, prompt the user to see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { alpm_question_remove_pkgs_t question = { .type = ALPM_QUESTION_REMOVE_PKGS, .skip = 0, .packages = unresolvable }; QUESTION(handle, &question); if(question.skip) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ handle->pm_errno = 0; if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)alpm_depmissing_free); alpm_list_free(*data); *data = NULL; } } else { /* pm_errno was set by resolvedeps, callback may have overwrote it */ handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; alpm_list_free(resolved); alpm_list_free(unresolvable); ret = -1; goto cleanup; } } /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(!alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = ALPM_PKG_REASON_DEPEND; } } /* Unresolvable packages will be removed from the target list; set these * aside in the transaction as a list we won't operate on. If we free them * before the end of the transaction, we may kill pointers the frontend * holds to package objects. */ trans->unresolvable = unresolvable; alpm_list_free(trans->add); trans->add = resolved; event.type = ALPM_EVENT_RESOLVEDEPS_DONE; EVENT(handle, &event); }
/* Re-order a list of target packages with respect to their dependencies. * * Example (reverse == 0): * A depends on C * B depends on A * Target order is A,B,C,D * * Should be re-ordered to C,A,B,D * * if reverse is > 0, the dependency order will be reversed. * * This function returns the new alpm_list_t* target list. * */ alpm_list_t *_alpm_sortbydeps(pmhandle_t *handle, alpm_list_t *targets, int reverse) { alpm_list_t *newtargs = NULL; alpm_list_t *vertices = NULL; alpm_list_t *vptr; pmgraph_t *vertex; if(targets == NULL) { return NULL; } _alpm_log(handle, PM_LOG_DEBUG, "started sorting dependencies\n"); vertices = dep_graph_init(targets); vptr = vertices; vertex = vertices->data; while(vptr) { /* mark that we touched the vertex */ vertex->state = -1; int found = 0; while(vertex->childptr && !found) { pmgraph_t *nextchild = vertex->childptr->data; vertex->childptr = vertex->childptr->next; if(nextchild->state == 0) { found = 1; nextchild->parent = vertex; vertex = nextchild; } else if(nextchild->state == -1) { pmpkg_t *vertexpkg = vertex->data; pmpkg_t *childpkg = nextchild->data; const char *message; _alpm_log(handle, PM_LOG_WARNING, _("dependency cycle detected:\n")); if(reverse) { message =_("%s will be removed after its %s dependency\n"); } else { message =_("%s will be installed before its %s dependency\n"); } _alpm_log(handle, PM_LOG_WARNING, message, vertexpkg->name, childpkg->name); } } if(!found) { newtargs = alpm_list_add(newtargs, vertex->data); /* mark that we've left this vertex */ vertex->state = 1; vertex = vertex->parent; if(!vertex) { vptr = vptr->next; while(vptr) { vertex = vptr->data; if(vertex->state == 0) break; vptr = vptr->next; } } } } _alpm_log(handle, PM_LOG_DEBUG, "sorting dependencies finished\n"); if(reverse) { /* reverse the order */ alpm_list_t *tmptargs = alpm_list_reverse(newtargs); /* free the old one */ alpm_list_free(newtargs); newtargs = tmptargs; } alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); return newtargs; }
int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *i; alpm_list_t *deltas = NULL; size_t numtargs, current = 0, replaces = 0; int errors; alpm_trans_t *trans = handle->trans; if(download_files(handle, &deltas)) { alpm_list_free(deltas); return -1; } if(validate_deltas(handle, deltas, data)) { alpm_list_free(deltas); return -1; } alpm_list_free(deltas); /* Check integrity of packages */ numtargs = alpm_list_count(trans->add); EVENT(trans, ALPM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; for(i = trans->add; i; i = i->next, current++) { alpm_pkg_t *spkg = i->data; int percent = (current * 100) / numtargs; const char *filename; char *filepath; alpm_siglevel_t level; PROGRESS(trans, ALPM_TRANS_PROGRESS_INTEGRITY_START, "", percent, numtargs, current); if(spkg->origin == PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } filename = alpm_pkg_get_filename(spkg); filepath = _alpm_filecache_find(handle, filename); alpm_db_t *sdb = alpm_pkg_get_db(spkg); level = alpm_db_get_siglevel(sdb); /* load the package file and replace pkgcache entry with it in the target list */ /* TODO: alpm_pkg_get_db() will not work on this target anymore */ _alpm_log(handle, ALPM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); alpm_pkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1, spkg->md5sum, spkg->base64_sig, level); if(!pkgfile) { errors++; *data = alpm_list_add(*data, strdup(filename)); FREE(filepath); continue; } FREE(filepath); pkgfile->reason = spkg->reason; /* copy over install reason */ i->data = pkgfile; _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } PROGRESS(trans, ALPM_TRANS_PROGRESS_INTEGRITY_START, "", 100, numtargs, current); EVENT(trans, ALPM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); if(errors) { RET_ERR(handle, ALPM_ERR_PKG_INVALID, -1); } if(trans->flags & ALPM_TRANS_FLAG_DOWNLOADONLY) { return 0; } trans->state = STATE_COMMITING; replaces = alpm_list_count(trans->remove); /* fileconflict check */ if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) { EVENT(trans, ALPM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n"); alpm_list_t *conflict = _alpm_db_find_fileconflicts(handle, trans->add, trans->remove); if(conflict) { if(data) { *data = conflict; } else { alpm_list_free_inner(conflict, (alpm_list_fn_free)_alpm_fileconflict_free); alpm_list_free(conflict); } RET_ERR(handle, ALPM_ERR_FILE_CONFLICTS, -1); } EVENT(trans, ALPM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); } /* check available disk space */ if(handle->checkspace) { EVENT(trans, ALPM_TRANS_EVT_DISKSPACE_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n"); if(_alpm_check_diskspace(handle) == -1) { _alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space")); return -1; } EVENT(trans, ALPM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); } /* remove conflicting and to-be-replaced packages */ if(replaces) { _alpm_log(handle, ALPM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); /* we want the frontend to be aware of commit details */ if(_alpm_remove_packages(handle) == -1) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not commit removal transaction\n")); return -1; } } /* install targets */ _alpm_log(handle, ALPM_LOG_DEBUG, "installing packages\n"); if(_alpm_upgrade_packages(handle) == -1) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not commit transaction\n")); return -1; } return 0; }
static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) { const char *cachedir; alpm_list_t *i, *j; alpm_list_t *files = NULL; int errors = 0; cachedir = _alpm_filecache_setup(handle); handle->trans->state = STATE_DOWNLOADING; /* Total progress - figure out the total download size if required to * pass to the callback. This function is called once, and it is up to the * frontend to compute incremental progress. */ if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ for(i = handle->trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; total_size += spkg->download_size; } handle->totaldlcb(total_size); } /* group sync records by repository and download */ for(i = handle->dbs_sync; i; i = i->next) { alpm_db_t *current = i->data; for(j = handle->trans->add; j; j = j->next) { alpm_pkg_t *spkg = j->data; if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { alpm_list_t *delta_path = spkg->delta_path; if(delta_path) { /* using deltas */ alpm_list_t *dlts; for(dlts = delta_path; dlts; dlts = dlts->next) { alpm_delta_t *delta = dlts->data; if(delta->download_size != 0) { struct dload_payload *dpayload; CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); STRDUP(dpayload->filename, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); dpayload->max_size = delta->download_size; files = alpm_list_add(files, dpayload); } /* keep a list of all the delta files for md5sums */ *deltas = alpm_list_add(*deltas, delta); } } else if(spkg->download_size != 0) { struct dload_payload *payload; ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); STRDUP(payload->filename, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); payload->max_size = alpm_pkg_get_size(spkg); files = alpm_list_add(files, payload); } } } if(files) { EVENT(handle->trans, ALPM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); for(j = files; j; j = j->next) { struct dload_payload *payload = j->data; alpm_list_t *server; int ret = -1; for(server = current->servers; server; server = server->next) { const char *server_url = server->data; size_t len; /* print server + filename into a buffer */ len = strlen(server_url) + strlen(payload->filename) + 2; CALLOC(payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); snprintf(payload->fileurl, len, "%s/%s", server_url, payload->filename); payload->handle = handle; payload->allow_resume = 1; ret = _alpm_download(payload, cachedir, NULL); if(ret != -1) { break; } } if(ret == -1) { errors++; } } alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_free); alpm_list_free(files); files = NULL; if(errors) { _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"), current->treename); if(handle->pm_errno == 0) { handle->pm_errno = ALPM_ERR_RETRIEVE; } return -1; } } } for(j = handle->trans->add; j; j = j->next) { alpm_pkg_t *pkg = j->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; } /* clear out value to let callback know we are done */ if(handle->totaldlcb) { handle->totaldlcb(0); } return 0; }
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; alpm_list_t *remove = NULL; int ret = 0; alpm_trans_t *trans = handle->trans; if(data) { *data = NULL; } /* ensure all sync database are valid since we will be using them */ for(i = handle->dbs_sync; i; i = i->next) { const alpm_db_t *db = i->data; if(!(db->status & DB_STATUS_VALID)) { RET_ERR(handle, ALPM_ERR_DB_INVALID, -1); } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { alpm_list_t *resolved = NULL; /* target list after resolvedeps */ /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } } /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } alpm_list_free(localpkgs); /* If there were unresolvable top-level packages, prompt the user to see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; QUESTION(trans, ALPM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); if(remove_unresolvable) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ handle->pm_errno = 0; /* pm_errno was set by resolvedeps */ if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(*data); *data = NULL; } } else { /* pm_errno is set by resolvedeps */ alpm_list_free(resolved); ret = -1; goto cleanup; } } /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { alpm_pkg_t *pkg = i->data; if(!_alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = ALPM_PKG_REASON_DEPEND; } } /* Unresolvable packages will be removed from the target list, so we free the transaction specific fields */ alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); /* re-order w.r.t. dependencies */ alpm_list_free(trans->add); trans->add = _alpm_sortbydeps(handle, resolved, 0); alpm_list_free(resolved); EVENT(trans, ALPM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); } if(!(trans->flags & ALPM_TRANS_FLAG_NOCONFLICTS)) { /* check for inter-conflicts and whatnot */ EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for conflicts\n"); /* 1. check for conflicts in the target list */ _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n"); deps = _alpm_innerconflicts(handle, trans->add); for(i = deps; i; i = i->next) { alpm_conflict_t *conflict = i->data; alpm_pkg_t *rsync, *sync, *sync1, *sync2; /* have we already removed one of the conflicting targets? */ sync1 = _alpm_pkg_find(trans->add, conflict->package1); sync2 = _alpm_pkg_find(trans->add, conflict->package2); if(!sync1 || !sync2) { continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; } else if(_alpm_depcmp(sync2, dep1)) { rsync = sync1; sync = sync2; } else { _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); _alpm_dep_free(dep1); _alpm_dep_free(dep2); goto cleanup; } _alpm_dep_free(dep1); _alpm_dep_free(dep2); /* Prints warning */ _alpm_log(handle, ALPM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ continue; } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); deps = NULL; /* 2. we check for target vs db conflicts (and resolve)*/ _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs db and db vs targets\n"); deps = _alpm_outerconflicts(handle->db_local, trans->add); for(i = deps; i; i = i->next) { alpm_conflict_t *conflict = i->data; /* if conflict->package2 (the local package) is not elected for removal, we ask the user */ int found = 0; for(j = trans->add; j && !found; j = j->next) { alpm_pkg_t *spkg = j->data; if(_alpm_pkg_find(spkg->removes, conflict->package2)) { found = 1; } } if(found) { continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); alpm_pkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); alpm_pkg_t *local = _alpm_db_get_pkgfromcache(handle->db_local, conflict->package2); int doremove = 0; QUESTION(trans, ALPM_TRANS_CONV_CONFLICT_PKG, conflict->package1, conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ _alpm_log(handle, ALPM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); sync->removes = alpm_list_add(sync->removes, local); } else { /* abort */ _alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n")); handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict); if(newconflict) { *data = alpm_list_add(*data, newconflict); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); goto cleanup; } } EVENT(trans, ALPM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); alpm_list_free(deps); } /* Build trans->remove list */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { alpm_pkg_t *rpkg = j->data; if(!_alpm_pkg_find(trans->remove, rpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(rpkg)); } } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { _alpm_log(handle, ALPM_LOG_DEBUG, "checking dependencies\n"); deps = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), trans->remove, trans->add, 1); if(deps) { handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; ret = -1; if(data) { *data = deps; } else { alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); } goto cleanup; } } for(i = trans->add; i; i = i->next) { /* update download size field */ alpm_pkg_t *spkg = i->data; if(compute_download_size(spkg) != 0) { ret = -1; goto cleanup; } } cleanup: alpm_list_free(unresolvable); alpm_list_free(remove); return ret; }
/* Normal -S, install packages from AUR * returns 0 on success, -1 on failure */ static int sync_targets(CURL *curl, alpm_list_t *targets) { struct pw_hashdb *hashdb = build_hashdb(); struct pkgpair pkgpair; struct pkgpair *pkgpair_ptr; struct aurpkg_t *aurpkg; alpm_pkg_t *lpkg; alpm_list_t *i; alpm_list_t *reinstall, *new_packages, *upgrade, *downgrade, *not_aur; alpm_list_t *aurpkg_list, *final_targets; int vercmp; int joined = 0, ret = 0; reinstall = new_packages = upgrade = downgrade = aurpkg_list = not_aur = NULL; final_targets = NULL; if (!hashdb) { pw_fprintf(PW_LOG_ERROR, stderr, "Failed to create hashdb\n"); goto cleanup; } for (i = targets; i; i = i->next) { aurpkg_list = query_aur(curl, i->data, AUR_QUERY_INFO); if (!aurpkg_list) { not_aur = alpm_list_add(not_aur, i->data); goto free_aurpkg; } /* Check version string */ pkgpair.pkgname = i->data; pkgpair_ptr = hash_search(hashdb->aur, &pkgpair); /* Locally installed AUR */ if (pkgpair_ptr) { aurpkg = aurpkg_list->data; lpkg = pkgpair_ptr->pkg; vercmp = alpm_pkg_vercmp(aurpkg->version, alpm_pkg_get_version(lpkg)); if (vercmp > 0) { upgrade = alpm_list_add(upgrade, i->data); } else if (vercmp == 0) { reinstall = alpm_list_add(reinstall, i->data); } else { downgrade = alpm_list_add(downgrade, i->data); } } else { new_packages = alpm_list_add(new_packages, i->data); } free_aurpkg: alpm_list_free_inner(aurpkg_list, (alpm_list_fn_free) aurpkg_free); alpm_list_free(aurpkg_list); } if (not_aur) { printf("\n%sThese packages are not from the AUR:%s\n", color.bred, color.nocolor); print_list(not_aur); } if (downgrade) { printf("\n%sLocally installed but newer than AUR, ignoring:%s\n", color.bcyan, color.nocolor); print_list(downgrade); } if (reinstall) { printf("\n%sReinstalling:%s\n", color.byellow, color.nocolor); print_list(reinstall); } if (upgrade) { printf("\n%sUpgrading:%s\n", color.bblue, color.nocolor); print_list(upgrade); } if (new_packages) { printf("\n%sSyncing:%s\n", color.bmag, color.nocolor); print_list(new_packages); } printf("\n"); if (config->noconfirm || yesno("Do you wish to proceed?")) { final_targets = alpm_list_join(reinstall, upgrade); final_targets = alpm_list_join(final_targets, new_packages); joined = 1; ret = upgrade_pkgs(final_targets, hashdb); } cleanup: hashdb_free(hashdb); alpm_list_free(downgrade); alpm_list_free(not_aur); if (joined) { alpm_list_free(final_targets); } else { alpm_list_free(reinstall); alpm_list_free(new_packages); alpm_list_free(upgrade); } return ret; }
/* -Su, checks AUR packages */ static int sync_upgrade(CURL *curl, alpm_list_t *targets) { int ret = 0; int cnt = 0; int upgrade_all; struct pkgpair pkgpair; struct pw_hashdb *hashdb = build_hashdb(); if (!hashdb) { pw_fprintf(PW_LOG_ERROR, stderr, "Failed to build hash database."); return -1; } /* Make sure that packages are from AUR */ alpm_list_t *i, *new_targs = NULL; for (i = targets; i; i = i->next) { pkgpair.pkgname = i->data; if (!hash_search(hashdb->aur, &pkgpair)) { if (cnt++) { printf(", "); } pw_printf(PW_LOG_NORM, "%s", i->data); } else { new_targs = alpm_list_add(new_targs, i->data); } } if (cnt > 1) { printf(" are not AUR packages and will not be checked.\n"); } else if (cnt == 1) { printf(" is not an AUR package and will not be checked.\n"); } alpm_list_t *outdated_pkgs = NULL; if (!targets) { /* Check all AUR packages */ outdated_pkgs = get_outdated_pkgs(curl, hashdb, NULL); } else { if (!new_targs) { goto cleanup; } outdated_pkgs = get_outdated_pkgs(curl, hashdb, new_targs); } if (!outdated_pkgs) { pw_printf(PW_LOG_INFO, "All AUR packages are up to date.\n"); goto cleanup; } printf("\n"); pw_printf(PW_LOG_INFO, "Targets:\n"); print_aurpkg_list(outdated_pkgs); printf("\n"); /* --check, don't upgrade */ if (config->op_s_check) { goto cleanup; } upgrade_all = config->noconfirm || yesno("Do you wish to upgrade the above packages?"); if (upgrade_all) { /* Experimental */ alpm_list_t *final_targets = NULL; struct aurpkg_t *aurpkg; for (i = outdated_pkgs; i; i = i->next) { aurpkg = i->data; final_targets = alpm_list_add(final_targets, aurpkg->name); } ret = upgrade_pkgs(final_targets, hashdb); alpm_list_free(final_targets); } cleanup: alpm_list_free_inner(outdated_pkgs, (alpm_list_fn_free) aurpkg_free); alpm_list_free(outdated_pkgs); alpm_list_free(new_targs); hashdb_free(hashdb); return ret; }
/* Returns a list of outdated AUR packages among targets or all AUR packages. * The list and the packages are to be freed by the caller. * * @param curl curl easy handle * @param targets list of strings (package names) that are _definitely_ AUR packages */ static alpm_list_t *get_outdated_pkgs(CURL *curl, struct pw_hashdb *hashdb, alpm_list_t *targets) { alpm_list_t *i; alpm_list_t *outdated_pkgs = NULL; alpm_list_t *pkglist, *targs; struct pkgpair pkgpair; struct pkgpair *pkgpair_ptr; struct aurpkg_t *aurpkg; const char *pkgname, *pkgver; if (targets) { targs = targets; } else { targs = NULL; alpm_list_t *tmp_targs = hash_to_list(hashdb->aur); for (i = tmp_targs; i; i = i->next) { pkgpair_ptr = i->data; targs = alpm_list_add(targs, (void *) pkgpair_ptr->pkgname); } alpm_list_free(tmp_targs); } for (i = targs; i; i = i->next) { pkglist = query_aur(curl, i->data, AUR_QUERY_INFO); if (!pkglist) { continue; } pkgpair.pkgname = i->data; pkgpair_ptr = hash_search(hashdb->aur, &pkgpair); if (!pkgpair_ptr) { /* Shouldn't happen */ pw_fprintf(PW_LOG_ERROR, stderr, "Unable to find AUR package \"%s\"" "in hashdb!\n", i->data); } aurpkg = pkglist->data; pkgver = alpm_pkg_get_version(pkgpair_ptr->pkg); pkgname = i->data; if (alpm_pkg_vercmp(aurpkg->version, pkgver) > 0) { /* Just show outdated package for now */ pw_printf(PW_LOG_INFO, "%s %s is outdated, %s%s%s%s is available\n", pkgname, pkgver, color.bred, aurpkg->version, color.nocolor, color.bold); /* Add to upgrade list */ outdated_pkgs = alpm_list_add(outdated_pkgs, aurpkg); pkglist->data = NULL; } else if (config->verbose) { pw_printf(PW_LOG_INFO, "%s %s is up to date.\n", pkgname, pkgver); } alpm_list_free_inner(pkglist, (alpm_list_fn_free) aurpkg_free); alpm_list_free(pkglist); } if (!targets) { alpm_list_free(targs); } return outdated_pkgs; }
/* Lists detailed information about targets */ static int sync_info(CURL *curl, alpm_list_t *targets) { int found, ret, pkgcount; alpm_list_t *i, *j, *results; alpm_list_t *free_list = NULL; alpm_list_t *syncdbs = alpm_option_get_syncdbs(config->handle); alpm_pkg_t *spkg; char cwd[PATH_MAX]; char filename[PATH_MAX]; char url[PATH_MAX]; FILE *fp = NULL; int fd; struct aurpkg_t *pkg; if (!getcwd(cwd, PATH_MAX)) { return error(PW_ERR_GETCWD); } if (chdir(powaur_dir)) { return error(PW_ERR_CHDIR, powaur_dir); } found = ret = pkgcount = 0; for (i = targets; i; i = i->next, ++pkgcount) { /* Search sync dbs first */ spkg = search_syncdbs(syncdbs, i->data); if (spkg) { if (found++){ printf("\n"); } pacman_pkgdump(spkg, PKG_FROM_SYNC); spkg = NULL; continue; } results = query_aur(curl, i->data, AUR_QUERY_INFO); if (alpm_list_count(results) != 1) { if (pkgcount > 0) { printf("\n"); } pw_printf(PW_LOG_ERROR, "package %s not found\n", i->data); goto garbage_collect; } snprintf(filename, PATH_MAX, "%s.PKGBUILDXXXXXX", i->data); fd = mkstemp(filename); if (fd < 0) { error(PW_ERR_FOPEN, filename); goto garbage_collect; } fp = fdopen(fd, "w+"); if (!fp) { printf("NO\n"); error(PW_ERR_FOPEN, filename); goto garbage_collect; } snprintf(url, PATH_MAX, AUR_PKGBUILD_URL, i->data); /* Download the PKGBUILD and parse it */ ret = download_single_file(curl, url, fp); if (ret) { goto destroy_remnants; } /* Parse PKGBUILD and get detailed info */ fseek(fp, 0L, SEEK_SET); pkg = results->data; parse_pkgbuild(pkg, fp); if (found++) { printf("\n"); } printf("%s%s %saur%s\n", color.bold, REPO, color.bmag, color.nocolor); printf("%s%s %s%s\n", color.bold, NAME, pkg->name, color.nocolor); printf("%s%s %s%s%s\n", color.bold, VERSION, color.bgreen, pkg->version, color.nocolor); printf("%s%s %s%s%s\n", color.bold, URL, color.bcyan, pkg->url, color.nocolor); printf("%s%s%s ", color.bold, A_URL, color.bcyan); printf(AUR_PKG_URL, pkg->id); printf("%s\n", color.nocolor); printf("%s%s %s%s\n", color.bold, LICENSES, color.nocolor, pkg->license); printf("%s%s %s%d\n", color.bold, A_VOTES, color.nocolor, pkg->votes); printf("%s%s ", color.bold, A_OUTOFDATE); if (pkg->outofdate) { printf("%s%s", color.bred, "Yes"); } else { printf("%s%s", color.nocolor, "No"); } printf("%s\n", color.nocolor); print_list_prefix(pkg->provides, PROVIDES); print_list_prefix(pkg->depends, DEPS); print_list_prefix(pkg->optdepends, OPTDEPS); print_list_prefix(pkg->conflicts, CONFLICTS); print_list_prefix(pkg->replaces, REPLACES); print_list_prefix(pkg->arch, ARCH); printf("%s%s%s %s\n", color.bold, DESC, color.nocolor, pkg->desc); destroy_remnants: fclose(fp); fp = NULL; unlink(filename); garbage_collect: free_list = alpm_list_add(free_list, results); } cleanup: for (i = free_list; i; i = i->next) { alpm_list_free_inner(i->data, (alpm_list_fn_free) aurpkg_free); alpm_list_free(i->data); } alpm_list_free(free_list); if (chdir(cwd)) { return error(PW_ERR_RESTORECWD); } return found ? 0 : -1; }
/** * pacman_list_free_contents: * @list: A #PacmanList. * @func: A #GDestroyNotify function. * * Frees every item in @list using @func. */ void pacman_list_free_contents (PacmanList *list, GDestroyNotify func) { alpm_list_free_inner (list, (alpm_list_fn_free) func); }
/** * @brief Transaction preparation for remove actions. * * This functions takes a pointer to a alpm_list_t which will be * filled with a list of alpm_depmissing_t* objects representing * the packages blocking the transaction. * * @param handle the context handle * @param data a pointer to an alpm_list_t* to fill * * @return 0 on success, -1 on error */ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data) { alpm_list_t *lp; alpm_trans_t *trans = handle->trans; alpm_db_t *db = handle->db_local; if((trans->flags & ALPM_TRANS_FLAG_RECURSE) && !(trans->flags & ALPM_TRANS_FLAG_CASCADE)) { _alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n"); if(_alpm_recursedeps(db, trans->remove, trans->flags & ALPM_TRANS_FLAG_RECURSEALL)) { return -1; } } if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { EVENT(handle, ALPM_EVENT_CHECKDEPS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(db), trans->remove, NULL, 1); if(lp != NULL) { if(trans->flags & ALPM_TRANS_FLAG_CASCADE) { if(remove_prepare_cascade(handle, lp)) { return -1; } } else if(trans->flags & ALPM_TRANS_FLAG_UNNEEDED) { /* Remove needed packages (which would break dependencies) * from target list */ remove_prepare_keep_needed(handle, lp); } else { if(data) { *data = lp; } else { alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); } RET_ERR(handle, ALPM_ERR_UNSATISFIED_DEPS, -1); } } } /* re-order w.r.t. dependencies */ _alpm_log(handle, ALPM_LOG_DEBUG, "sorting by dependencies\n"); lp = _alpm_sortbydeps(handle, trans->remove, 1); /* free the old alltargs */ alpm_list_free(trans->remove); trans->remove = lp; /* -Rcs == -Rc then -Rs */ if((trans->flags & ALPM_TRANS_FLAG_CASCADE) && (trans->flags & ALPM_TRANS_FLAG_RECURSE)) { _alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n"); if(_alpm_recursedeps(db, trans->remove, trans->flags & ALPM_TRANS_FLAG_RECURSEALL)) { return -1; } } /* Note packages being removed that are optdepends for installed packages */ remove_notify_needed_optdepends(handle, trans->remove); if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) { EVENT(handle, ALPM_EVENT_CHECKDEPS_DONE, NULL, NULL); } return 0; }
void alpm_list_free_all (alpm_list_t *list) { do { alpm_list_free_inner (list, free); alpm_list_free (list); list = NULL; } while (0); }
static void pk_backend_search_thread (PkBackendJob *job, GVariant* params, gpointer p) { PkBackend *backend = pk_backend_job_get_backend (job); PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend); gchar **needles = NULL; SearchType type; PatternFunc pattern_func; GDestroyNotify pattern_free; MatchFunc match_func; PkRoleEnum role; PkBitfield filters = 0; gboolean skip_local, skip_remote; const alpm_list_t *i; alpm_list_t *patterns = NULL; _cleanup_error_free_ GError *error = NULL; g_return_if_fail (p == NULL); role = pk_backend_job_get_role(job); switch(role) { case PK_ROLE_ENUM_GET_PACKAGES: type = SEARCH_TYPE_ALL; g_variant_get (params, "(t)", &filters); break; case PK_ROLE_ENUM_GET_DETAILS: type = SEARCH_TYPE_DETAILS; g_variant_get (params, "(^a&s)", &needles); break; case PK_ROLE_ENUM_SEARCH_FILE: type = SEARCH_TYPE_FILES; g_variant_get (params, "(t^a&s)", &filters, &needles); break; case PK_ROLE_ENUM_SEARCH_GROUP: type = SEARCH_TYPE_GROUP; g_variant_get (params, "(t^a&s)", &filters, &needles); break; case PK_ROLE_ENUM_SEARCH_NAME: type = SEARCH_TYPE_NAME; g_variant_get (params, "(t^a&s)", &filters, &needles); break; case PK_ROLE_ENUM_WHAT_PROVIDES: type = SEARCH_TYPE_PROVIDES; g_variant_get (params, "(t^a&s)", &filters, &needles); break; case PK_ROLE_ENUM_SEARCH_DETAILS: type = SEARCH_TYPE_DETAILS; g_variant_get (params, "(t^a&s)", &filters, &needles); break; default: g_assert_not_reached (); break; } g_return_if_fail (type < SEARCH_TYPE_LAST); pattern_func = pattern_funcs[type]; pattern_free = pattern_frees[type]; match_func = match_funcs[type]; g_return_if_fail (pattern_func != NULL); g_return_if_fail (match_func != NULL); skip_local = pk_bitfield_contain (filters, PK_FILTER_ENUM_NOT_INSTALLED); skip_remote = pk_bitfield_contain (filters, PK_FILTER_ENUM_INSTALLED); /* convert search terms to the pattern requested */ if (needles) { for (; *needles != NULL; ++needles) { gpointer pattern = pattern_func (backend, *needles, &error); if (pattern == NULL) goto out; patterns = alpm_list_add (patterns, pattern); } } /* find installed packages first */ if (!skip_local) pk_backend_search_db (job, priv->localdb, match_func, patterns); if (skip_remote) goto out; for (i = alpm_get_syncdbs (priv->alpm); i != NULL; i = i->next) { if (pk_backend_job_is_cancelled (job)) break; pk_backend_search_db (job, i->data, match_func, patterns); } out: if (pattern_free != NULL) alpm_list_free_inner (patterns, pattern_free); alpm_list_free (patterns); pk_alpm_finish (job, error); }