- color support in fileconflict checking
authorMichael Schroeder <mls@suse.de>
Tue, 21 Jul 2009 09:45:41 +0000 (11:45 +0200)
committerMichael Schroeder <mls@suse.de>
Tue, 21 Jul 2009 09:45:41 +0000 (11:45 +0200)
- more commands for solv

examples/solv.c
ext/pool_fileconflicts.c
ext/repo_rpmdb.c
ext/repo_rpmdb.h
src/pool.c
src/repo_solv.c
src/rules.c
src/solver.c
src/solver.h

index 6a07889..ec00a84 100644 (file)
@@ -7,7 +7,7 @@
 
 /* solv, a little software installer demoing the sat solver library */
 
-/* things missing:
+/* things available in the library but missing from solv:
  * - vendor policy loading
  * - soft locks file handling
  * - multi version handling
@@ -74,11 +74,13 @@ struct repoinfo {
   char *metalink;
   char *path;
   int type;
-  int gpgcheck;
+  int pkgs_gpgcheck;
+  int repo_gpgcheck;
   int priority;
   int keeppackages;
   int metadata_expire;
 
+  unsigned char cookie[32];
   unsigned char extcookie[32];
 };
 
@@ -221,6 +223,9 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp)
              cinfo->alias = strdup(kp + 1);
              cinfo->type = TYPE_RPMMD;
              cinfo->autorefresh = 1;
+#ifndef FEDORA
+             cinfo->repo_gpgcheck = 1;
+#endif
              cinfo->metadata_expire = METADATA_EXPIRE;
              continue;
            }
@@ -245,7 +250,9 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp)
          else if (!strcmp(kp, "autorefresh"))
            cinfo->autorefresh = *vp == '0' ? 0 : 1;
          else if (!strcmp(kp, "gpgcheck"))
-           cinfo->gpgcheck = *vp == '0' ? 0 : 1;
+           cinfo->pkgs_gpgcheck = *vp == '0' ? 0 : 1;
+         else if (!strcmp(kp, "repo_gpgcheck"))
+           cinfo->repo_gpgcheck = *vp == '0' ? 0 : 1;
          else if (!strcmp(kp, "baseurl"))
            cinfo->baseurl = strdup(vp);
          else if (!strcmp(kp, "mirrorlist"))
@@ -344,13 +351,38 @@ verify_checksum(int fd, const char *file, const unsigned char *chksum, Id chksum
 }
 
 char *
-findmetalinkurl(FILE *fp)
+findmetalinkurl(FILE *fp, unsigned char *chksump, Id *chksumtypep)
 {
   char buf[4096], *bp, *ep;
+
+  if (chksumtypep)
+    *chksumtypep = 0;
   while((bp = fgets(buf, sizeof(buf), fp)) != 0)
     {
       while (*bp == ' ' || *bp == '\t')
        bp++;
+      if (chksumtypep && !*chksumtypep && !strncmp(bp, "<hash type=\"sha256\">", 20))
+       {
+         int i;
+
+         bp += 20;
+         memset(chksumtypep, 0, 32);
+         for (i = 0; i < 64; i++)
+           {
+             int c = *bp++;
+             if (c >= '0' && c <= '9')
+               chksump[i / 2] = chksump[i / 2] * 16 + (c - '0');
+             else if (c >= 'a' && c <= 'f')
+               chksump[i / 2] = chksump[i / 2] * 16 + (c - ('a' - 10));
+             else if (c >= 'A' && c <= 'F')
+               chksump[i / 2] = chksump[i / 2] * 16 + (c - ('A' - 10));
+             else
+               break;
+           }
+         if (i == 64)
+           *chksumtypep = REPOKEY_TYPE_SHA256;
+         continue;
+       }
       if (strncmp(bp, "<url", 4))
        continue;
       bp = strchr(bp, '>');
@@ -396,12 +428,19 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign
       if (file != cinfo->metalink)
        {
          FILE *fp = curlfopen(cinfo, cinfo->metalink, 0, 0, 0, 0);
+         unsigned char mlchksum[32];
+         Id mlchksumtype = 0;
          if (!fp)
            return 0;
-         cinfo->baseurl = findmetalinkurl(fp);
+         cinfo->baseurl = findmetalinkurl(fp, mlchksum, &mlchksumtype);
          fclose(fp);
          if (!cinfo->baseurl)
            return 0;
+         if (!chksumtype && mlchksumtype)
+           {
+             chksumtype = mlchksumtype;
+             chksum = mlchksum;
+           }
          return curlfopen(cinfo, file, uncompress, chksum, chksumtype, badchecksump);
        }
       snprintf(url, sizeof(url), "%s", file);
@@ -659,7 +698,14 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie, int mark)
       /* set the checksum so that we can use it with the stub loads */
       struct stat stb;
       if (!fstat(fileno(fp), &stb))
