support medianr in lookup_deltalocation, change lookup_location to return medianr...
[platform/upstream/libsolv.git] / src / pool.c
index ebc8016..4b6ab43 100644 (file)
@@ -54,27 +54,34 @@ pool_create(void)
   pool->nsolvables = 2;
   memset(pool->solvables, 0, 2 * sizeof(Solvable));
 
+  queue_init(&pool->vendormap);
+
+#if defined(DEBIAN)
+  pool->disttype = DISTTYPE_DEB;
+  pool->noarchid = ARCH_ALL;
+#elif defined(ARCHLINUX)
+  pool->disttype = DISTTYPE_ARCH;
+  pool->noarchid = ARCH_ANY;
+#else
+  pool->disttype = DISTTYPE_RPM;
+  pool->noarchid = ARCH_NOARCH;
+#endif
+
   /* initialize the system solvable */
   s = pool->solvables + SYSTEMSOLVABLE;
   s->name = SYSTEM_SYSTEM;
-  s->arch = ARCH_NOARCH;
+  s->arch = pool->noarchid;
   s->evr = ID_EMPTY;
 
-  queue_init(&pool->vendormap);
-
   pool->debugmask = SOLV_DEBUG_RESULT; /* FIXME */
 #ifdef FEDORA
   pool->obsoleteusescolors = 1;
 #endif
-#ifdef DEBIAN 
-  pool->allowselfconflicts = 1;
-# ifdef MULTI_SEMANTICS
-  pool->disttype = DISTTYPE_DEB;
-# endif
-#endif
 #ifdef RPM5
+  pool->forbidselfconflicts = 1;
   pool->obsoleteusesprovides = 1;
   pool->implicitobsoleteusesprovides = 1;
+  pool->havedistepoch = 1;
 #endif
   return pool;
 }
@@ -90,6 +97,7 @@ pool_free(Pool *pool)
   pool_freeidhashes(pool);
   pool_freeallrepos(pool, 1);
   solv_free(pool->id2arch);
+  solv_free(pool->id2color);
   solv_free(pool->solvables);
   stringpool_free(&pool->ss);
   solv_free(pool->rels);
@@ -101,6 +109,8 @@ pool_free(Pool *pool)
     free((char *)pool->languages[i]);
   solv_free(pool->languages);
   solv_free(pool->languagecache);
+  solv_free(pool->errstr);
+  solv_free(pool->rootdir);
   solv_free(pool);
 }
 
@@ -111,7 +121,8 @@ pool_freeallrepos(Pool *pool, int reuseids)
 
   pool_freewhatprovides(pool);
   for (i = 1; i < pool->nrepos; i++) 
-    repo_freedata(pool->repos[i]);
+    if (pool->repos[i])
+      repo_freedata(pool->repos[i]);
   pool->repos = solv_free(pool->repos);
   pool->nrepos = 0; 
   pool->urepos = 0; 
@@ -124,9 +135,75 @@ void
 pool_setdisttype(Pool *pool, int disttype)
 {
   pool->disttype = disttype;
+  if (disttype == DISTTYPE_RPM)
+    pool->noarchid = ARCH_NOARCH;
+  if (disttype == DISTTYPE_DEB)
+    pool->noarchid = ARCH_ALL;
+  if (disttype == DISTTYPE_ARCH)
+    pool->noarchid = ARCH_ANY;
+  pool->solvables[SYSTEMSOLVABLE].arch = pool->noarchid;
 }
 #endif
 
