LCOV - code coverage report
Current view: top level - src - search.c (source / functions) Hit Total Coverage
Test: rapport Lines: 99 236 41.9 %
Date: 2021-12-10 16:22:55 Functions: 4 5 80.0 %
Branches: 44 122 36.1 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       5                 :            :  * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
       6                 :            :  * Copyright (c) 2014 Matthew Seaman <matthew@FreeBSD.org>
       7                 :            :  * All rights reserved.
       8                 :            :  * 
       9                 :            :  * Redistribution and use in source and binary forms, with or without
      10                 :            :  * modification, are permitted provided that the following conditions
      11                 :            :  * are met:
      12                 :            :  * 1. Redistributions of source code must retain the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer
      14                 :            :  *    in this position and unchanged.
      15                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      16                 :            :  *    notice, this list of conditions and the following disclaimer in the
      17                 :            :  *    documentation and/or other materials provided with the distribution.
      18                 :            :  * 
      19                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      20                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      21                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      22                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      23                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      24                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      28                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :            :  */
      30                 :            : 
      31                 :            : #include <err.h>
      32                 :            : #include <getopt.h>
      33                 :            : #include <stdio.h>
      34                 :            : #include <stdlib.h>
      35                 :            : #include <string.h>
      36                 :            : #include <unistd.h>
      37                 :            : 
      38                 :            : #include <pkg.h>
      39                 :            : 
      40                 :            : #include "pkgcli.h"
      41                 :            : 
      42                 :            : typedef struct _cliopt {
      43                 :            :         const char *option;
      44                 :            :         char key;
      45                 :            : } cliopt;
      46                 :            : 
      47                 :            : /* an option string should not be a prefix of any other option string */ 
      48                 :            : static const cliopt search_label[] = {
      49                 :            :         { "comment",     'c'  },
      50                 :            :         { "description", 'd'  },
      51                 :            :         { "name",        'n'  },
      52                 :            :         { "origin",      'o'  },
      53                 :            :         { "pkg-name",    'p'  },
      54                 :            :         { NULL,          '\0' },
      55                 :            : };
      56                 :            : 
      57                 :            : static const cliopt modifiers[] = {
      58                 :            :         { "annotations",          'A'  },
      59                 :            :         { "arch",                 'a'  },
      60                 :            :         { "categories",           'C'  },
      61                 :            :         { "comment",              'c'  },
      62                 :            :         { "depends-on",           'd'  },
      63                 :            :         { "description",          'D'  },
      64                 :            :         { "full",                 'f'  },
      65                 :            :         { "licenses",             'l'  },
      66                 :            :         { "maintainer",           'm'  },
      67                 :            :         { "name",                 'n'  },
      68                 :            :         { "options",              'o'  },
      69                 :            :         { "pkg-size",           'P'  },
      70                 :            :         { "prefix",               'p'  },
      71                 :            :         { "repository",           'R'  },
      72                 :            :         { "required-by",          'r'  },
      73                 :            :         { "shared-libs-required", 'B'  },
      74                 :            :         { "shared-libs-provided", 'b'  },
      75                 :            :         { "size",                 's'  },
      76                 :            :         { "url",                  'u'  },
      77                 :            :         { "version",              'v'  },
      78                 :            :         { "www",                  'w'  },
      79                 :            :         { NULL,                   '\0' },
      80                 :            : };      
      81                 :            : 
      82                 :            : static char
      83                 :         16 : match_optarg(const cliopt *optlist, const char *opt)
      84                 :            : {
      85                 :         16 :         int i, matched = -1;
      86                 :         16 :         char key = '\0';
      87                 :            :         size_t optlen;
      88                 :            : 
      89                 :         16 :         optlen = strlen(opt);
      90                 :            : 
      91                 :            :         /* Match any unique prefix from  optlist */
      92         [ +  + ]:        160 :         for (i = 0; optlist[i].option != NULL; i++) {
      93         [ +  + ]:        144 :                 if (strncmp(opt, optlist[i].option, optlen) != 0)
      94                 :        128 :                         continue;
      95         [ -  + ]:         16 :                 if (matched > 0) {
      96                 :          0 :                         warnx("\"%s\" is ambiguous. Was "
      97                 :          0 :                               "\"%s\" or \"%s\" meant?", opt,
      98                 :          0 :                               optlist[matched].option, optlist[i].option);
      99                 :          0 :                         key = '\0';
     100                 :          0 :                         break;
     101                 :            :                 }
     102                 :         16 :                 matched = i;
     103                 :         16 :                 key = optlist[i].key;
     104                 :         16 :         }
     105                 :         16 :         return (key);
     106                 :            : }
     107                 :            : 
     108                 :            : static pkgdb_field
     109                 :         12 : search_label_opt(const char *optionarg)
     110                 :            : {
     111                 :            :         pkgdb_field field;
     112                 :            : 
     113                 :            :         /* label options */
     114   [ +  -  -  +  :         12 :         switch(match_optarg(search_label, optionarg)) {
                   -  - ]
     115                 :            :         case 'o':
     116                 :          8 :                 field = FIELD_ORIGIN;
     117                 :          8 :                 break;
     118                 :            :         case 'n':
     119                 :          4 :                 field = FIELD_NAME;
     120                 :          4 :                 break;
     121                 :            :         case 'p':
     122                 :          0 :                 field = FIELD_NAMEVER;
     123                 :          0 :                 break;
     124                 :            :         case 'c':
     125                 :          0 :                 field = FIELD_COMMENT;
     126                 :          0 :                 break;
     127                 :            :         case 'd':
     128                 :          0 :                 field = FIELD_DESC;
     129                 :          0 :                 break;
     130                 :            :         default:
     131                 :          0 :                 usage_search();
     132                 :          0 :                 errx(EXIT_FAILURE, "Unknown search/label option: %s", optionarg);
     133                 :            :                 /* NOTREACHED */
     134                 :            :         }
     135                 :         12 :         return field;
     136                 :            : }
     137                 :            : 
     138                 :            : static unsigned int
     139                 :          4 : modifier_opt(const char *optionarg)
     140                 :            : {
     141                 :            :         unsigned int opt;
     142                 :            : 
     143                 :            :         /* output modifiers */
     144   [ -  -  -  +  :          4 :         switch(match_optarg(modifiers, optionarg)) {
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                -  -  - ]
     145                 :            :         case 'A':
     146                 :          0 :                 opt = INFO_ANNOTATIONS;
     147                 :          0 :                 break;
     148                 :            :         case 'a':
     149                 :          0 :                 opt = INFO_ARCH;
     150                 :          0 :                 break;
     151                 :            :         case 'C':
     152                 :          0 :                 opt = INFO_CATEGORIES;
     153                 :          0 :                 break;
     154                 :            :         case 'c':
     155                 :          4 :                 opt = INFO_COMMENT;
     156                 :          4 :                 break;
     157                 :            :         case 'd':
     158                 :          0 :                 opt = INFO_DEPS;
     159                 :          0 :                 break;
     160                 :            :         case 'D':
     161                 :          0 :                 opt = INFO_DESCR;
     162                 :          0 :                 break;
     163                 :            :         case 'f':
     164                 :          0 :                 opt = INFO_FULL;
     165                 :          0 :                 break;
     166                 :            :         case 'l':
     167                 :          0 :                 opt = INFO_LICENSES;
     168                 :          0 :                 break;
     169                 :            :         case 'm':
     170                 :          0 :                 opt = INFO_MAINTAINER;
     171                 :          0 :                 break;
     172                 :            :         case 'n':
     173                 :          0 :                 opt = INFO_NAME;
     174                 :          0 :                 break;
     175                 :            :         case 'o':
     176                 :          0 :                 opt = INFO_OPTIONS;
     177                 :          0 :                 break;
     178                 :            :         case 'P':
     179                 :          0 :                 opt = INFO_PKGSIZE;
     180                 :          0 :                 break;
     181                 :            :         case 'p':
     182                 :          0 :                 opt = INFO_PREFIX;
     183                 :          0 :                 break;
     184                 :            :         case 'R':
     185                 :          0 :                 opt = INFO_REPOSITORY;
     186                 :          0 :                 break;
     187                 :            :         case 'r':
     188                 :          0 :                 opt = INFO_RDEPS;
     189                 :          0 :                 break;
     190                 :            :         case 'B':
     191                 :          0 :                 opt = INFO_SHLIBS_REQUIRED;
     192                 :          0 :                 break;
     193                 :            :         case 'b':
     194                 :          0 :                 opt = INFO_SHLIBS_PROVIDED;
     195                 :          0 :                 break;
     196                 :            :         case 's':
     197                 :          0 :                 opt = INFO_FLATSIZE;
     198                 :          0 :                 break;
     199                 :            :         case 'u':
     200                 :          0 :                 opt = INFO_REPOURL;
     201                 :          0 :                 break;
     202                 :            :         case 'v':
     203                 :          0 :                 opt = INFO_VERSION;
     204                 :          0 :                 break;
     205                 :            :         case 'w':
     206                 :          0 :                 opt = INFO_WWW;
     207                 :          0 :                 break;
     208                 :            :         default:
     209                 :          0 :                 usage_search();
     210                 :          0 :                 errx(EXIT_FAILURE, "Unkown modifier option %s", optionarg);
     211                 :            :                 /* NOTREACHED */
     212                 :            :         }
     213                 :          4 :         return opt;
     214                 :            : }
     215                 :            : 
     216                 :            : void
     217                 :          0 : usage_search(void)
     218                 :            : {
     219                 :            :         int i, n;
     220                 :            : 
     221                 :          0 :         fprintf(stderr, "Usage: pkg search [-eU] [-r repo] [-S search] "
     222                 :            :             "[-L label] [-Q mod]... [-Cgix] <pkg-name>\n");
     223                 :          0 :         fprintf(stderr, "       pkg search [-cDdefopqRU] [-r repo] "
     224                 :            :             "[-Cgix] <pattern>\n\n");
     225                 :          0 :         n = fprintf(stderr, "       Search and Label options:");
     226         [ #  # ]:          0 :         for (i = 0; search_label[i].option != NULL; i++) {
     227         [ #  # ]:          0 :                 if (n > 72)
     228                 :          0 :                         n = fprintf(stderr, "\n            ");
     229                 :          0 :                 n += fprintf(stderr, " %s", search_label[i].option);
     230                 :          0 :         }
     231                 :          0 :         fprintf(stderr, "\n");
     232                 :          0 :         n = fprintf(stderr, "       Output Modifiers:");
     233         [ #  # ]:          0 :         for (i = 0; modifiers[i].option != NULL; i++) {
     234         [ #  # ]:          0 :                 if (n > 68)
     235                 :          0 :                         n = fprintf(stderr, "\n            ");
     236                 :          0 :                 n += fprintf(stderr, " %s", modifiers[i].option);
     237                 :          0 :         }
     238                 :          0 :         fprintf(stderr, "\n");
     239                 :          0 :         fprintf(stderr, "For more information see 'pkg help search'.\n");
     240                 :          0 : }
     241                 :            : 
     242                 :            : int
     243                 :         16 : exec_search(int argc, char **argv)
     244                 :            : {
     245                 :         16 :         const char      *pattern = NULL;
     246                 :         16 :         const char      *reponame = NULL;
     247                 :         16 :         int              ret = EPKG_OK, ch;
     248                 :            :         int              flags;
     249                 :         16 :         uint64_t         opt = 0;
     250                 :         16 :         match_t          match = MATCH_REGEX;
     251                 :         16 :         pkgdb_field      search = FIELD_NONE;
     252                 :         16 :         pkgdb_field      label = FIELD_NONE;
     253                 :         16 :         struct pkgdb    *db = NULL;
     254                 :         16 :         struct pkgdb_it *it = NULL;
     255                 :         16 :         struct pkg      *pkg = NULL;
     256                 :         16 :         bool             atleastone = false;
     257                 :            :         bool             old_quiet;
     258                 :            : 
     259                 :         16 :         struct option longopts[] = {
     260                 :            :                 { "case-sensitive",   no_argument,            NULL,   'C' },
     261                 :            :                 { "comment",          no_argument,            NULL,   'c' },
     262                 :            :                 { "description",      no_argument,            NULL,   'D' },
     263                 :            :                 { "depends-on",               no_argument,            NULL,   'd' },
     264                 :            :                 { "exact",            no_argument,            NULL,   'e' },
     265                 :            :                 { "full",             no_argument,            NULL,   'f' },
     266                 :            :                 { "glob",             no_argument,            NULL,   'g' },
     267                 :            :                 { "case-insensitive", no_argument,            NULL,   'i' },
     268                 :            :                 { "label",            required_argument,      NULL,   'L' },
     269                 :            :                 { "origins",          no_argument,            NULL,   'o' },
     270                 :            :                 { "prefix",           no_argument,            NULL,   'p' },
     271                 :            :                 { "quiet",            no_argument,            NULL,   'q' },
     272                 :            :                 { "query-modifier",   required_argument,      NULL,   'Q' },
     273                 :            :                 { "repository",               required_argument,      NULL,   'r' },
     274                 :            :                 { "raw",              no_argument,            NULL,   'R' },
     275                 :            :                 { "search",           required_argument,      NULL,   'S' },
     276                 :            :                 { "size",             no_argument,            NULL,   's' },
     277                 :            :                 { "no-repo-update",   no_argument,            NULL,   'U' },
     278                 :            :                 { "regex",            no_argument,            NULL,   'x' },
     279                 :            :                 { "raw-format",               required_argument,      NULL,   1   },
     280                 :            :                 { NULL,                 0,                      NULL,   0   },
     281                 :            :         };
     282                 :            : 
     283         [ +  + ]:         44 :         while ((ch = getopt_long(argc, argv, "+CcDdefgiL:opqQ:r:RS:sUx", longopts, NULL)) != -1) {
     284   [ -  -  -  -  :         28 :                 switch (ch) {
          +  -  -  -  -  
          +  -  +  +  -  
          -  +  -  -  -  
                   -  - ]
     285                 :            :                 case 'C':
     286                 :          0 :                         pkgdb_set_case_sensitivity(true);
     287                 :          0 :                         break;
     288                 :            :                 case 'c':       /* Same as -S comment */
     289                 :          0 :                         search = search_label_opt("comment");
     290                 :          0 :                         break;
     291                 :            :                 case 'D':       /* Same as -S description */
     292                 :          0 :                         search = search_label_opt("description");
     293                 :          0 :                         break;
     294                 :            :                 case 'd':       /* Same as -Q depends-on  */
     295                 :          0 :                         opt |= modifier_opt("depends-on");
     296                 :          0 :                         break;
     297                 :            :                 case 'e':
     298                 :          4 :                         match = MATCH_EXACT;
     299                 :          4 :                         break;
     300                 :            :                 case 'f':       /* Same as -Q full */
     301                 :          0 :                         opt |= modifier_opt("full");
     302                 :          0 :                         break;
     303                 :            :                 case 'g':
     304                 :          0 :                         match = MATCH_GLOB;
     305                 :          0 :                         break;
     306                 :            :                 case 'i':
     307                 :          0 :                         pkgdb_set_case_sensitivity(false);
     308                 :          0 :                         break;
     309                 :            :                 case 'L':
     310                 :          0 :                         label = search_label_opt(optarg);
     311                 :          0 :                         break;
     312                 :            :                 case 'o':       /* Same as -L origin */
     313                 :          8 :                         label = search_label_opt("origin");
     314                 :          8 :                         break;
     315                 :            :                 case 'p':       /* Same as -Q prefix */
     316                 :          0 :                         opt |= modifier_opt("prefix");
     317                 :          0 :                         break;
     318                 :            :                 case 'q':
     319                 :          8 :                         quiet = true;
     320                 :          8 :                         break;
     321                 :            :                 case 'Q':
     322                 :          4 :                         opt |= modifier_opt(optarg);
     323                 :          4 :                         break;
     324                 :            :                 case 'r':
     325                 :          0 :                         reponame = optarg;
     326                 :          0 :                         break;
     327                 :            :                 case 'R':
     328                 :          0 :                         opt = INFO_RAW;
     329                 :          0 :                         break;
     330                 :            :                 case 'S':
     331                 :          4 :                         search = search_label_opt(optarg);
     332                 :          4 :                         break;
     333                 :            :                 case 's':       /* Same as -Q size */
     334                 :          0 :                         opt |= modifier_opt("size");
     335                 :          0 :                         break;
     336                 :            :                 case 'U':
     337                 :          0 :                         auto_update = false;
     338                 :          0 :                         break;
     339                 :            :                 case 'x':
     340                 :          0 :                         match = MATCH_REGEX;
     341                 :          0 :                         break;
     342                 :            :                 case 1:
     343         [ #  # ]:          0 :                         if (strcasecmp(optarg, "json") == 0)
     344                 :          0 :                                 opt |= INFO_RAW_JSON;
     345         [ #  # ]:          0 :                         else if (strcasecmp(optarg, "json-compact") == 0)
     346                 :          0 :                                 opt |= INFO_RAW_JSON_COMPACT;
     347         [ #  # ]:          0 :                         else if (strcasecmp(optarg, "yaml") == 0)
     348                 :          0 :                                 opt |= INFO_RAW_YAML;
     349         [ #  # ]:          0 :                         else if (strcasecmp(optarg, "ucl") == 0)
     350                 :          0 :                                 opt |= INFO_RAW_UCL;
     351                 :            :                         else
     352                 :          0 :                                 errx(EXIT_FAILURE, "Invalid format '%s' for the "
     353                 :            :                                     "raw output, expecting json, json-compact "
     354                 :          0 :                                     "or yaml", optarg);
     355                 :          0 :                         break;
     356                 :            :                 default:
     357                 :          0 :                         usage_search();
     358                 :          0 :                         return (EXIT_FAILURE);
     359                 :            :                 }
     360                 :            :         }
     361                 :            : 
     362                 :         16 :         argc -= optind;
     363                 :         16 :         argv += optind;
     364                 :            : 
     365         [ -  + ]:         16 :         if (argc != 1) {
     366                 :          0 :                 usage_search();
     367                 :          0 :                 return (EXIT_FAILURE);
     368                 :            :         }
     369                 :            : 
     370                 :         16 :         pattern = argv[0];
     371         [ +  - ]:         16 :         if (pattern[0] == '\0') {
     372                 :          0 :                 fprintf(stderr, "Pattern must not be empty.\n");
     373                 :          0 :                 return (EXIT_FAILURE);
     374                 :            :         }
     375         [ +  + ]:         16 :         if (search == FIELD_NONE) {
     376         [ -  + ]:         12 :                 if (strchr(pattern, '/') != NULL)
     377                 :          0 :                         search = FIELD_ORIGIN;
     378                 :            :                 else
     379                 :         12 :                         search = FIELD_NAMEVER; /* Default search */
     380                 :         12 :         }
     381         [ +  + ]:         16 :         if (label == FIELD_NONE)
     382                 :          8 :                 label = search; /* By default, show what was searched  */
     383                 :            : 
     384   [ -  +  +  -  :         16 :         switch(label) {
                -  -  + ]
     385                 :            :         case FIELD_NONE:
     386                 :          0 :                 break;          /* should never happen */
     387                 :            :         case FIELD_ORIGIN:
     388         [ +  + ]:          8 :                 if (quiet) {
     389                 :          4 :                         opt = INFO_TAG_ORIGIN;
     390                 :          4 :                         quiet = false;
     391                 :          4 :                 } else {
     392                 :          4 :                         opt |= INFO_TAG_ORIGIN|INFO_COMMENT;
     393                 :            :                 }
     394                 :          8 :                 break;
     395                 :            :         case FIELD_NAME:
     396                 :          4 :                 opt |= INFO_TAG_NAME|INFO_COMMENT;
     397                 :          4 :                 break;
     398                 :            :         case FIELD_NAMEVER:
     399                 :          4 :                 opt |= INFO_TAG_NAMEVER|INFO_COMMENT;
     400                 :          4 :                 break;
     401                 :            :         case FIELD_COMMENT:
     402                 :          0 :                 opt |= INFO_TAG_NAMEVER|INFO_COMMENT;
     403                 :          0 :                 break;
     404                 :            :         case FIELD_DESC:
     405                 :          0 :                 opt |= INFO_TAG_NAMEVER|INFO_DESCR;
     406                 :          0 :                 break;
     407                 :            :         }
     408                 :            : 
     409         [ +  + ]:         16 :         if (quiet) {
     410                 :          4 :                 opt = INFO_TAG_NAMEVER;
     411                 :          4 :                 quiet = false;
     412                 :          4 :         }
     413                 :            : 
     414                 :         16 :         ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO);
     415   [ -  -  +  + ]:         16 :         switch(ret) {
     416                 :            :         case EPKG_ENOACCESS:
     417                 :          0 :                 warnx("Insufficient privileges to query the package database");
     418                 :          0 :                 return (EXIT_FAILURE);
     419                 :            :         case EPKG_ENODB:
     420         [ +  - ]:          4 :                 if (!auto_update) {
     421                 :          0 :                         warnx("Unable to open remote repository catalogues. Try running '%s update' first.", getprogname());
     422                 :          0 :                         return (EXIT_FAILURE);
     423                 :            :                 }
     424                 :          4 :                 break;
     425                 :            :         case EPKG_OK:
     426                 :         12 :                 break;
     427                 :            :         default:
     428                 :          0 :                 return (EXIT_FAILURE);
     429                 :            :         }
     430                 :            : 
     431                 :            :         /* first update the remote repositories if needed */
     432                 :         16 :         old_quiet = quiet;
     433                 :         16 :         quiet = true;
     434   [ +  -  +  + ]:         16 :         if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK)
     435                 :          4 :                 return (ret);
     436                 :         12 :         quiet = old_quiet;
     437                 :            : 
     438         [ -  + ]:         12 :         if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
     439                 :          0 :                 return (EXIT_FAILURE);
     440                 :            : 
     441   [ +  -  +  -  :         36 :         if ((it = pkgdb_repo_search(db, pattern, match, search, search,
                   +  - ]
     442                 :         24 :             reponame)) == NULL) {
     443                 :          0 :                 pkgdb_close(db);
     444                 :          0 :                 return (EXIT_FAILURE);
     445                 :            :         }
     446                 :            : 
     447         [ +  - ]:         12 :         if (opt & INFO_RAW) {
     448         [ #  # ]:          0 :                 if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) == 0)
     449                 :          0 :                         opt |= INFO_RAW_YAML;
     450                 :          0 :         }
     451                 :            : 
     452                 :         12 :         flags = info_flags(opt, true);
     453         [ +  + ]:         24 :         while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) {
     454                 :         12 :                 print_info(pkg, opt);
     455                 :         12 :                 atleastone = true;
     456                 :            :         }
     457                 :            : 
     458                 :         12 :         pkg_free(pkg);
     459                 :         12 :         pkgdb_it_free(it);
     460                 :         12 :         pkgdb_close(db);
     461                 :            : 
     462         [ +  - ]:         12 :         if (!atleastone)
     463                 :          0 :                 ret = EPKG_FATAL;
     464                 :            : 
     465         [ +  - ]:         12 :         return ((ret == EPKG_OK || ret == EPKG_END) ? EXIT_SUCCESS : EXIT_FAILURE);
     466                 :         16 : }

Generated by: LCOV version 1.15