-        calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+       {
+         int i;
+
+         stb.st_mtime = 0;
+          calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+         for (i = 0; i < 32; i++)
+           cinfo->extcookie[i] ^= cinfo->cookie[i];
+       }
     }
   if (mark)
     futimes(fileno(fp), 0);    /* try to set modification time */
@@ -742,7 +788,14 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *
       /* set the checksum so that we can use it with the stub loads */
       struct stat stb;
       if (!stat(tmpl, &stb))
-        calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+       {
+         int i;
+
+         stb.st_mtime = 0;
+          calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie);
+         for (i = 0; i < 32; i++)
+           cinfo->extcookie[i] ^= cinfo->cookie[i];
+       }
     }
   if (onepiece)
     {
@@ -1113,7 +1166,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
       dorefresh = cinfo->autorefresh;
       if (dorefresh && cinfo->metadata_expire && stat(calccachepath(repo, 0), &stb) == 0)
        {
-         if (time(0) - stb.st_mtime < cinfo->metadata_expire)
+         if (cinfo->metadata_expire == -1 || time(0) - stb.st_mtime < cinfo->metadata_expire)
            dorefresh = 0;
        }
       if (!dorefresh && usecachedrepo(repo, 0, 0, 0))
@@ -1135,24 +1188,22 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
              cinfo->repo = 0;
              break;
            }
-         calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
-         if (usecachedrepo(repo, 0, cookie, 1))
+         calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cinfo->cookie);
+         if (usecachedrepo(repo, 0, cinfo->cookie, 1))
            {
              printf(" cached\n");
               fclose(fp);
              break;
            }
-         sigfp = curlfopen(cinfo, "repodata/repomd.xml.asc", 0, 0, 0, 0);
-#ifndef FEDORA
-         if (!sigfp)
-           {
-             printf(" unsigned, skipped\n");
-             fclose(fp);
-             break;
-           }
-#endif
-         if (sigfp)
+         if (cinfo->repo_gpgcheck)
            {
+             sigfp = curlfopen(cinfo, "repodata/repomd.xml.asc", 0, 0, 0, 0);
+             if (!sigfp)
+               {
+                 printf(" unsigned, skipped\n");
+                 fclose(fp);
+                 break;
+               }
              if (!sigpool)
                sigpool = read_sigs();
              if (!checksig(sigpool, fp, sigfp))
@@ -1189,7 +1240,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
          repomd_add_ext(repo, data, "filelists");
          repodata_internalize(data);
          if (!badchecksum)
-           writecachedrepo(repo, data, 0, cookie);
+           writecachedrepo(repo, data, 0, cinfo->cookie);
          repodata_create_stubs(data);
          break;
 
@@ -1205,32 +1256,35 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
              cinfo->repo = 0;
              break;
            }
-         calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
-         if (usecachedrepo(repo, 0, cookie, 1))
+         calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cinfo->cookie);
+         if (usecachedrepo(repo, 0, cinfo->cookie, 1))
            {
              printf(" cached\n");
              fclose(fp);
              break;
            }