+int
+pool_get_flag(Pool *pool, int flag)
+{
+  switch (flag)
+    {
+    case POOL_FLAG_PROMOTEEPOCH:
+      return pool->promoteepoch;
+    case POOL_FLAG_FORBIDSELFCONFLICTS:
+      return pool->forbidselfconflicts;
+    case POOL_FLAG_OBSOLETEUSESPROVIDES:
+      return pool->obsoleteusesprovides;
+    case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES:
+      return pool->implicitobsoleteusesprovides;
+    case POOL_FLAG_OBSOLETEUSESCOLORS:
+      return pool->obsoleteusescolors;
+    case POOL_FLAG_NOINSTALLEDOBSOLETES:
+      return pool->noinstalledobsoletes;
+    case POOL_FLAG_HAVEDISTEPOCH:
+      return pool->havedistepoch;
+    default:
+      break;
+    }
+  return -1;
+}
+
+int
+pool_set_flag(Pool *pool, int flag, int value)
+{
+  int old = pool_get_flag(pool, flag);
+  switch (flag)
+    {
+    case POOL_FLAG_PROMOTEEPOCH:
+      pool->promoteepoch = value;
+      break;
+    case POOL_FLAG_FORBIDSELFCONFLICTS:
+      pool->forbidselfconflicts = value;
+      break;
+    case POOL_FLAG_OBSOLETEUSESPROVIDES:
+      pool->obsoleteusesprovides = value;
+      break;
+    case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES:
+      pool->implicitobsoleteusesprovides = value;
+      break;
+    case POOL_FLAG_OBSOLETEUSESCOLORS:
+      pool->obsoleteusescolors = value;
+      break;
+    case POOL_FLAG_NOINSTALLEDOBSOLETES:
+      pool->noinstalledobsoletes = value;
+      break;
+    case POOL_FLAG_HAVEDISTEPOCH:
+      pool->havedistepoch = value;
+      break;
+    default:
+      break;
+    }
+  return old;
+}
+
+
 Id
 pool_add_solvable(Pool *pool)
 {
@@ -181,10 +258,6 @@ pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
   ob = pool->whatprovides[*(Id *)bp];
   if (oa == ob)
     return *(Id *)ap - *(Id *)bp;
-  if (!oa)
-    return -1;
-  if (!ob)
-    return 1;
   da = pool->whatprovidesdata + oa;
   db = pool->whatprovidesdata + ob;
   while (*db)
@@ -204,7 +277,7 @@ pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
 static void
 pool_shrink_whatprovides(Pool *pool)
 {
-  Id i, id;
+  Id i, n, id;
   Id *sorted;
   Id lastid, *last, *dp, *lp;
   Offset o;
@@ -213,17 +286,17 @@ pool_shrink_whatprovides(Pool *pool)
   if (pool->ss.nstrings < 3)
     return;
   sorted = solv_malloc2(pool->ss.nstrings, sizeof(Id));
-  for (id = 0; id < pool->ss.nstrings; id++)
-    sorted[id] = id;
-  solv_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
+  for (i = id = 0; id < pool->ss.nstrings; id++)
+    if (pool->whatprovides[id] && pool->whatprovides[id] != 1)
+      sorted[i++] = id;
+  n = i;
+  solv_sort(sorted, n, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
   last = 0;
   lastid = 0;
-  for (i = 1; i < pool->ss.nstrings; i++)
+  for (i = 0; i < n; i++)
     {
       id = sorted[i];
       o = pool->whatprovides[id];
-      if (o == 0 || o == 1)
-       continue;
       dp = pool->whatprovidesdata + o;
       if (last)
        {
@@ -300,8 +373,11 @@ pool_createwhatprovides(Pool *pool)
   unsigned int now;
 
   now = solv_timems(0);
-  POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d, memory used: %d K\n", pool->nsolvables, pool->nsolvables * (int)sizeof(Solvable) / 1024);
   POOL_DEBUG(SOLV_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "string memory used: %d K array + %d K data,  rel memory used: %d K array\n", pool->ss.nstrings / (1024 / (int)sizeof(Id)), pool->ss.sstrings / 1024, pool->nrels * (int)sizeof(Reldep) / 1024);
+  if (pool->ss.stringhashmask || pool->relhashmask)
+    POOL_DEBUG(SOLV_DEBUG_STATS, "string hash memory: %d K, rel hash memory : %d K\n", (pool->ss.stringhashmask + 1) / (int)(1024/sizeof(Id)), (pool->relhashmask + 1) / (int)(1024/sizeof(Id)));
 
   pool_freeidhashes(pool);     /* XXX: should not be here! */
   pool_freewhatprovides(pool);
@@ -452,7 +528,7 @@ pool_queuetowhatprovides(Pool *pool, Queue *q)
 
 #if defined(MULTI_SEMANTICS)
 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
-#elif defined(DEBIAN_SEMANTICS)
+#elif defined(DEBIAN)
 # define EVRCMP_DEPCMP EVRCMP_COMPARE
 #else
 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
@@ -474,7 +550,10 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
        {
        case REL_ARCH:
          if (s->arch != evr)
-           return 0;
+           {
+             if (evr != ARCH_SRC || s->arch != ARCH_NOSRC)
+               return 0;
+           }
          return pool_match_nevr(pool, s, name);
        case REL_OR:
          if (pool_match_nevr(pool, s, name))
@@ -492,15 +571,26 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
   if (!pool_match_nevr(pool, s, name))
     return 0;
   if (evr == s->evr)
-    return flags & 2 ? 1 : 0;
+    return (flags & REL_EQ) ? 1 : 0;
   if (!flags)
     return 0;
   if (flags == 7)
     return 1;
-  if (flags != 2 && flags != 5)
-    flags ^= 5;
-  if ((flags & (1 << (1 + pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP)))) != 0)
-    return 1;
+  switch (pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP))
+    {
+    case -2:
+      return 1;
+    case -1:
+      return (flags & REL_LT) ? 1 : 0;
+    case 0:
+      return (flags & REL_EQ) ? 1 : 0;
+    case 1:
+      return (flags & REL_GT) ? 1 : 0;
+    case 2:
+      return (flags & REL_EQ) ? 1 : 0;
+    default:
+      break;
+    }
   return 0;
 }
 
@@ -512,18 +602,24 @@ pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr)
     return 0;
   if (flags == 7 || pflags == 7)
     return 1;          /* rel provides every version */
-  if ((pflags & flags & 5) != 0)
+  if ((pflags & flags & (REL_LT | REL_GT)) != 0)
     return 1;          /* both rels show in the same direction */
   if (pevr == evr)
+    return (flags & pflags & REL_EQ) ? 1 : 0;
+  switch (pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP))
     {
-      if ((pflags & flags & 2) != 0)
-       return 1;       /* both have '=', match */
-    }
-  else
-    {
-      int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
-      if ((f & (1 << (1 + pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP)))) != 0)
-       return 1;
+    case -2:
+      return (pflags & REL_EQ) ? 1 : 0;
+    case -1:
+      return (flags & REL_LT) || (pflags & REL_GT) ? 1 : 0;
+    case 0:
+      return (flags & pflags & REL_EQ) ? 1 : 0;
+    case 1:
+      return (flags & REL_GT) || (pflags & REL_LT) ? 1 : 0;
+    case 2:
+      return (flags & REL_EQ) ? 1 : 0;
+    default:
+      break;
     }
   return 0;
 }
