LCOV - code coverage report
Current view: top level - libpkg - pkg_jobs_universe.c (source / functions) Hit Total Coverage
Test: rapport Lines: 549 702 78.2 %
Date: 2021-12-10 16:22:55 Functions: 22 24 91.7 %
Branches: 357 515 69.3 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2014, Vsevolod Stakhov
       2                 :            :  * All rights reserved.
       3                 :            :  *
       4                 :            :  * Redistribution and use in source and binary forms, with or without
       5                 :            :  * modification, are permitted provided that the following conditions are met:
       6                 :            :  *       * Redistributions of source code must retain the above copyright
       7                 :            :  *         notice, this list of conditions and the following disclaimer.
       8                 :            :  *       * Redistributions in binary form must reproduce the above copyright
       9                 :            :  *         notice, this list of conditions and the following disclaimer in the
      10                 :            :  *         documentation and/or other materials provided with the distribution.
      11                 :            :  *
      12                 :            :  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
      13                 :            :  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      14                 :            :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      15                 :            :  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
      16                 :            :  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      17                 :            :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      18                 :            :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      19                 :            :  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      20                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      21                 :            :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      22                 :            :  */
      23                 :            : 
      24                 :            : #ifdef HAVE_CONFIG_H
      25                 :            : #include "pkg_config.h"
      26                 :            : #endif
      27                 :            : 
      28                 :            : #include <sys/param.h>
      29                 :            : #include <sys/types.h>
      30                 :            : 
      31                 :            : #include <assert.h>
      32                 :            : #include <errno.h>
      33                 :            : #ifdef HAVE_LIBUTIL_H
      34                 :            : #include <libutil.h>
      35                 :            : #endif
      36                 :            : #include <stdbool.h>
      37                 :            : #include <stdlib.h>
      38                 :            : #include <string.h>
      39                 :            : #include <ctype.h>
      40                 :            : 
      41                 :            : #include "pkg.h"
      42                 :            : #include "private/event.h"
      43                 :            : #include "private/pkg.h"
      44                 :            : #include "private/pkgdb.h"
      45                 :            : #include "private/pkg_jobs.h"
      46                 :            : #include "kvec.h"
      47                 :            : 
      48                 :            : #define IS_DELETE(j) ((j)->type == PKG_JOBS_DEINSTALL || (j)->type == PKG_JOBS_AUTOREMOVE)
      49                 :            : 
      50                 :            : typedef kvec_t(struct pkg *) pkg_chain_t;
      51                 :            : 
      52                 :            : struct pkg *
      53                 :       2189 : pkg_jobs_universe_get_local(struct pkg_jobs_universe *universe,
      54                 :            :         const char *uid, unsigned flag)
      55                 :            : {
      56                 :       2189 :         struct pkg *pkg = NULL;
      57                 :            :         struct pkgdb_it *it;
      58                 :            :         struct pkg_job_universe_item *unit, *cur, *found;
      59                 :            : 
      60         [ +  + ]:       2189 :         if (flag == 0) {
      61   [ +  -  -  + ]:       2185 :                 if (!IS_DELETE(universe->j))
      62                 :       2185 :                         flag = PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_RDEPS|PKG_LOAD_OPTIONS|
      63                 :            :                                 PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
      64                 :            :                                 PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|PKG_LOAD_ANNOTATIONS|
      65                 :            :                                 PKG_LOAD_CONFLICTS;
      66                 :            :                 else
      67                 :          0 :                         flag = PKG_LOAD_BASIC|PKG_LOAD_RDEPS|PKG_LOAD_DEPS|PKG_LOAD_ANNOTATIONS;
      68                 :       2185 :         }
      69                 :            : 
      70                 :       2189 :         unit = pkghash_get_value(universe->items, uid);
      71         [ +  + ]:       2189 :         if (unit != NULL) {
      72                 :            :                 /* Search local in a universe chain */
      73                 :        781 :                 cur = unit;
      74                 :        781 :                 found = NULL;
      75                 :        781 :                 do {
      76         [ +  + ]:        821 :                         if (cur->pkg->type == PKG_INSTALLED) {
      77                 :        347 :                                 found = cur;
      78                 :        347 :                                 break;
      79                 :            :                         }
      80                 :        474 :                         cur = cur->prev;
      81         [ +  + ]:        474 :                 } while (cur != unit);
      82                 :            : 
      83         [ +  + ]:        781 :                 if (found) {
      84                 :        347 :                         pkgdb_ensure_loaded(universe->j->db, unit->pkg, flag);
      85                 :        347 :                         return (unit->pkg);
      86                 :            :                 }
      87                 :        434 :         }
      88                 :            : 
      89         [ +  - ]:       1842 :         if ((it = pkgdb_query(universe->j->db, uid, MATCH_EXACT)) == NULL)
      90                 :          0 :                 return (NULL);
      91                 :            : 
      92         [ +  + ]:       1842 :         if (pkgdb_it_next(it, &pkg, flag) != EPKG_OK)
      93                 :       1524 :                 pkg = NULL;
      94                 :            : 
      95                 :       1842 :         pkgdb_it_free(it);
      96                 :            : 
      97                 :       1842 :         return (pkg);
      98                 :       2189 : }
      99                 :            : 
     100                 :            : static pkg_chain_t *
     101                 :        152 : pkg_jobs_universe_get_remote(struct pkg_jobs_universe *universe,
     102                 :            :         const char *uid, unsigned flag)
     103                 :            : {
     104                 :        152 :         struct pkg *pkg = NULL;
     105                 :        152 :         pkg_chain_t *result = NULL;
     106                 :            :         struct pkgdb_it *it;
     107                 :            :         struct pkg_job_universe_item *unit, *cur, *found;
     108                 :            : 
     109         [ -  + ]:        152 :         if (flag == 0) {
     110                 :        152 :                 flag = PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_OPTIONS|
     111                 :            :                         PKG_LOAD_PROVIDES|PKG_LOAD_REQUIRES|
     112                 :            :                                 PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
     113                 :            :                                 PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
     114                 :        152 :         }
     115                 :            : 
     116                 :        152 :         unit = pkghash_get_value(universe->items, uid);
     117   [ -  +  #  # ]:        152 :         if (unit != NULL && unit->pkg->type != PKG_INSTALLED) {
     118                 :            :                 /* Search local in a universe chain */
     119                 :          0 :                 cur = unit;
     120                 :          0 :                 found = NULL;
     121                 :          0 :                 do {
     122         [ #  # ]:          0 :                         if (cur->pkg->type != PKG_INSTALLED) {
     123                 :          0 :                                 found = cur;
     124                 :          0 :                                 break;
     125                 :            :                         }
     126                 :          0 :                         cur = cur->prev;
     127         [ #  # ]:          0 :                 } while (cur != unit);
     128                 :            : 
     129         [ #  # ]:          0 :                 if (found) {
     130                 :            :                         /* Assume processed */
     131                 :          0 :                         return (NULL);
     132                 :            :                 }
     133                 :          0 :         }
     134                 :            : 
     135   [ +  -  +  -  :        456 :         if ((it = pkgdb_repo_query(universe->j->db, uid, MATCH_EXACT,
                   +  - ]
     136                 :        304 :                 universe->j->reponame)) == NULL)
     137                 :          0 :                 return (NULL);
     138                 :            : 
     139         [ +  + ]:        356 :         while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {
     140         [ +  + ]:        204 :                 if (result == NULL)
     141                 :        136 :                         result = xcalloc(1, sizeof(pkg_chain_t));
     142   [ +  +  -  + ]:        204 :                 kv_prepend(typeof(pkg), *result, pkg);
     143                 :        204 :                 pkg = NULL;
     144                 :            :         }
     145                 :            : 
     146                 :        152 :         pkgdb_it_free(it);
     147                 :            : 
     148                 :        152 :         return (result);
     149                 :        152 : }
     150                 :            : 
     151                 :            : /**
     152                 :            :  * Check whether a package is in the universe already or add it
     153                 :            :  * @return item or NULL
     154                 :            :  */
     155                 :            : int
     156                 :       1708 : pkg_jobs_universe_add_pkg(struct pkg_jobs_universe *universe, struct pkg *pkg,
     157                 :            :                 bool force __unused, struct pkg_job_universe_item **found)
     158                 :            : {
     159                 :       1708 :         struct pkg_job_universe_item *item, *seen, *tmp = NULL;
     160                 :            : 
     161                 :       1708 :         pkg_validate(pkg, universe->j->db);
     162                 :            : 
     163         [ +  + ]:       1708 :         if (pkg->digest == NULL) {
     164                 :          4 :                 pkg_debug(3, "no digest found for package %s (%s-%s)",
     165                 :          4 :                     pkg->uid, pkg->name, pkg->version);
     166         [ -  + ]:          4 :                 if (pkg_checksum_calculate(pkg, universe->j->db, false, true, false) != EPKG_OK) {
     167                 :          0 :                         *found = NULL;
     168                 :          0 :                         return (EPKG_FATAL);
     169                 :            :                 }
     170                 :          4 :         }
     171                 :            : 
     172                 :       1708 :         seen = pkghash_get_value(universe->seen, pkg->digest);
     173         [ +  + ]:       1708 :         if (seen) {
     174                 :        660 :                 bool same_package = false;
     175                 :            : 
     176         [ +  + ]:        776 :                 DL_FOREACH(seen, tmp) {
     177   [ +  +  +  +  :        714 :                         if (tmp->pkg == pkg || (tmp->pkg->type == pkg->type &&
                   +  + ]
     178                 :         61 :                             strcmp(tmp->pkg->digest, pkg->digest) == 0)) {
     179         [ +  + ]:        622 :                                 if (tmp->pkg->reponame != NULL) {
     180         [ +  + ]:        369 :                                         if (strcmp(tmp->pkg->reponame, pkg->reponame) == 0) {
     181                 :        345 :                                                 same_package = true;
     182                 :        345 :                                                 break;
     183                 :            :                                         }
     184                 :         24 :                                 } else {
     185                 :        253 :                                         same_package = true;
     186                 :        253 :                                         break;
     187                 :            :                                 }
     188                 :         24 :                         }
     189                 :        116 :                 }
     190                 :            : 
     191         [ +  + ]:        660 :                 if (same_package) {
     192         [ +  + ]:        598 :                         if (found != NULL) {
     193                 :        593 :                                 *found = seen;
     194                 :        593 :                         }
     195                 :            : 
     196                 :        598 :                         return (EPKG_END);
     197                 :            :                 }
     198                 :         62 :         }
     199                 :            : 
     200         [ -  + ]:       1110 :         if (pkg_is_locked(pkg)) {
     201                 :          0 :                 return (EPKG_LOCKED);
     202                 :            :         }
     203                 :            : 
     204                 :       1110 :         pkg_debug(2, "universe: add new %s pkg: %s, (%s-%s:%s)",
     205                 :       1110 :             (pkg->type == PKG_INSTALLED ? "local" : "remote"), pkg->uid,
     206                 :       1110 :             pkg->name, pkg->version, pkg->digest);
     207                 :            : 
     208                 :       1110 :         item = xcalloc(1, sizeof (struct pkg_job_universe_item));
     209                 :       1110 :         item->pkg = pkg;
     210                 :            : 
     211                 :       1110 :         tmp = pkghash_get_value(universe->items, pkg->uid);
     212         [ +  + ]:       1110 :         if (tmp == NULL) {
     213   [ +  +  -  + ]:       1089 :                 pkghash_safe_add(universe->items, pkg->uid, item, NULL);
     214                 :        845 :                 item->inhash = true;
     215                 :        845 :         }
     216                 :            : 
     217         [ +  + ]:       1110 :         DL_APPEND(tmp, item);
     218                 :            : 
     219         [ +  + ]:       1110 :         if (seen == NULL)
     220   [ +  +  -  + ]:       1495 :                 pkghash_safe_add(universe->seen, item->pkg->digest, item, NULL);
     221                 :            : 
     222                 :       1110 :         universe->nitems++;
     223                 :            : 
     224         [ +  + ]:       1110 :         if (found != NULL)
     225                 :        541 :                 *found = item;
     226                 :            : 
     227                 :       1110 :         return (EPKG_OK);
     228                 :       1708 : }
     229                 :            : 
     230                 :            : #define DEPS_FLAG_REVERSE 0x1 << 1
     231                 :            : #define DEPS_FLAG_MIRROR 0x1 << 2
     232                 :            : #define DEPS_FLAG_FORCE_LOCAL 0x1 << 3
     233                 :            : #define DEPS_FLAG_FORCE_MISSING 0x1 << 4
     234                 :            : #define DEPS_FLAG_FORCE_UPGRADE 0x1 << 5
     235                 :            : 
     236                 :            : static int
     237                 :       1541 : pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,
     238                 :            :         struct pkg *pkg, unsigned flags)
     239                 :            : {
     240                 :       1541 :         struct pkg_dep *d = NULL;
     241                 :            :         int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
     242                 :            :         int rc;
     243                 :            :         struct pkg_job_universe_item *unit;
     244                 :            :         struct pkg *npkg, *rpkg, *lpkg;
     245                 :       1541 :         pkg_chain_t *rpkgs = NULL;
     246                 :       1541 :         bool found = false;
     247                 :            : 
     248                 :       1541 :         rpkg = NULL;
     249                 :            : 
     250         [ +  + ]:       1541 :         if (flags & DEPS_FLAG_REVERSE) {
     251                 :        860 :                 pkg_debug(4, "Processing rdeps for %s (%s)", pkg->uid, pkg->type == PKG_INSTALLED ? "installed" : "remote");
     252         [ +  + ]:        860 :                 if (pkg->type != PKG_INSTALLED) {
     253                 :        593 :                         lpkg = pkg_jobs_universe_get_local(universe, pkg->uid, 0);
     254   [ +  +  -  + ]:        593 :                         if (lpkg != NULL && lpkg != pkg)
     255                 :        187 :                                 return (pkg_jobs_universe_process_deps(universe, lpkg, flags));
     256                 :        406 :                 }
     257                 :        673 :                 deps_func = pkg_rdeps;
     258                 :        673 :         }
     259                 :            :         else {
     260                 :        681 :                 pkg_debug(4, "Processing deps for %s", pkg->uid);
     261                 :        681 :                 deps_func = pkg_deps;
     262                 :            :         }
     263                 :            : 
     264         [ +  + ]:       1710 :         while (deps_func(pkg, &d) == EPKG_OK) {
     265                 :        364 :                 pkg_debug(4, "Processing *deps for %s: %s", pkg->uid, d->uid);
     266         [ +  + ]:        364 :                 if (pkghash_get(universe->items, d->uid) != NULL)
     267                 :        212 :                         continue;
     268                 :            : 
     269                 :        152 :                 rpkgs = NULL;
     270                 :        152 :                 npkg = NULL;
     271         [ +  + ]:        152 :                 if (!(flags & DEPS_FLAG_MIRROR)) {
     272                 :        148 :                         npkg = pkg_jobs_universe_get_local(universe, d->uid, 0);
     273                 :        148 :                 }
     274                 :            : 
     275         [ -  + ]:        152 :                 if (!(flags & DEPS_FLAG_FORCE_LOCAL)) {
     276                 :            : 
     277                 :            :                         /* Check for remote dependencies */
     278                 :        152 :                         rpkgs = pkg_jobs_universe_get_remote(universe, d->uid, 0);
     279                 :        152 :                 }
     280                 :            : 
     281   [ +  +  +  + ]:        152 :                 if (npkg == NULL && rpkgs == NULL) {
     282                 :          8 :                         pkg_emit_error("%s has a missing dependency: %s",
     283                 :          8 :                                 pkg->name, d->name);
     284                 :            : 
     285         [ -  + ]:          8 :                         if (flags & DEPS_FLAG_FORCE_MISSING) {
     286                 :          0 :                                 continue;
     287                 :            :                         }
     288                 :            : 
     289                 :          8 :                         return (EPKG_FATAL);
     290                 :            :                 }
     291                 :            : 
     292         [ +  + ]:        144 :                 if (npkg != NULL) {
     293         [ +  - ]:         40 :                         if (pkg_jobs_universe_process_item(universe, npkg, &unit) != EPKG_OK) {
     294                 :          0 :                                 continue;
     295                 :            :                         }
     296                 :         40 :                 }
     297                 :            : 
     298         [ +  + ]:        144 :                 if (rpkgs == NULL)
     299                 :          8 :                         continue;
     300                 :            :                 /*
     301                 :            :                  * When processing deps, we should first try to select a dependency
     302                 :            :                  * from the same repo.
     303                 :            :                  * Otherwise, we would have ping-pong of dependencies instead of
     304                 :            :                  * the situation when this behaviour is handled by
     305                 :            :                  * CONSERVATIVE_UPGRADES.
     306                 :            :                  *
     307                 :            :                  * Important notes here:
     308                 :            :                  * 1. We are looking for packages that are dependencies of a package
     309                 :            :                  * `pkg`
     310                 :            :                  * 2. Now if `pkg` belongs to repo `r` and `rpkg` belongs to repo
     311                 :            :                  * `r` then we just select it.
     312                 :            :                  * 3. If `rpkg` is not found in `r` we just scan all packages
     313                 :            :                  */
     314                 :            : 
     315                 :            :                 /*
     316                 :            :                  * XXX: this is the proper place to expand flexible dependencies
     317                 :            :                  */
     318                 :            : 
     319                 :        136 :                 found = false;
     320                 :            :                 /* Iteration one */
     321         [ +  + ]:        180 :                 for (int i = 0; i < kv_size(*rpkgs); i++) {
     322                 :        160 :                         rpkg = kv_A(*rpkgs, i);
     323                 :            : 
     324   [ +  +  +  -  :        160 :                         if (pkg->reponame && rpkg->reponame &&
                   +  + ]
     325                 :        128 :                                         strcmp (pkg->reponame, rpkg->reponame) == 0) {
     326                 :        116 :                                 found = true;
     327                 :        116 :                                 break;
     328                 :            :                         }
     329                 :         44 :                 }
     330                 :            : 
     331                 :            :                 /* Fallback if a dependency is not found in the same repo */
     332         [ +  + ]:        136 :                 if (!found) {
     333         [ +  + ]:         52 :                         for (int i = 0; i < kv_size(*rpkgs); i++) {
     334                 :         32 :                                 rpkg = kv_A(*rpkgs, i);
     335                 :            : 
     336         [ -  + ]:         32 :                                 if (npkg != NULL) {
     337                 :            :                                         /* Set reason for upgrades */
     338         [ +  + ]:         32 :                                         if (!pkg_jobs_need_upgrade(rpkg, npkg))
     339                 :         24 :                                                 continue;
     340                 :            :                                         /* Save automatic flag */
     341                 :          8 :                                         rpkg->automatic = npkg->automatic;
     342                 :          8 :                                 }
     343                 :            : 
     344                 :          8 :                                 rc = pkg_jobs_universe_process_item(universe, rpkg, NULL);
     345                 :            : 
     346                 :            :                                 /* Special case if we cannot find any package */
     347   [ -  +  #  # ]:          8 :                                 if (npkg == NULL && rc != EPKG_OK) {
     348                 :          0 :                                         kv_destroy(*rpkgs);
     349                 :          0 :                                         free(rpkgs);
     350                 :          0 :                                         return (rc);
     351                 :            :                                 }
     352                 :          8 :                         }
     353                 :         20 :                 }
     354                 :            :                 else {
     355         [ +  - ]:        116 :                         assert (rpkg != NULL);
     356                 :            : 
     357         [ +  + ]:        116 :                         if (npkg != NULL) {
     358                 :            :                                 /* Set reason for upgrades */
     359         [ +  + ]:         12 :                                 if (!pkg_jobs_need_upgrade(rpkg, npkg))
     360                 :          8 :                                         continue;
     361                 :            :                                 /* Save automatic flag */
     362                 :          4 :                                 rpkg->automatic = npkg->automatic;
     363                 :          4 :                         }
     364                 :            : 
     365                 :        108 :                         rc = pkg_jobs_universe_process_item(universe, rpkg, NULL);
     366   [ +  +  +  - ]:        108 :                         if (npkg == NULL && rc != EPKG_OK) {
     367                 :          0 :                                 kv_destroy(*rpkgs);
     368                 :          0 :                                 free(rpkgs);
     369                 :          0 :                                 return (rc);
     370                 :            :                         }
     371                 :            :                 }
     372                 :            : 
     373                 :        128 :                 kv_destroy(*rpkgs);
     374                 :        128 :                 free(rpkgs);
     375                 :            :         }
     376                 :            : 
     377                 :       1346 :         return (EPKG_OK);
     378                 :       1541 : }
     379                 :            : 
     380                 :            : static int
     381                 :         48 : pkg_jobs_universe_handle_provide(struct pkg_jobs_universe *universe,
     382                 :            :     struct pkgdb_it *it, const char *name, bool is_shlib, struct pkg *parent __unused)
     383                 :            : {
     384                 :            :         struct pkg_job_universe_item *unit;
     385                 :            :         struct pkg_job_provide *pr, *prhead;
     386                 :            :         struct pkg *npkg, *rpkg;
     387                 :            :         int rc;
     388                 :         48 :         unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
     389                 :            :                                 PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
     390                 :            :                                 PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
     391                 :            :                                 PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
     392                 :            : 
     393                 :         48 :         rpkg = NULL;
     394                 :            : 
     395                 :         48 :         prhead = pkghash_get_value(universe->provides, name);
     396         [ +  + ]:         72 :         while (pkgdb_it_next(it, &rpkg, flags) == EPKG_OK) {
     397                 :            :                 /* Check for local packages */
     398         [ +  + ]:         24 :                 if ((unit = pkghash_get_value(universe->items, rpkg->uid)) != NULL) {
     399                 :            :                         /* Remote provide is newer, so we can add it */
     400   [ -  +  -  + ]:         32 :                         if (pkg_jobs_universe_process_item(universe, rpkg,
     401                 :         16 :                             &unit) != EPKG_OK) {
     402                 :          0 :                                 continue;
     403                 :            :                         }
     404                 :            : 
     405                 :         16 :                         rpkg = NULL;
     406                 :         16 :                 }
     407                 :            :                 else {
     408                 :            :                         /* Maybe local package has just been not added */
     409                 :          8 :                         npkg = pkg_jobs_universe_get_local(universe, rpkg->uid, 0);
     410         [ +  - ]:          8 :                         if (npkg != NULL) {
     411   [ #  #  #  # ]:          0 :                                 if (pkg_jobs_universe_process_item(universe, npkg,
     412                 :          0 :                                                 &unit) != EPKG_OK) {
     413                 :          0 :                                         return (EPKG_FATAL);
     414                 :            :                                 }
     415   [ #  #  #  # ]:          0 :                                 if (pkg_jobs_universe_process_item(universe, rpkg,
     416                 :          0 :                                                 &unit) != EPKG_OK) {
     417                 :          0 :                                         continue;
     418                 :            :                                 }
     419         [ #  # ]:          0 :                                 if (unit != NULL)
     420                 :          0 :                                         rpkg = NULL;
     421                 :          0 :                         }
     422                 :            :                 }
     423                 :            : 
     424                 :            :                 /* Skip seen packages */
     425         [ +  + ]:         24 :                 if (unit == NULL) {
     426         [ +  - ]:          8 :                         if (rpkg->digest == NULL) {
     427                 :          0 :                                 pkg_debug(3, "no digest found for package %s", rpkg->uid);
     428   [ #  #  #  #  :          0 :                                 if (pkg_checksum_calculate(rpkg,
                   #  # ]
     429                 :          0 :                                     universe->j->db, false, true, false) != EPKG_OK) {
     430                 :          0 :                                         return (EPKG_FATAL);
     431                 :            :                                 }
     432                 :          0 :                         }
     433                 :          8 :                         rc = pkg_jobs_universe_process_item(universe, rpkg,
     434                 :            :                                         &unit);
     435                 :            : 
     436         [ +  - ]:          8 :                         if (rc != EPKG_OK) {
     437                 :          0 :                                 return (rc);
     438                 :            :                         }
     439                 :            : 
     440                 :            :                         /* Reset package to avoid freeing */
     441                 :          8 :                         rpkg = NULL;
     442                 :          8 :                 }
     443                 :            : 
     444                 :         24 :                 pr = xcalloc (1, sizeof (*pr));
     445                 :         24 :                 pr->un = unit;
     446                 :         24 :                 pr->provide = name;
     447                 :         24 :                 pr->is_shlib = is_shlib;
     448                 :            : 
     449         [ -  + ]:         24 :                 if (prhead == NULL) {
     450         [ -  + ]:         24 :                         DL_APPEND(prhead, pr);
     451   [ +  +  -  + ]:         28 :                         pkghash_safe_add(universe->provides, pr->provide,
     452                 :            :                             prhead, NULL);
     453                 :         24 :                         pkg_debug (4, "universe: add new provide %s-%s(%s) for require %s",
     454                 :         24 :                                         pr->un->pkg->name, pr->un->pkg->version,
     455                 :         24 :                                         pr->un->pkg->type == PKG_INSTALLED ? "l" : "r",
     456                 :         24 :                                         pr->provide);
     457                 :         24 :                 } else {
     458         [ #  # ]:          0 :                         DL_APPEND(prhead, pr);
     459                 :          0 :                         pkg_debug (4, "universe: append provide %s-%s(%s) for require %s",
     460                 :          0 :                                         pr->un->pkg->name, pr->un->pkg->version,
     461                 :          0 :                                         pr->un->pkg->type == PKG_INSTALLED ? "l" : "r",
     462                 :          0 :                                         pr->provide);
     463                 :            :                 }
     464                 :            :         }
     465                 :            : 
     466                 :         48 :         return (EPKG_OK);
     467                 :         48 : }
     468                 :            : 
     469                 :            : static int
     470                 :        673 : pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
     471                 :            :         struct pkg *pkg)
     472                 :            : {
     473                 :            :         struct pkgdb_it *it;
     474                 :            :         int rc;
     475                 :            :         pkghash_it hit;
     476                 :            : 
     477                 :        673 :         hit = pkghash_iterator(pkg->shlibs_required);
     478         [ +  + ]:        681 :         while (pkghash_next(&hit)) {
     479         [ +  + ]:          8 :                 if (pkghash_get(universe->provides, hit.key) != NULL)
     480                 :          4 :                         continue;
     481                 :            : 
     482                 :            :                 /* Check for local provides */
     483                 :          4 :                 it = pkgdb_query_shlib_provide(universe->j->db, hit.key);
     484         [ -  + ]:          4 :                 if (it != NULL) {
     485                 :          8 :                         rc = pkg_jobs_universe_handle_provide(universe, it,
     486                 :          4 :                             hit.key, true, pkg);
     487                 :          4 :                         pkgdb_it_free(it);
     488                 :            : 
     489         [ +  - ]:          4 :                         if (rc != EPKG_OK) {
     490                 :          0 :                                 pkg_debug(1, "cannot find local packages that provide library %s "
     491                 :            :                                                 "required for %s",
     492                 :          0 :                                                 hit.key, pkg->name);
     493                 :          0 :                         }
     494                 :          4 :                 }
     495                 :            :                 /* Not found, search in the repos */
     496                 :          8 :                 it = pkgdb_repo_shlib_provide(universe->j->db,
     497                 :          4 :                         hit.key, universe->j->reponame);
     498                 :            : 
     499         [ -  + ]:          4 :                 if (it != NULL) {
     500                 :          4 :                         rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, true, pkg);
     501                 :          4 :                         pkgdb_it_free(it);
     502                 :            : 
     503         [ +  - ]:          4 :                         if (rc != EPKG_OK) {
     504                 :          0 :                                 pkg_debug(1, "cannot find remote packages that provide library %s "
     505                 :            :                                                 "required for %s",
     506                 :          0 :                                     hit.key, pkg->name);
     507                 :          0 :                         }
     508                 :          4 :                 }
     509                 :            :         }
     510                 :            : 
     511                 :        673 :         return (EPKG_OK);
     512                 :            : }
     513                 :            : 
     514                 :            : static int
     515                 :        673 : pkg_jobs_universe_process_provides_requires(struct pkg_jobs_universe *universe,
     516                 :            :         struct pkg *pkg)
     517                 :            : {
     518                 :            :         struct pkgdb_it *it;
     519                 :            :         int rc;
     520                 :            :         pkghash_it hit;
     521                 :            : 
     522                 :            : 
     523                 :        673 :         hit = pkghash_iterator(pkg->requires);
     524         [ +  + ]:        713 :         while(pkghash_next(&hit)) {
     525         [ +  + ]:         40 :                 if (pkghash_get(universe->provides, hit.key) != NULL)
     526                 :         20 :                         continue;
     527                 :            : 
     528                 :            :                 /* Check for local provides */
     529                 :         20 :                 it = pkgdb_query_provide(universe->j->db, hit.key);
     530         [ +  - ]:         20 :                 if (it != NULL) {
     531                 :         20 :                         rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, false, pkg);
     532                 :         20 :                         pkgdb_it_free(it);
     533                 :            : 
     534         [ +  - ]:         20 :                         if (rc != EPKG_OK) {
     535                 :          0 :                                 pkg_debug(1, "cannot find local packages that provide %s "
     536                 :            :                                                 "required for %s",
     537                 :          0 :                                                 hit.key, pkg->name);
     538                 :          0 :                         }
     539                 :         20 :                 }
     540                 :            : 
     541                 :            :                 /* Not found, search in the repos */
     542                 :         40 :                 it = pkgdb_repo_provide(universe->j->db,
     543                 :         20 :                         hit.key, universe->j->reponame);
     544                 :            : 
     545         [ -  + ]:         20 :                 if (it != NULL) {
     546                 :         20 :                         rc = pkg_jobs_universe_handle_provide(universe, it, hit.key, false, pkg);
     547                 :         20 :                         pkgdb_it_free(it);
     548                 :            : 
     549         [ +  - ]:         20 :                         if (rc != EPKG_OK) {
     550                 :          0 :                                 pkg_debug(1, "cannot find remote packages that provide %s "
     551                 :            :                                                 "required for %s",
     552                 :          0 :                                     hit.key, pkg->name);
     553                 :          0 :                                 return (rc);
     554                 :            :                         }
     555                 :         20 :                 }
     556                 :            :         }
     557                 :            : 
     558                 :        673 :         return (EPKG_OK);
     559                 :        673 : }
     560                 :            : 
     561                 :            : int
     562                 :        773 : pkg_jobs_universe_process_item(struct pkg_jobs_universe *universe, struct pkg *pkg,
     563                 :            :                 struct pkg_job_universe_item **result)
     564                 :            : {
     565                 :        773 :         unsigned flags = 0, job_flags;
     566                 :        773 :         int rc = EPKG_OK;
     567                 :        773 :         pkg_jobs_t type = universe->j->type;
     568                 :            :         struct pkg_job_universe_item *found;
     569                 :            : 
     570                 :        773 :         pkg_debug(4, "Processing item %s\n", pkg->uid);
     571                 :            : 
     572                 :        773 :         job_flags = universe->j->flags;
     573                 :            : 
     574                 :            :         /*
     575                 :            :          * Add pkg itself. If package is already seen then we check the `processed`
     576                 :            :          * flag that means that we have already tried to check our universe
     577                 :            :          */
     578                 :        773 :         rc = pkg_jobs_universe_add_pkg(universe, pkg, false, &found);
     579         [ -  + ]:        773 :         if (rc == EPKG_CONFLICT)
     580                 :          0 :                 return (rc);
     581                 :            : 
     582         [ +  + ]:        773 :         if (result)
     583                 :        112 :                 *result = found;
     584                 :            : 
     585         [ +  + ]:        773 :         if (rc == EPKG_END) {
     586         [ +  + ]:        593 :                 if (found->processed)
     587                 :         92 :                         return (EPKG_OK);
     588                 :        501 :         }
     589         [ -  + ]:        180 :         else if (rc != EPKG_OK) {
     590                 :          0 :                 return (rc);
     591                 :            :         }
     592                 :            : 
     593                 :        681 :         found->processed = true;
     594                 :            : 
     595                 :            :         /* Convert jobs flags to dependency logical flags */
     596         [ +  - ]:        681 :         if (job_flags & PKG_FLAG_FORCE_MISSING)
     597                 :          0 :                 flags |= DEPS_FLAG_FORCE_MISSING;
     598                 :            : 
     599   [ +  -  +  -  :        681 :         switch(type) {
                      - ]
     600                 :            :         case PKG_JOBS_FETCH:
     601         [ -  + ]:          4 :                 if (job_flags & PKG_FLAG_RECURSIVE) {
     602                 :          4 :                         flags |= DEPS_FLAG_MIRROR;
     603                 :            :                         /* For fetch jobs we worry about depends only */
     604                 :          4 :                         rc = pkg_jobs_universe_process_deps(universe, pkg, flags);
     605                 :          4 :                 }
     606                 :          4 :                 break;
     607                 :            :         case PKG_JOBS_INSTALL:
     608                 :            :         case PKG_JOBS_UPGRADE:
     609                 :            :                 /* Handle depends */
     610                 :        677 :                 rc = pkg_jobs_universe_process_deps(universe, pkg, flags);
     611         [ +  + ]:        677 :                 if (rc != EPKG_OK)
     612                 :          4 :                         return (rc);
     613                 :            :                 /* Handle reverse depends */
     614                 :       1346 :                 rc = pkg_jobs_universe_process_deps(universe, pkg,
     615                 :        673 :                         flags|DEPS_FLAG_REVERSE);
     616         [ -  + ]:        673 :                 if (rc != EPKG_OK)
     617                 :          0 :                                 return (rc);
     618                 :            :                 /* Provides/requires */
     619                 :        673 :                 rc = pkg_jobs_universe_process_shlibs(universe, pkg);
     620         [ -  + ]:        673 :                 if (rc != EPKG_OK)
     621                 :          0 :                         return (rc);
     622                 :        673 :                 rc = pkg_jobs_universe_process_provides_requires(universe, pkg);
     623         [ +  - ]:        673 :                 if (rc != EPKG_OK)
     624                 :          0 :                         return (rc);
     625                 :        673 :                 break;
     626                 :            :         case PKG_JOBS_AUTOREMOVE:
     627                 :            :                 /* XXX */
     628                 :          0 :                 break;
     629                 :            :         case PKG_JOBS_DEINSTALL:
     630                 :            :                 /* For delete jobs we worry only about local reverse deps */
     631                 :          0 :                 flags |= DEPS_FLAG_REVERSE|DEPS_FLAG_FORCE_LOCAL;
     632         [ #  # ]:          0 :                 if (job_flags & PKG_FLAG_RECURSIVE)
     633                 :          0 :                         rc = pkg_jobs_universe_process_deps(universe, pkg, flags);
     634                 :          0 :                 break;
     635                 :            :         }
     636                 :            : 
     637                 :        677 :         return (rc);
     638                 :        773 : }
     639                 :            : 
     640                 :            : int
     641                 :        545 : pkg_jobs_universe_process(struct pkg_jobs_universe *universe,
     642                 :            :         struct pkg *pkg)
     643                 :            : {
     644                 :        545 :         return (pkg_jobs_universe_process_item(universe, pkg, NULL));
     645                 :            : }
     646                 :            : 
     647                 :            : #define RECURSION_LIMIT 1024
     648                 :            : 
     649                 :            : static void
     650                 :        894 : pkg_jobs_update_universe_item_priority(struct pkg_jobs_universe *universe,
     651                 :            :                 struct pkg_job_universe_item *item, int priority,
     652                 :            :                 enum pkg_priority_update_type type)
     653                 :            : {
     654                 :        894 :         struct pkg_dep *d = NULL;
     655                 :        894 :         struct pkg_conflict *c = NULL;
     656                 :            :         struct pkg_job_universe_item *found, *cur, *it;
     657                 :            :         const char *is_local;
     658                 :            :         int maxpri;
     659                 :            : 
     660                 :            :         int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
     661                 :            :         int (*rdeps_func)(const struct pkg *pkg, struct pkg_dep **d);
     662                 :            : 
     663         [ -  + ]:        894 :         if (priority > RECURSION_LIMIT) {
     664                 :          0 :                 pkg_debug(1, "recursion limit has been reached, something is bad"
     665                 :            :                                         " with dependencies/conflicts graph");
     666                 :          0 :                 return;
     667                 :            :         }
     668         [ +  - ]:        894 :         else if (priority + 10 > RECURSION_LIMIT) {
     669                 :          0 :                 pkg_debug(2, "approaching recursion limit at %d, while processing of"
     670                 :          0 :                     " package %s", priority, item->pkg->uid);
     671                 :          0 :         }
     672                 :            : 
     673         [ +  + ]:       1897 :         LL_FOREACH(item, it) {
     674   [ +  +  +  + ]:       1742 :                 if ((item->next != NULL || item->prev != NULL) &&
     675         [ +  + ]:       1023 :                     it->pkg->type != PKG_INSTALLED &&
     676         [ +  + ]:        763 :                     (type == PKG_PRIORITY_UPDATE_CONFLICT ||
     677                 :        719 :                      type == PKG_PRIORITY_UPDATE_DELETE)) {
     678                 :            :                         /*
     679                 :            :                          * We do not update priority of a remote part of conflict, as we know
     680                 :            :                          * that remote packages should not contain conflicts (they should be
     681                 :            :                          * resolved in request prior to calling of this function)
     682                 :            :                          */
     683                 :         72 :                         pkg_debug(4, "skip update priority for %s-%s",
     684                 :         72 :                             it->pkg->uid, it->pkg->digest);
     685                 :         72 :                         continue;
     686                 :            :                 }
     687         [ -  + ]:        951 :                 if (it->priority > priority)
     688                 :          0 :                         continue;
     689                 :            : 
     690                 :        951 :                 is_local = it->pkg->type == PKG_INSTALLED ? "local" : "remote";
     691                 :        951 :                 pkg_debug(2, "universe: update %s priority of %s(%s): %d -> %d, reason: %d",
     692                 :        951 :                     is_local, it->pkg->uid, it->pkg->version, it->priority, priority, type);
     693                 :        951 :                 it->priority = priority;
     694                 :            : 
     695         [ +  + ]:        951 :                 if (type == PKG_PRIORITY_UPDATE_DELETE) {
     696                 :            :                         /*
     697                 :            :                          * For delete requests we inverse deps and rdeps logic
     698                 :            :                          */
     699                 :        176 :                         deps_func = pkg_rdeps;
     700                 :        176 :                         rdeps_func = pkg_deps;
     701                 :        176 :                 }
     702                 :            :                 else {
     703                 :        775 :                         deps_func = pkg_deps;
     704                 :        775 :                         rdeps_func = pkg_rdeps;
     705                 :            :                 }
     706                 :            : 
     707         [ +  + ]:       1163 :                 while (deps_func(it->pkg, &d) == EPKG_OK) {
     708                 :        212 :                         found = pkghash_get_value(universe->items, d->uid);
     709         [ +  - ]:        212 :                         if (found == NULL)
     710                 :          0 :                                 continue;
     711         [ +  + ]:        452 :                         LL_FOREACH(found, cur) {
     712         [ +  + ]:        240 :                                 if (cur->priority < priority + 1)
     713                 :        352 :                                         pkg_jobs_update_universe_item_priority(universe, cur,
     714                 :        176 :                                             priority + 1, type);
     715                 :        240 :                         }
     716                 :            :                 }
     717                 :            : 
     718                 :        951 :                 d = NULL;
     719                 :        951 :                 maxpri = priority;
     720         [ +  + ]:       1102 :                 while (rdeps_func(it->pkg, &d) == EPKG_OK) {
     721                 :        151 :                         found = pkghash_get_value(universe->items, d->uid);
     722         [ +  + ]:        151 :                         if (found == NULL)
     723                 :         43 :                                 continue;
     724         [ +  + ]:        284 :                         LL_FOREACH(found, cur) {
     725         [ +  + ]:        176 :                                 if (cur->priority >= maxpri) {
     726                 :         20 :                                         maxpri = cur->priority + 1;
     727                 :         20 :                                 }
     728                 :        176 :                         }
     729                 :            :                 }
     730         [ +  + ]:        951 :                 if (maxpri != priority) {
     731                 :         40 :                         pkg_jobs_update_universe_item_priority(universe, it,
     732                 :         20 :                                         maxpri, type);
     733                 :         20 :                         return;
     734                 :            :                 }
     735         [ +  + ]:        931 :                 if (it->pkg->type == PKG_INSTALLED)
     736                 :        240 :                         continue;
     737                 :            : 
     738         [ +  + ]:        767 :                 while (pkg_conflicts(it->pkg, &c) == EPKG_OK) {
     739                 :         76 :                         found = pkghash_get_value(universe->items, c->uid);
     740         [ +  + ]:        200 :                         LL_FOREACH(found, cur) {
     741         [ +  + ]:        124 :                                 if (cur->pkg->type != PKG_INSTALLED)
     742                 :         48 :                                         continue;
     743                 :            :                                 /*
     744                 :            :                                  * Move delete requests to be done before installing
     745                 :            :                                  */
     746         [ +  + ]:         76 :                                 if (cur->priority <= it->priority)
     747                 :        112 :                                         pkg_jobs_update_universe_item_priority(universe, cur,
     748                 :         56 :                                             it->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
     749                 :         76 :                         }
     750                 :            :                 }
     751                 :        691 :         }
     752                 :        894 : }
     753                 :            : 
     754                 :            : void
     755                 :          8 : pkg_jobs_update_conflict_priority(struct pkg_jobs_universe *universe,
     756                 :            :         struct pkg_solved *req)
     757                 :            : {
     758                 :          8 :         struct pkg_conflict *c = NULL;
     759                 :          8 :         struct pkg *lp = req->items[1]->pkg;
     760                 :          8 :         struct pkg_job_universe_item *found, *cur, *rit = NULL;
     761                 :            : 
     762         [ +  + ]:         20 :         while (pkg_conflicts(lp, &c) == EPKG_OK) {
     763                 :         12 :                 rit = NULL;
     764                 :         12 :                 found = pkghash_get_value(universe->items, c->uid);
     765         [ +  - ]:         12 :                 assert(found != NULL);
     766                 :            : 
     767         [ -  + ]:         16 :                 LL_FOREACH(found, cur) {
     768         [ +  + ]:         16 :                         if (cur->pkg->type != PKG_INSTALLED) {
     769                 :         12 :                                 rit = cur;
     770                 :         12 :                                 break;
     771                 :            :                         }
     772                 :          4 :                 }
     773                 :            : 
     774         [ +  - ]:         12 :                 assert(rit != NULL);
     775         [ +  - ]:         12 :                 if (rit->priority >= req->items[1]->priority) {
     776                 :          0 :                         pkg_jobs_update_universe_item_priority(universe, req->items[1],
     777                 :          0 :                                         rit->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
     778                 :            :                         /*
     779                 :            :                          * Update priorities for a remote part as well
     780                 :            :                          */
     781                 :          0 :                         pkg_jobs_update_universe_item_priority(universe, req->items[0],
     782                 :          0 :                                         req->items[0]->priority, PKG_PRIORITY_UPDATE_REQUEST);
     783                 :          0 :                 }
     784                 :            :         }
     785                 :          8 : }
     786                 :            : 
     787                 :            : 
     788                 :            : void
     789                 :        642 : pkg_jobs_update_universe_priority(struct pkg_jobs_universe *universe,
     790                 :            :         struct pkg_job_universe_item *it, enum pkg_priority_update_type type)
     791                 :            : {
     792                 :        642 :         pkg_jobs_update_universe_item_priority(universe, it, 0, type);
     793                 :        642 : }
     794                 :            : 
     795                 :            : static void
     796                 :         24 : pkg_jobs_universe_provide_free(struct pkg_job_provide *pr)
     797                 :            : {
     798                 :            :         struct pkg_job_provide *cur, *tmp;
     799                 :            : 
     800   [ +  +  +  + ]:         48 :         DL_FOREACH_SAFE(pr, cur, tmp) {
     801                 :         24 :                 free (cur);
     802                 :         24 :         }
     803                 :         24 : }
     804                 :            : 
     805                 :            : static void
     806                 :          0 : pkg_jobs_universe_replacement_free(struct pkg_job_replace *r)
     807                 :            : {
     808                 :          0 :         free(r->new_uid);
     809                 :          0 :         free(r->old_uid);
     810                 :          0 :         free(r);
     811                 :          0 : }
     812                 :            : 
     813                 :            : void
     814                 :        611 : pkg_jobs_universe_free(struct pkg_jobs_universe *universe)
     815                 :            : {
     816                 :            :         struct pkg_job_universe_item *cur, *curtmp;
     817                 :            :         pkghash_it it;
     818                 :            : 
     819                 :        611 :         it = pkghash_iterator(universe->items);
     820         [ +  + ]:       1456 :         while (pkghash_next(&it)) {
     821   [ +  +  +  + ]:       1955 :                 LL_FOREACH_SAFE(it.value, cur, curtmp) {
     822                 :       1110 :                         pkg_free(cur->pkg);
     823                 :       1110 :                         free(cur);
     824                 :       1110 :                 }
     825                 :            :         }
     826                 :        611 :         pkghash_destroy(universe->items);
     827                 :        611 :         universe->items = NULL;
     828                 :        611 :         pkghash_destroy(universe->seen);
     829                 :        611 :         universe->seen = NULL;
     830                 :        611 :         it = pkghash_iterator(universe->provides);
     831         [ +  + ]:        635 :         while (pkghash_next(&it))
     832                 :         24 :                 pkg_jobs_universe_provide_free(it.value);
     833                 :        611 :         pkghash_destroy(universe->provides);
     834   [ +  -  +  -  :        611 :         LL_FREE(universe->uid_replaces, pkg_jobs_universe_replacement_free);
          #  #  #  #  #  
                #  #  # ]
     835                 :        611 : }
     836                 :            : 
     837                 :            : struct pkg_jobs_universe *
     838                 :        611 : pkg_jobs_universe_new(struct pkg_jobs *j)
     839                 :            : {
     840                 :            :         struct pkg_jobs_universe *universe;
     841                 :            : 
     842                 :        611 :         universe = xcalloc(1, sizeof(struct pkg_jobs_universe));
     843                 :        611 :         universe->j = j;
     844                 :            : 
     845                 :        611 :         return (universe);
     846                 :            : }
     847                 :            : 
     848                 :            : struct pkg_job_universe_item *
     849                 :         41 : pkg_jobs_universe_find(struct pkg_jobs_universe *universe, const char *uid)
     850                 :            : {
     851                 :         41 :         return (pkghash_get_value(universe->items, uid));
     852                 :            : }
     853                 :            : 
     854                 :            : void
     855                 :          0 : pkg_jobs_universe_change_uid(struct pkg_jobs_universe *universe,
     856                 :            :         struct pkg_job_universe_item *unit,
     857                 :            :         const char *new_uid, bool update_rdeps)
     858                 :            : {
     859                 :          0 :         struct pkg_dep *rd = NULL, *d = NULL;
     860                 :            :         struct pkg_job_universe_item *found, *tmp;
     861                 :            : 
     862                 :            :         struct pkg *lp;
     863                 :            :         struct pkg_job_replace *replacement;
     864                 :            : 
     865         [ #  # ]:          0 :         if (update_rdeps) {
     866                 :            :                 /* For all rdeps update deps accordingly */
     867         [ #  # ]:          0 :                 while (pkg_rdeps(unit->pkg, &rd) == EPKG_OK) {
     868                 :          0 :                         found = pkg_jobs_universe_find(universe, rd->uid);
     869         [ #  # ]:          0 :                         if (found == NULL) {
     870                 :          0 :                                 lp = pkg_jobs_universe_get_local(universe, rd->uid, 0);
     871                 :            :                                 /* XXX */
     872         [ #  # ]:          0 :                                 assert(lp != NULL);
     873                 :          0 :                                 pkg_jobs_universe_process_item(universe, lp, &found);
     874                 :          0 :                         }
     875                 :            : 
     876         [ #  # ]:          0 :                         if (found != NULL) {
     877         [ #  # ]:          0 :                                 while (pkg_deps(found->pkg, &d) == EPKG_OK) {
     878         [ #  # ]:          0 :                                         if (strcmp(d->uid, unit->pkg->uid) == 0) {
     879                 :          0 :                                                 free(d->uid);
     880                 :          0 :                                                 d->uid = xstrdup(new_uid);
     881                 :          0 :                                         }
     882                 :            :                                 }
     883                 :          0 :                         }
     884                 :            :                 }
     885                 :          0 :         }
     886                 :            : 
     887                 :          0 :         replacement = xcalloc(1, sizeof(*replacement));
     888                 :          0 :         replacement->old_uid = xstrdup(unit->pkg->uid);
     889                 :          0 :         replacement->new_uid = xstrdup(new_uid);
     890                 :          0 :         LL_PREPEND(universe->uid_replaces, replacement);
     891                 :            : 
     892                 :          0 :         tmp = pkghash_delete(universe->items, unit->pkg->uid);
     893         [ #  # ]:          0 :         if (tmp != NULL)
     894                 :          0 :                 tmp->inhash = false;
     895                 :          0 :         free(unit->pkg->uid);
     896                 :          0 :         unit->pkg->uid = xstrdup(new_uid);
     897                 :            : 
     898                 :          0 :         found = pkghash_get_value(universe->items, new_uid);
     899         [ #  # ]:          0 :         if (found != NULL)
     900         [ #  # ]:          0 :                 DL_APPEND(found, unit);
     901                 :            :         else
     902   [ #  #  #  # ]:          0 :                 pkghash_safe_add(universe->items, new_uid, unit, NULL);
     903                 :            : 
     904                 :          0 : }
     905                 :            : 
     906                 :            : static struct pkg_job_universe_item *
     907                 :        261 : pkg_jobs_universe_select_max_ver(struct pkg_job_universe_item *chain)
     908                 :            : {
     909                 :        261 :         struct pkg_job_universe_item *cur, *res = NULL;
     910                 :        261 :         bool found = false;
     911                 :            :         int r;
     912                 :            : 
     913         [ +  + ]:        724 :         LL_FOREACH(chain, cur) {
     914         [ +  + ]:        463 :                 if (cur->pkg->type == PKG_INSTALLED)
     915                 :        133 :                         continue;
     916                 :            : 
     917         [ +  + ]:        330 :                 if (res != NULL) {
     918                 :         93 :                         r = pkg_version_change_between(cur->pkg, res->pkg);
     919         [ -  + ]:         93 :                         if (r == PKG_UPGRADE) {
     920                 :          0 :                                 res = cur;
     921                 :          0 :                                 found = true;
     922                 :          0 :                         }
     923         [ +  + ]:         93 :                         else if (r != PKG_REINSTALL) {
     924                 :            :                                 /*
     925                 :            :                                  * Actually the selected package is newer than some other
     926                 :            :                                  * packages in the chain
     927                 :            :                                  */
     928                 :         77 :                                 found = true;
     929                 :         77 :                         }
     930                 :         93 :                 }
     931                 :            :                 else {
     932                 :        237 :                         res = cur;
     933                 :            :                 }
     934                 :        330 :         }
     935                 :            : 
     936         [ +  + ]:        261 :         return (found ? res : NULL);
     937                 :            : }
     938                 :            : 
     939                 :            : static struct pkg_job_universe_item *
     940                 :        256 : pkg_jobs_universe_select_max_prio(struct pkg_job_universe_item *chain)
     941                 :            : {
     942                 :            :         struct pkg_repo *repo;
     943                 :        256 :         unsigned int max_pri = 0;
     944                 :        256 :         struct pkg_job_universe_item *cur, *res = NULL;
     945                 :            : 
     946         [ +  + ]:        672 :         LL_FOREACH(chain, cur) {
     947         [ +  + ]:        416 :                 if (cur->pkg->type == PKG_INSTALLED)
     948                 :        104 :                         continue;
     949                 :            : 
     950         [ -  + ]:        312 :                 if (cur->pkg->reponame) {
     951                 :        312 :                         repo = pkg_repo_find(cur->pkg->reponame);
     952   [ +  -  +  + ]:        312 :                         if (repo && repo->priority > max_pri) {
     953                 :         24 :                                 res = cur;
     954                 :         24 :                                 max_pri = repo->priority;
     955                 :         24 :                         }
     956                 :        312 :                 }
     957                 :        312 :         }
     958                 :            : 
     959                 :        256 :         return (res);
     960                 :            : }
     961                 :            : 
     962                 :            : static struct pkg_job_universe_item *
     963                 :        164 : pkg_jobs_universe_select_same_repo(struct pkg_job_universe_item *chain,
     964                 :            :         struct pkg_job_universe_item *local, const char *assumed_reponame)
     965                 :            : {
     966                 :        164 :         struct pkg_repo *local_repo = NULL, *repo;
     967                 :        164 :         struct pkg_job_universe_item *cur, *res = NULL;
     968                 :            : 
     969         [ +  - ]:        164 :         if (!local) {
     970                 :            : 
     971         [ #  # ]:          0 :                 if (assumed_reponame) {
     972                 :          0 :                         local_repo = pkg_repo_find(assumed_reponame);
     973                 :          0 :                 }
     974                 :          0 :         }
     975                 :            :         else {
     976         [ -  + ]:        164 :                 if (local->pkg->reponame) {
     977                 :          0 :                         local_repo = pkg_repo_find(local->pkg->reponame);
     978                 :          0 :                 }
     979                 :            :                 else {
     980                 :        164 :                         const char *lrepo = pkg_kv_get(&local->pkg->annotations, "repository");
     981         [ +  + ]:        164 :                         if (lrepo) {
     982                 :         80 :                                 local_repo = pkg_repo_find(lrepo);
     983                 :         80 :                         }
     984                 :            :                 }
     985                 :            :         }
     986                 :            : 
     987         [ +  + ]:        164 :         if (local_repo == NULL) {
     988                 :        124 :                 return (NULL);
     989                 :            :         }
     990                 :            :         else {
     991         [ +  + ]:         80 :                 LL_FOREACH(chain, cur) {
     992         [ +  + ]:         76 :                         if (cur->pkg->type == PKG_INSTALLED)
     993                 :         40 :                                 continue;
     994                 :            : 
     995         [ -  + ]:         36 :                         if (cur->pkg->reponame) {
     996                 :         36 :                                 repo = pkg_repo_find(cur->pkg->reponame);
     997         [ -  + ]:         36 :                                 if (repo == local_repo) {
     998                 :         36 :                                         res = cur;
     999                 :         36 :                                         break;
    1000                 :            :                                 }
    1001                 :          0 :                         }
    1002                 :          0 :                 }
    1003                 :            :         }
    1004                 :            : 
    1005                 :         40 :         return (res);
    1006                 :        164 : }
    1007                 :            : 
    1008                 :            : struct pkg_job_universe_item *
    1009                 :        321 : pkg_jobs_universe_select_candidate(struct pkg_job_universe_item *chain,
    1010                 :            :     struct pkg_job_universe_item *local, bool conservative,
    1011                 :            :     const char *reponame, bool pinning)
    1012                 :            : {
    1013                 :        321 :         struct pkg_job_universe_item *res = NULL;
    1014                 :            : 
    1015         [ +  + ]:        321 :         if (local == NULL) {
    1016                 :            :                 /* New package selection */
    1017         [ +  - ]:        152 :                 if (conservative) {
    1018                 :            :                         /* Check same repo */
    1019   [ -  +  #  # ]:        152 :                         if (reponame && pinning) {
    1020                 :          0 :                                 res =  pkg_jobs_universe_select_same_repo(chain, NULL, reponame);
    1021                 :          0 :                         }
    1022                 :            : 
    1023         [ -  + ]:        152 :                         if (res == NULL) {
    1024                 :            :                                 /* Priority -> version */
    1025                 :        152 :                                 res = pkg_jobs_universe_select_max_prio(chain);
    1026         [ +  + ]:        152 :                                 if (res == NULL) {
    1027                 :        128 :                                         res = pkg_jobs_universe_select_max_ver(chain);
    1028                 :        128 :                                 }
    1029                 :        152 :                         }
    1030                 :        152 :                 }
    1031                 :            :                 else {
    1032   [ #  #  #  # ]:          0 :                         if (reponame && pinning) {
    1033                 :          0 :                                 res =  pkg_jobs_universe_select_same_repo(chain, NULL, reponame);
    1034                 :          0 :                         }
    1035                 :            : 
    1036         [ #  # ]:          0 :                         if (res == NULL) {
    1037                 :            :                                 /* Version -> priority */
    1038                 :          0 :                                 res = pkg_jobs_universe_select_max_ver(chain);
    1039         [ #  # ]:          0 :                                 if (res == NULL) {
    1040                 :          0 :                                         res = pkg_jobs_universe_select_max_prio(chain);
    1041                 :          0 :                                 }
    1042                 :          0 :                         }
    1043                 :            :                 }
    1044                 :        152 :         }
    1045                 :            :         else {
    1046         [ +  + ]:        169 :                 if (conservative) {
    1047                 :            :                         /* same -> prio -> version */
    1048         [ -  + ]:        140 :                         if (pinning)
    1049                 :        140 :                                 res = pkg_jobs_universe_select_same_repo(chain, local, reponame);
    1050         [ +  + ]:        140 :                         if (res == NULL) {
    1051                 :        104 :                                 res = pkg_jobs_universe_select_max_prio(chain);
    1052                 :        104 :                         }
    1053         [ +  + ]:        140 :                         if (res == NULL) {
    1054                 :        104 :                                 res = pkg_jobs_universe_select_max_ver(chain);
    1055                 :        104 :                         }
    1056                 :        140 :                 }
    1057                 :            :                 else {
    1058                 :            :                         /* same -> version -> prio */
    1059         [ +  + ]:         29 :                         if (pinning)
    1060                 :         24 :                                 res = pkg_jobs_universe_select_same_repo(chain, local, reponame);
    1061         [ -  + ]:         29 :                         if (res == NULL) {
    1062                 :         29 :                                 res = pkg_jobs_universe_select_max_ver(chain);
    1063                 :         29 :                         }
    1064         [ +  - ]:         29 :                         if (res == NULL) {
    1065                 :          0 :                                 res = pkg_jobs_universe_select_max_prio(chain);
    1066                 :          0 :                         }
    1067                 :            :                 }
    1068                 :            :         }
    1069                 :            : 
    1070                 :            :         /* Fallback to any */
    1071         [ +  + ]:        321 :         return (res != NULL ? res : chain);
    1072                 :            : }
    1073                 :            : 
    1074                 :            : void
    1075                 :       1088 : pkg_jobs_universe_process_upgrade_chains(struct pkg_jobs *j)
    1076                 :            : {
    1077                 :            :         struct pkg_job_universe_item *unit, *cur, *local;
    1078                 :            :         struct pkg_job_request *req;
    1079                 :            :         struct pkg_job_request_item *rit, *rtmp;
    1080                 :            :         pkghash_it it;
    1081                 :            : 
    1082                 :       1088 :         it = pkghash_iterator(j->universe->items);
    1083         [ +  + ]:       2600 :         while (pkghash_next(&it)) {
    1084                 :       1512 :                 unsigned vercnt = 0;
    1085                 :       1512 :                 unit = (struct pkg_job_universe_item *)it.value;
    1086                 :            : 
    1087                 :       1512 :                 req = pkghash_get_value(j->request_add, unit->pkg->uid);
    1088         [ +  + ]:       1512 :                 if (req == NULL) {
    1089                 :            :                         /* Not obviously requested */
    1090                 :        493 :                         continue;
    1091                 :            :                 }
    1092                 :            : 
    1093                 :       1019 :                 local = NULL;
    1094         [ +  + ]:       2590 :                 LL_FOREACH(unit, cur) {
    1095         [ +  + ]:       1571 :                         if (cur->pkg->type == PKG_INSTALLED)
    1096                 :        407 :                                 local = cur;
    1097                 :       1571 :                         vercnt ++;
    1098                 :       1571 :                 }
    1099                 :            : 
    1100   [ +  +  +  - ]:       1019 :                 if (local != NULL && local->pkg->locked) {
    1101                 :          0 :                         pkg_debug(1, "removing %s from the request as it is locked",
    1102                 :          0 :                                 cur->pkg->uid);
    1103                 :          0 :                         pkghash_del(j->request_add, req->item->pkg->uid);
    1104                 :          0 :                         pkg_jobs_request_free(req);
    1105                 :          0 :                         continue;
    1106                 :            :                 }
    1107                 :            : 
    1108         [ +  + ]:       1019 :                 if (vercnt <= 1)
    1109                 :        572 :                         continue;
    1110                 :            : 
    1111                 :            :                 /*
    1112                 :            :                  * Here we have more than one upgrade candidate,
    1113                 :            :                  * if local == NULL, then we have two remote repos,
    1114                 :            :                  * if local != NULL, then we have unspecified upgrade path
    1115                 :            :                  */
    1116                 :            : 
    1117   [ +  +  +  + ]:        447 :                 if ((local == NULL && vercnt > 1) || (vercnt > 2)) {
    1118                 :            :                         /* Select the most recent or one of packages */
    1119                 :            :                         struct pkg_job_universe_item *selected;
    1120                 :            : 
    1121                 :        290 :                         selected = pkg_jobs_universe_select_candidate(unit, local,
    1122                 :        145 :                                 j->conservative, NULL, j->pinning);
    1123                 :            :                         /*
    1124                 :            :                          * Now remove all requests but selected from the requested
    1125                 :            :                          * candidates
    1126                 :            :                          */
    1127         [ +  - ]:        145 :                         assert(selected != NULL);
    1128                 :        145 :                         pkghash_del(j->request_add, req->item->pkg->uid);
    1129                 :            : 
    1130                 :            :                         /*
    1131                 :            :                          * We also check if the selected package has different digest,
    1132                 :            :                          * and if it has the same digest we proceed only if we have a
    1133                 :            :                          * forced job
    1134                 :            :                          */
    1135   [ +  +  +  + ]:        145 :                         if (local != NULL && strcmp(local->pkg->digest,
    1136   [ +  +  +  + ]:        210 :                                 selected->pkg->digest) == 0 &&
    1137                 :         20 :                                 (j->flags & PKG_FLAG_FORCE) == 0) {
    1138                 :          4 :                                 pkg_debug (1, "removing %s from the request as it is the "
    1139                 :          4 :                                                                 "same as local", selected->pkg->uid);
    1140                 :          4 :                                 continue;
    1141                 :            :                         }
    1142                 :            : 
    1143         [ +  + ]:        524 :                         LL_FOREACH(unit, cur) {
    1144         [ +  + ]:        383 :                                 if (cur == selected)
    1145                 :        141 :                                         continue;
    1146                 :            : 
    1147   [ +  +  +  + ]:        902 :                                 DL_FOREACH_SAFE(req->item, rit, rtmp) {
    1148         [ +  + ]:        660 :                                         if (rit->unit == cur) {
    1149   [ +  -  -  +  :        236 :                                                 DL_DELETE(req->item, rit);
             +  +  +  + ]
    1150                 :        118 :                                                 free(rit);
    1151                 :        118 :                                         }
    1152                 :        660 :                                 }
    1153                 :        242 :                         }
    1154         [ +  - ]:        141 :                         if (req->item == NULL) {
    1155                 :          0 :                                 rit = xcalloc(1, sizeof(*rit));
    1156                 :          0 :                                 rit->pkg = selected->pkg;
    1157                 :          0 :                                 rit->unit = selected;
    1158         [ #  # ]:          0 :                                 DL_APPEND(req->item, rit);
    1159                 :          0 :                         }
    1160   [ +  -  +  - ]:        282 :                         pkghash_safe_add(j->request_add, selected->pkg->uid, req, NULL);
    1161                 :        141 :                 }
    1162                 :            :         }
    1163                 :       1088 : }
    1164                 :            : 
    1165                 :            : struct pkg_job_universe_item*
    1166                 :        424 : pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
    1167                 :            :         const char *uid, struct pkg *lp, bool force, const char *version)
    1168                 :            : {
    1169                 :        424 :         struct pkg *pkg = NULL, *selected = lp;
    1170                 :            :         struct pkgdb_it *it;
    1171                 :            :         struct pkg_job_universe_item *unit, *ucur;
    1172                 :        424 :         int flag = PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_OPTIONS|
    1173                 :            :                                         PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
    1174                 :            :                                         PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
    1175                 :            :                                         PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
    1176                 :            :         kvec_t(struct pkg *) candidates;
    1177                 :            : 
    1178                 :        424 :         unit = pkghash_get_value(universe->items, uid);
    1179         [ +  + ]:        424 :         if (unit != NULL) {
    1180                 :            :                 /*
    1181                 :            :                  * If a unit has been found, we have already found the potential
    1182                 :            :                  * upgrade chain for it
    1183                 :            :                  */
    1184         [ +  + ]:        108 :                 if (force) {
    1185                 :            :                         /*
    1186                 :            :                          * We also need to ensure that a chain contains remote packages
    1187                 :            :                          * in case of forced upgrade
    1188                 :            :                          */
    1189         [ +  + ]:         26 :                         DL_FOREACH(unit, ucur) {
    1190         [ +  + ]:         21 :                                 if (ucur->pkg->type != PKG_INSTALLED) {
    1191                 :          8 :                                         return (unit);
    1192                 :            :                                 }
    1193                 :         13 :                         }
    1194                 :          5 :                 }
    1195                 :            :                 else {
    1196                 :         95 :                         return (unit);
    1197                 :            :                 }
    1198                 :          5 :         }
    1199                 :            : 
    1200   [ +  -  +  -  :        963 :         if ((it = pkgdb_repo_query(universe->j->db, uid, MATCH_EXACT,
                   +  - ]
    1201                 :        642 :                 universe->j->reponame)) == NULL)
    1202                 :          0 :                 return (NULL);
    1203                 :            : 
    1204                 :        321 :         kv_init(candidates);
    1205         [ +  + ]:        733 :         while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {
    1206                 :            : 
    1207   [ +  +  +  + ]:        412 :                 if (version != NULL && strcmp(pkg->version, version) != 0)
    1208                 :          8 :                         continue;
    1209                 :            : 
    1210         [ +  + ]:        404 :                 if (force) {
    1211                 :            :                         /* Just add everything */
    1212                 :         25 :                         selected = pkg;
    1213                 :         25 :                 }
    1214                 :            :                 else {
    1215   [ +  +  +  + ]:        636 :                         if (selected == lp &&
    1216         [ +  + ]:        355 :                                         (lp == NULL || pkg_jobs_need_upgrade(pkg, lp)))
    1217                 :        261 :                                 selected = pkg;
    1218         [ +  + ]:        118 :                         else if (pkg_version_change_between(pkg, selected) == PKG_UPGRADE)
    1219                 :          4 :                                 selected = pkg;
    1220                 :            :                 }
    1221   [ +  +  -  + ]:        404 :                 kv_prepend(typeof(pkg), candidates, pkg);
    1222                 :        404 :                 pkg = NULL;
    1223                 :            :         }
    1224                 :            : 
    1225                 :        321 :         pkgdb_it_free(it);
    1226                 :            : 
    1227         [ +  + ]:        321 :         if (lp != NULL) {
    1228                 :            :                 /* Add local package to the universe as well */
    1229                 :        223 :                 pkg_jobs_universe_add_pkg(universe, lp, false, NULL);
    1230                 :        223 :         }
    1231         [ +  + ]:        321 :         if (selected != lp) {
    1232                 :            :                 /* We need to add the whole chain of upgrade candidates */
    1233         [ +  + ]:        629 :                 for (int i = 0; i < kv_size(candidates); i++) {
    1234                 :        351 :                         pkg_jobs_universe_add_pkg(universe, kv_A(candidates, i), force, NULL);
    1235                 :        351 :                 }
    1236                 :        278 :         }
    1237                 :            :         else {
    1238         [ +  + ]:         96 :                 while (kv_size(candidates) > 0)
    1239                 :         53 :                         pkg_free(kv_pop(candidates));
    1240                 :         43 :                 kv_destroy(candidates);
    1241                 :            : 
    1242                 :         43 :                 return (NULL);
    1243                 :            :         }
    1244                 :            : 
    1245                 :        278 :         unit = pkghash_get_value(universe->items, uid);
    1246                 :        278 :         kv_destroy(candidates);
    1247                 :            : 
    1248                 :        278 :         return (unit);
    1249                 :        424 : }

Generated by: LCOV version 1.15