-         sigfp = curlfopen(cinfo, "content.asc", 0, 0, 0, 0);
-         if (!sigfp)
+         if (cinfo->repo_gpgcheck)
            {
-             printf(" unsigned, skipped\n");
-             fclose(fp);
-             break;
-           }
-         if (sigfp)
-           {
-             if (!sigpool)
-               sigpool = read_sigs();
-             if (!checksig(sigpool, fp, sigfp))
+             sigfp = curlfopen(cinfo, "content.asc", 0, 0, 0, 0);
+             if (!sigfp)
                {
-                 printf(" checksig failed, skipped\n");
-                 fclose(sigfp);
+                 printf(" unsigned, skipped\n");
                  fclose(fp);
                  break;
                }
-             fclose(sigfp);
+             if (sigfp)
+               {
+                 if (!sigpool)
+                   sigpool = read_sigs();
+                 if (!checksig(sigpool, fp, sigfp))
+                   {
+                     printf(" checksig failed, skipped\n");
+                     fclose(sigfp);
+                     fclose(fp);
+                     break;
+                   }
+                 fclose(sigfp);
+               }
            }
          repo_add_content(repo, fp, 0);
          fclose(fp);
@@ -1255,7 +1309,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos)
          susetags_add_ext(repo, data);
          repodata_internalize(data);
          if (!badchecksum)
-           writecachedrepo(repo, data, 0, cookie);
+           writecachedrepo(repo, data, 0, cinfo->cookie);
          repodata_create_stubs(data);
          break;
        default:
@@ -1715,6 +1769,34 @@ nscallback(Pool *pool, void *data, Id name, Id evr)
   return 0;
 }
 