@@ -648,12 +744,14 @@ pool_addrelproviders(Pool *pool, Id d)
           * we have to iterate over the solvables as src packages do not
           * provide anything, thus they are not indexed in our
           * whatprovides hash */
-         if (evr == ARCH_SRC)
+         if (evr == ARCH_SRC || evr == ARCH_NOSRC)
            {
              Solvable *s;
              for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++)
                {
-                 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+                 if (!s->repo)
+                   continue;
+                 if (s->arch != evr && s->arch != ARCH_NOSRC)
                    continue;
                  if (pool_match_nevr(pool, s, name))
                    queue_push(&plist, p);
@@ -724,22 +822,14 @@ pool_addrelproviders(Pool *pool, Id d)
          pidp = s->repo->idarraydata + s->provides;
          while ((pid = *pidp++) != 0)
            {
-             if (pid == name)
+             if (!ISRELDEP(pid))
                {
-#if defined(MULTI_SEMANTICS)
+                 if (pid != name)
+                   continue;           /* wrong provides name */
                  if (pool->disttype == DISTTYPE_DEB)
-                   continue;
-                 else
-                   break;
-#elif defined(DEBIAN_SEMANTICS)
-                 continue;             /* unversioned provides can
-                                        * never match versioned deps */
-#else
-                 break;                /* yes, provides all versions */
-#endif
+                   continue;           /* unversioned provides can never match versioned deps */
+                 break;
                }
-             if (!ISRELDEP(pid))
-               continue;               /* wrong provides name */
              prd = GETRELDEP(pool, pid);
              if (prd->name != name)
                continue;               /* wrong provides name */
@@ -788,15 +878,56 @@ pool_debug(Pool *pool, int type, const char *format, ...)
       return;
     }
   vsnprintf(buf, sizeof(buf), format, args);
+  va_end(args);
   pool->debugcallback(pool, pool->debugcallbackdata, type, buf);
 }
 