+#define MODE_LIST        0
+#define MODE_INSTALL     1
+#define MODE_ERASE       2
+#define MODE_UPDATE      3
+#define MODE_DISTUPGRADE 4
+#define MODE_VERIFY      5
+#define MODE_PATCH       6
+#define MODE_INFO        7
+#define MODE_REPOLIST    8
+#define MODE_SEARCH     9
+
+void
+usage(int r)
+{
+  fprintf(stderr, "Usage: solv COMMAND <select>\n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "    distupgrade: replace installed packages with\n");
+  fprintf(stderr, "                 versions from the repositories\n");
+  fprintf(stderr, "    erase:       erase installed packages\n");
+  fprintf(stderr, "    info:        display package information\n");
+  fprintf(stderr, "    install:     install packages\n");
+  fprintf(stderr, "    list:        list packages\n");
+  fprintf(stderr, "    repos:       list enabled repositories\n");
+  fprintf(stderr, "    search:      search name/summary/description\n");
+  fprintf(stderr, "    update:      update installed packages\n");
+  fprintf(stderr, "\n");
+  exit(r);
+}
 
 int
 main(int argc, char **argv)
@@ -1725,57 +1807,132 @@ main(int argc, char **argv)
   Id p, pp;
   struct repoinfo *repoinfos;
   int nrepoinfos = 0;
-  int i, mode, newpkgs;
+  int i, mainmode, mode, newpkgs;
   Queue job, checkq;
   Solver *solv = 0;
   Transaction *trans;
   char inbuf[128], *ip;
-  int updateall = 0;
-  int distupgrade = 0;
-  int patchmode = 0;
+  int allpkgs = 0;
   FILE **newpkgsfps;
   struct fcstate fcstate;
 
   argc--;
   argv++;
   if (!argv[0])
+    usage(1);
+  if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in"))
     {
-      fprintf(stderr, "Usage: solv install|erase|update|show <select>\n");
-      exit(1);
+      mainmode = MODE_INSTALL;
+      mode = SOLVER_INSTALL;
     }
-  if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in"))
-    mode = SOLVER_INSTALL;
   else if (!strcmp(argv[0], "patch"))
     {
-      mode = SOLVER_UPDATE;
-      patchmode = 1;
+      mainmode = MODE_PATCH;
+      mode = SOLVER_INSTALL;
     }
   else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm"))
-    mode = SOLVER_ERASE;
-  else if (!strcmp(argv[0], "show"))
-    mode = 0;
+    {
+      mainmode = MODE_ERASE;
+      mode = SOLVER_ERASE;
+    }
+  else if (!strcmp(argv[0], "list"))
+    {
+      mainmode = MODE_LIST;
+      mode = 0;
+    }
+  else if (!strcmp(argv[0], "info"))
+    {
+      mainmode = MODE_INFO;
+      mode = 0;
+    }
+  else if (!strcmp(argv[0], "search"))
+    {
+      mainmode = MODE_SEARCH;
+      mode = 0;
+    }
+  else if (!strcmp(argv[0], "verify"))
+    {
+      mainmode = MODE_VERIFY;
+      mode = SOLVER_VERIFY;
+    }
   else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up"))
-    mode = SOLVER_UPDATE;
+    {
+      mainmode = MODE_UPDATE;
+      mode = SOLVER_UPDATE;
+    }
   else if (!strcmp(argv[0], "dist-upgrade") || !strcmp(argv[0], "dup"))
     {
+      mainmode = MODE_DISTUPGRADE;
       mode = SOLVER_UPDATE;
-      distupgrade = 1;
     }
-  else
+  else if (!strcmp(argv[0], "repos") || !strcmp(argv[0], "repolist") || !strcmp(argv[0], "lr"))
     {
-      fprintf(stderr, "Usage: solv install|erase|update|show <select>\n");
-      exit(1);
+      mainmode = MODE_REPOLIST;
+      mode = 0;
     }
+  else
+    usage(1);
 
   pool = pool_create();
+#ifdef FEDORA
+  pool->obsoleteusescolors = 1;
+#endif
   pool_setloadcallback(pool, load_stub, 0);
   pool->nscallback = nscallback;
   // pool_setdebuglevel(pool, 2);
   setarch(pool);
   repoinfos = read_repoinfos(pool, REPOINFO_PATH, &nrepoinfos);
+
+  if (mainmode == MODE_REPOLIST)
+    {
+      int j = 1;
+      for (i = 0; i < nrepoinfos; i++)
+       {
+         struct repoinfo *cinfo = repoinfos + i;
+         if (!cinfo->enabled)
+           continue;
+         printf("%d: %-20s %s\n", j++, cinfo->alias, cinfo->name);
+       }
+      exit(0);
+    }
+
   read_repos(pool, repoinfos, nrepoinfos);
 
-  if (mode == 0 || mode == SOLVER_INSTALL)
+  if (mainmode == MODE_SEARCH)
+    {
+      Dataiterator di;
+      Map m;
+      if (argc != 2)
+       usage(1);
+      map_init(&m, pool->nsolvables);
+      dataiterator_init(&di, pool, 0, 0, 0, argv[1], SEARCH_SUBSTRING|SEARCH_NOCASE);
+      dataiterator_set_keyname(&di, SOLVABLE_NAME);
+      dataiterator_set_search(&di, 0, 0);
+      while (dataiterator_step(&di))
+       MAPSET(&m, di.solvid);
+      dataiterator_set_keyname(&di, SOLVABLE_SUMMARY);
+      dataiterator_set_search(&di, 0, 0);
+      while (dataiterator_step(&di))
+       MAPSET(&m, di.solvid);
+      dataiterator_set_keyname(&di, SOLVABLE_DESCRIPTION);
+      dataiterator_set_search(&di, 0, 0);
+      while (dataiterator_step(&di))
+       MAPSET(&m, di.solvid);
+      dataiterator_free(&di);
+
+      for (p = 1; p < pool->nsolvables; p++)
+       {
+         Solvable *s = pool_id2solvable(pool, p);
+         if (!MAPTST(&m, p))
+           continue;
+         printf("  - %s: %s\n", solvable2str(pool, s), solvable_lookup_str(s, SOLVABLE_SUMMARY));
+       }
+      map_free(&m);
+      exit(0);
+    }
+
+
+  if (mainmode == MODE_LIST || mainmode == MODE_INSTALL)
     {
       for (i = 1; i < argc; i++)
        {
@@ -1807,33 +1964,55 @@ main(int argc, char **argv)
   queue_init(&job);
   for (i = 1; i < argc; i++)
     {
+      Queue job2;
+      int j;
+
       if (commandlinepkgs && commandlinepkgs[i])
        {
          queue_push2(&job, SOLVER_SOLVABLE, commandlinepkgs[i]);
          continue;
        }
-      mkselect(pool, mode, argv[i], &job);
+      queue_init(&job2);
+      mkselect(pool, mode, argv[i], &job2);
+      for (j = 0; j < job2.count; j++)
+       queue_push(&job, job2.elements[j]);
+      queue_free(&job2);
     }
-  if (!job.count && mode == SOLVER_UPDATE)
-    updateall = 1;
-  else if (!job.count)
+
+  if (!job.count && mainmode != MODE_UPDATE && mainmode != MODE_DISTUPGRADE && mainmode != MODE_VERIFY && mainmode != MODE_PATCH)
     {
       printf("no package matched\n");
       exit(1);
     }
 
-  if (!mode)
+  if (!job.count)
+    allpkgs = 1;
+
+  if (mainmode == MODE_LIST || mainmode == MODE_INFO)
     {
-      /* show mode, no solver needed */
+      /* list mode, no solver needed */
       for (i = 0; i < job.count; i += 2)
        {
          FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1])
            {
              Solvable *s = pool_id2solvable(pool, p);
-             const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de");
-             printf("  - %s [%s]\n", solvable2str(pool, s), s->repo->name);
-             if (sum)
-                printf("    %s\n", sum);
+             if (mainmode == MODE_INFO)
+               {
+                 printf("Name:        %s\n", solvable2str(pool, s));
+                 printf("Repo:        %s\n", s->repo->name);
+                 printf("Summary:     %s\n", solvable_lookup_str(s, SOLVABLE_SUMMARY));
+                 printf("Url:         %s\n", solvable_lookup_str(s, SOLVABLE_URL));
+                 printf("License:     %s\n", solvable_lookup_str(s, SOLVABLE_LICENSE));
+                 printf("Description:\n%s\n", solvable_lookup_str(s, SOLVABLE_DESCRIPTION));
+                 printf("\n");
+               }
+             else
+               {
+                 const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de");
+                 printf("  - %s [%s]\n", solvable2str(pool, s), s->repo->name);
+                 if (sum)
+                   printf("    %s\n", sum);
+               }
            }
        }
       queue_free(&job);
@@ -1843,7 +2022,7 @@ main(int argc, char **argv)
       exit(0);
     }
 
-  if (updateall && patchmode)
+  if (mainmode == MODE_PATCH)
     {
       int pruneyou = 0;
       Map installedmap;
@@ -1855,8 +2034,6 @@ main(int argc, char **argv)
          MAPSET(&installedmap, p);
 
       /* install all patches */
-      updateall = 0;
-      mode = SOLVER_INSTALL;
       for (p = 1; p < pool->nsolvables; p++)
        {
          const char *type;
@@ -1900,6 +2077,7 @@ main(int argc, char **argv)
     {
       if (mode == SOLVER_UPDATE)
        {
+         /* make update of not installed packages an install */
          FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1])
            if (pool->installed && pool->solvables[p].repo == pool->installed)
              break;
@@ -1925,15 +2103,19 @@ rerunsolver:
 
       solv = solver_create(pool);
       solv->ignorealreadyrecommended = 1;
-      solv->updatesystem = updateall;
-      solv->dosplitprovides = updateall;
-      if (updateall && distupgrade)
+      solv->updatesystem = allpkgs && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE);
+      solv->dosplitprovides = solv->updatesystem;
+      solv->fixsystem = allpkgs && (mainmode == MODE_VERIFY);
+      if (mainmode == MODE_DISTUPGRADE)
        {
          solv->distupgrade = 1;
           solv->allowdowngrade = 1;
           solv->allowarchchange = 1;
           solv->allowvendorchange = 1;
        }
+      /* infarch check currently doesn't work with colors */
+      solv->noinfarchcheck = pool->obsoleteusescolors;
+
       // queue_push2(&job, SOLVER_DISTUPGRADE, 3);
       solver_solve(solv, &job);
       if (!solv->problems.count)
index ed0a41c..0e91e9b 100644 (file)
@@ -214,7 +214,7 @@ findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
 {
   struct cbdata *cbdata = cbdatav;
   unsigned int hx = strhash(fn);
-  char md5padded[33];
+  char md5padded[34];
 
   if (!hx)
     hx = strlen(fn) + 1;
@@ -222,9 +222,10 @@ findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
     return;
   strncpy(md5padded, md5, 32);
   md5padded[32] = 0;
+  md5padded[33] = fmode >> 24;
   // printf("%d, hx %x -> %s   %d %s\n", cbdata->idx, hx, fn, fmode, md5);
   queue_push(&cbdata->files, cbdata->filesspacen);
-  addfilesspace(cbdata, (unsigned char *)md5padded, 33);
+  addfilesspace(cbdata, (unsigned char *)md5padded, 34);
   addfilesspace(cbdata, (unsigned char *)fn, strlen(fn) + 1);
 }
 
@@ -367,6 +368,11 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
     {
       int pend, ii, jj;
       int pidx = cbdata.lookat.elements[i + 1];
+      int iterflags;
+
+      iterflags = RPM_ITERATE_FILELIST_WITHMD5;
+      if (pool->obsoleteusescolors)
+       iterflags |= RPM_ITERATE_FILELIST_WITHCOL;
       p = pkgs->elements[pidx];
       hx = cbdata.lookat.elements[i];
       if (cbdata.lookat.elements[i + 2] != hx)
@@ -380,7 +386,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
       handle = (*handle_cb)(pool, p, handle_cbdata);
       if (!handle)
        continue;
-      rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_WITHMD5, findfileconflicts2_cb, &cbdata);
+      rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata);
 
       pend = cbdata.files.count;
       for (j = i + 2; j < cbdata.lookat.count && cbdata.lookat.elements[j] == hx; j++)
@@ -393,15 +399,19 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
          handle = (*handle_cb)(pool, q, handle_cbdata);
          if (!handle)
            continue;
-         rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_WITHMD5, findfileconflicts2_cb, &cbdata);
+         rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata);
           for (ii = 0; ii < pend; ii++)
            for (jj = pend; jj < cbdata.files.count; jj++)
              {
-               if (strcmp((char *)cbdata.filesspace + cbdata.files.elements[ii] + 33, (char *)cbdata.filesspace + cbdata.files.elements[jj] + 33))
-                 continue;
-               if (!strcmp((char *)cbdata.filesspace + cbdata.files.elements[ii], (char *)cbdata.filesspace + cbdata.files.elements[jj]))
-                 continue;
-               queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[ii] + 33, 1));
+               char *fsi = (char *)cbdata.filesspace + cbdata.files.elements[ii];
+               char *fsj = (char *)cbdata.filesspace + cbdata.files.elements[jj];
+               if (strcmp(fsi + 34, fsj + 34))
+                 continue;     /* different file names */
+               if (!strcmp(fsi, fsj))
+                 continue;     /* md5 sum matches */
+               if (pool->obsoleteusescolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
+                 continue;     /* colors do not conflict */
+               queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[ii] + 34, 1));
                queue_push(conflicts, p);
                queue_push(conflicts, str2id(pool, (char *)cbdata.filesspace + cbdata.files.elements[ii], 1));
                queue_push(conflicts, q);
index 911f1af..ed33bc9 100644 (file)
@@ -1908,6 +1908,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *
   char **md = 0;
   char **lt = 0;
   unsigned int *di, diidx;
+  unsigned int *co = 0;
   unsigned int lastdir;
   int lastdirl;
   unsigned int *fm;
@@ -1963,6 +1964,20 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *
          return;
        }
     }
+  if ((flags & RPM_ITERATE_FILELIST_WITHCOL) != 0)
+    {
+      co = headint32array(rpmhead, TAG_FILECOLORS, &cnt2);
+      if (!co || cnt != cnt2)
+       {
+         sat_free(co);
+         sat_free(md);
+         sat_free(fm);
+         sat_free(di);
+         sat_free(bn);
+         sat_free(dn);
+         return;
+       }
+    }
   lastdir = dcnt;
   lastdirl = 0;
   for (i = 0; i < cnt; i++)
@@ -2005,9 +2020,12 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *
                }
            }
          if (!md5p)
-           md5p = "";
+           {
+             sprintf(md5, "%08x%08x", (fm[i] >> 12) & 65535, 0);
+             md5p = md5;
+           }
        }
-      (*cb)(cbdata, space, fm[i], md5p);
+      (*cb)(cbdata, space, co ? (fm[i] | co[i] << 24) : fm[i], md5p);
     }
   sat_free(space);
   sat_free(lt);