+int
+pool_error(Pool *pool, int ret, const char *format, ...)
+{
+  va_list args;
+  int l;
+  va_start(args, format);
+  if (!pool->errstr)
+    {
+      pool->errstra = 1024;
+      pool->errstr = solv_malloc(pool->errstra);
+    }
+  if (!*format)
+    {
+      *pool->errstr = 0;
+      l = 0;
+    }
+  else
+    l = vsnprintf(pool->errstr, pool->errstra, format, args);
+  va_end(args);
+  if (l >= 0 && l + 1 > pool->errstra)
+    {
+      pool->errstra = l + 256;
+      pool->errstr = solv_realloc(pool->errstr, pool->errstra);
+      va_start(args, format);
+      l = vsnprintf(pool->errstr, pool->errstra, format, args);
+      va_end(args);
+    }
+  if (l < 0)
+    strcpy(pool->errstr, "unknown error");
+  if (pool->debugmask & SOLV_ERROR)
+    pool_debug(pool, SOLV_ERROR, "%s\n", pool->errstr);
+  return ret;
+}
+
+char *
+pool_errstr(Pool *pool)
+{
+  return pool->errstr ? pool->errstr : "no error";
+}
+
 void
 pool_setdebuglevel(Pool *pool, int level)
 {
   int mask = SOLV_DEBUG_RESULT;
   if (level > 0)
-    mask |= SOLV_DEBUG_STATS|SOLV_DEBUG_ANALYZE|SOLV_DEBUG_UNSOLVABLE|SOLV_DEBUG_SOLVER|SOLV_DEBUG_TRANSACTION;
+    mask |= SOLV_DEBUG_STATS|SOLV_DEBUG_ANALYZE|SOLV_DEBUG_UNSOLVABLE|SOLV_DEBUG_SOLVER|SOLV_DEBUG_TRANSACTION|SOLV_ERROR;
   if (level > 1)
     mask |= SOLV_DEBUG_JOB|SOLV_DEBUG_SOLUTIONS|SOLV_DEBUG_POLICY;
   if (level > 2)
@@ -944,6 +1075,7 @@ addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
          if (did)
            MAPSET(&cbd->useddirs, did);
        }
+      repodata_free_dircache(data);
     }
   if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id))
     return 0;
@@ -1085,21 +1217,26 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
 }
 
 void
-pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
+pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst)
 {
   Solvable *s;
-  Repo *repo;
+  Repo *installed, *repo;
   struct searchfiles sf, isf, *isfp;
   struct addfileprovides_cbdata cbd;
   int i;
   unsigned int now;
 
+  installed = pool->installed;
   now = solv_timems(0);
   memset(&sf, 0, sizeof(sf));
   map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
   memset(&isf, 0, sizeof(isf));
   map_init(&isf.seen, pool->ss.nstrings + pool->nrels);
 
+  if (idq)
+    queue_empty(idq);
+  if (idqinst)
+    queue_empty(idqinst);
   isfp = installed ? &isf : 0;
   for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++)
     {
@@ -1125,8 +1262,6 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
   map_free(&isf.seen);
   POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles);
   cbd.dids = 0;