@@ -2016,6 +2034,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *
   sat_free(di);
   sat_free(bn);
   sat_free(dn);
+  sat_free(co);
 }
 
 char *
index 78dd2f3..b801a48 100644 (file)
@@ -24,6 +24,7 @@ void repo_add_pubkeys(Repo *repo, const char **keys, int nkeys, int flags);
 
 #define RPM_ITERATE_FILELIST_ONLYDIRS  (1 << 0)
 #define RPM_ITERATE_FILELIST_WITHMD5   (1 << 1)
+#define RPM_ITERATE_FILELIST_WITHCOL   (1 << 2)
 
 void *rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep);
 void *rpm_byfp(FILE *fp, const char *name, void **statep);
index eae97e1..4bfc2de 100644 (file)
@@ -949,6 +949,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
       end = pool->nsolvables;
     }
   flags = 0;
+  map_init(&providedids, pool->ss.nstrings);
   for (p = start, s = pool->solvables + p; p < end; p++, s++)
     {
       repo = s->repo;
@@ -986,12 +987,11 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
            data = nextdata;    /* no direct hit, use next repodata */
          if (data)
            {
-             map_init(&providedids, pool->ss.nstrings);
+             map_empty(&providedids);
              repodata_search(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, 0, addfileprovides_setid_cb, &providedids);
              for (i = 0; i < cbd->nfiles; i++)
                if (!MAPTST(&providedids, cbd->ids[i]))
                  break;
-             map_free(&providedids);
              dataincludes = i == cbd->nfiles;
            }
          oldrepo = repo;
@@ -1009,18 +1009,23 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
          if (ffldata)
            {
              for (i = 0; i < cbd->nfiles; i++)
-               if (!repodata_filelistfilter_matches(ffldata, id2str(pool, cbd->ids[i])))
-                 {
-#if 0
-                   printf("Need the complete filelist in repo %s because of %s\n", repo->name, id2str(pool, cbd->ids[i]));
-#endif
-                   flags = SEARCH_COMPLETE_FILELIST;
-                   break;
-                 }
+               {
+                 if (data && p >= data->start && MAPTST(&providedids, cbd->ids[i]))
+                   continue;
+                 if (!repodata_filelistfilter_matches(ffldata, id2str(pool, cbd->ids[i])))
+                   {
+  #if 0
+                     printf("Need the complete filelist in repo %s because of %s\n", repo->name, id2str(pool, cbd->ids[i]));
+  #endif
+                     flags = SEARCH_COMPLETE_FILELIST;
+                     break;
+                   }
+               }
            }
        }
       repo_search(repo, p, SOLVABLE_FILELIST, 0, flags, addfileprovides_cb, cbd);
     }
+  map_free(&providedids);
 }
 
 void
index ca355c8..848eb93 100644 (file)
@@ -514,7 +514,7 @@ repo_add_solv_flags(Repo *repo, FILE *fp, int flags)
       /* make sure that we exactly replace the stub repodata */
       if (parent->end - parent->start != numsolv)
        {
-         pool_debug(pool, SAT_ERROR, "sub-repository solvable number doesn't match main repository (%d - %d)\n", parent->end - parent->start, numsolv);
+         pool_debug(pool, SAT_ERROR, "sub-repository solvable number does not match main repository (%d - %d)\n", parent->end - parent->start, numsolv);
          return SOLV_ERROR_CORRUPT;
        }
       for (i = 0; i < numsolv; i++)
index b673e80..02a918d 100644 (file)
@@ -500,7 +500,8 @@ solver_addrpmrulesforsolvable(Solver *solv, Solvable *s, Map *m)
       dontfix = 0;
       if (installed                    /* Installed system available */
          && !solv->fixsystem           /* NOT repair errors in rpm dependency graph */
-         && s->repo == installed)      /* solvable is installed? */
+         && s->repo == installed       /* solvable is installed */
+         && (!solv->fixmap.size || !MAPTST(&solv->fixmap, n - installed->start)))
         {
          dontfix = 1;                  /* dont care about broken rpm deps */
         }