-  if (idp)
-    *idp = 0;
   if (sf.nfiles)
     {
 #if 0
@@ -1134,13 +1269,12 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
        POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in filelist\n", pool_id2str(pool, sf.ids[i]));
 #endif
       pool_addfileprovides_search(pool, &cbd, &sf, 0);
-      if (idp)
-       {
-         sf.ids = solv_extend(sf.ids, sf.nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
-         sf.ids[sf.nfiles] = 0;
-         *idp = sf.ids;
-         sf.ids = 0;
-       }
+      if (idq)
+        for (i = 0; i < sf.nfiles; i++)
+         queue_push(idq, sf.ids[i]);
+      if (idqinst)
+        for (i = 0; i < sf.nfiles; i++)
+         queue_push(idqinst, sf.ids[i]);
       solv_free(sf.ids);
       for (i = 0; i < sf.nfiles; i++)
        {
@@ -1158,6 +1292,9 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
 #endif
       if (installed)
         pool_addfileprovides_search(pool, &cbd, &isf, installed);
+      if (installed && idqinst)
+        for (i = 0; i < isf.nfiles; i++)
+         queue_pushunique(idqinst, isf.ids[i]);
       solv_free(isf.ids);
       for (i = 0; i < isf.nfiles; i++)
        {
@@ -1175,7 +1312,7 @@ pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
 void
 pool_addfileprovides(Pool *pool)
 {
-  pool_addfileprovides_ids(pool, pool->installed, 0);
+  pool_addfileprovides_queue(pool, 0, 0);
 }
 
 void
@@ -1228,7 +1365,7 @@ pool_id2langid(Pool *pool, Id id, const char *lang, int create)
   char buf[256], *p;
   int l;
 
-  if (!lang)
+  if (!lang || !*lang)
     return id;
   n = pool_id2str(pool, id);
   l = strlen(n) + strlen(lang) + 2;
@@ -1635,7 +1772,7 @@ pool_calc_installsizechange(Pool *pool, Map *installedmap)
        continue;
       if (!MAPTST(installedmap, sp))
        continue;
-      change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
+      change += solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0);
     }
   if (oldinstalled)
     {
@@ -1643,7 +1780,7 @@ pool_calc_installsizechange(Pool *pool, Map *installedmap)
        {
          if (MAPTST(installedmap, sp))
            continue;
-         change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
+         change -= solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0);
        }
     }
   return change;
@@ -1887,12 +2024,12 @@ pool_lookup_id(Pool *pool, Id entry, Id keyname)
   return solvable_lookup_id(pool->solvables + entry, keyname);
 }
 
-unsigned int
-pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned int notfound)
+unsigned long long
+pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound)
 {
   if (entry == SOLVID_POS && pool->pos.repo)
     {
-      unsigned int value;
+      unsigned long long value;
       if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value))
        return value;
       return notfound;
@@ -1935,6 +2072,21 @@ pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
   return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
 }
 
+const char *
+pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp)
+{
+  const char *loc;
+  if (medianrp)
+    *medianrp = 0;
+  if (entry != SOLVID_POS)
+    return 0;
+  loc = pool_lookup_str(pool, entry, DELTA_LOCATION_DIR);
+  loc = pool_tmpjoin(pool, loc, loc ? "/" : 0, pool_lookup_str(pool, entry, DELTA_LOCATION_NAME));
+  loc = pool_tmpappend(pool, loc, "-", pool_lookup_str(pool, entry, DELTA_LOCATION_EVR));
+  loc = pool_tmpappend(pool, loc, ".", pool_lookup_str(pool, entry, DELTA_LOCATION_SUFFIX));
+  return loc;
+}
+
 void
 pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
 {
@@ -1967,4 +2119,37 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
     pool_freeidhashes(pool);
 }
 
+char *
+pool_prepend_rootdir(Pool *pool, const char *path)
+{
+  if (!path)
+    return 0;
+  if (!pool->rootdir)
+    return solv_strdup(path);
+  return solv_dupjoin(pool->rootdir, "/", *path == '/' ? path + 1 : path);
+}
+
+const char *
+pool_prepend_rootdir_tmp(Pool *pool, const char *path)
+{
+  if (!path)
+    return 0;
+  if (!pool->rootdir)
+    return path;
+  return pool_tmpjoin(pool, pool->rootdir, "/", *path == '/' ? path + 1 : path);
+}
+
+void
+pool_set_rootdir(Pool *pool, const char *rootdir)
+{
+  solv_free(pool->rootdir);
+  pool->rootdir = solv_strdup(rootdir);
+}
+
+const char *
+pool_get_rootdir(Pool *pool)
+{
+  return pool->rootdir;
+}
+
 /* EOF */