index 98f264d..be10f0b 100644 (file)
@@ -1289,6 +1289,7 @@ solver_free(Solver *solv)
   map_free(&solv->noobsoletes);
 
   map_free(&solv->updatemap);
+  map_free(&solv->fixmap);
   map_free(&solv->dupmap);
   map_free(&solv->dupinvolvedmap);
 
@@ -2429,6 +2430,30 @@ solver_solve(Solver *solv, Queue *job)
    */
   if (installed)
     {
+      /* check for verify jobs */
+      for (i = 0; i < job->count; i += 2)
+       {
+         how = job->elements[i];
+         what = job->elements[i + 1];
+         select = how & SOLVER_SELECTMASK;
+         switch (how & SOLVER_JOBMASK)
+           {
+           case SOLVER_VERIFY:
+             FOR_JOB_SELECT(p, pp, select, what)
+               {
+                 s = pool->solvables + p;
+                 if (!solv->installed || s->repo != solv->installed)
+                   continue;
+                 if (!solv->fixmap.size)
+                   map_grow(&solv->fixmap, solv->installed->end - solv->installed->start);
+                 MAPSET(&solv->fixmap, p - solv->installed->start);
+               }
+             break;
+           default:
+             break;
+           }
+       }
+
       oldnrules = solv->nrules;
       POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for installed solvables ***\n");
       FOR_REPO_SOLVABLES(installed, p, s)
@@ -2702,6 +2727,9 @@ solver_solve(Solver *solv, Queue *job)
              MAPSET(&solv->updatemap, p - solv->installed->start);
            }
          break;
+       case SOLVER_VERIFY:
+         POOL_DEBUG(SAT_DEBUG_JOB, "job: %sverify %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
+         break;
        case SOLVER_WEAKENDEPS:
          POOL_DEBUG(SAT_DEBUG_JOB, "job: %sweaken deps %s\n", weak ? "weak " : "", solver_select2str(solv, select, what));
          if (select != SOLVER_SOLVABLE)
index 7a92365..096d378 100644 (file)
@@ -81,7 +81,9 @@ typedef struct _Solver {
   Map noobsoletes;                     /* ignore obsoletes for these
                                           (multiinstall) */
 
-  Map updatemap;                       /* bring those packages to the newest version */
+  Map updatemap;                       /* bring those installed packages to the newest version */
+  Map fixmap;                          /* fix those packages */
+
   Queue weakruleq;                     /* index into 'rules' for weak ones */
   Map weakrulemap;                     /* map rule# to '1' for weak rules, 1..learntrules */
 
@@ -221,6 +223,7 @@ typedef struct _Solver {
 #define SOLVER_NOOBSOLETES             0x0500
 #define SOLVER_LOCK                    0x0600
 #define SOLVER_DISTUPGRADE             0x0700
+#define SOLVER_VERIFY                  0x0800
 
 #define SOLVER_JOBMASK                 0xff00