[devel] symlinks.req: semi-unmets

Alexey Tourbin =?iso-8859-1?q?at_=CE=C1_altlinux=2Eru?=
Сб Авг 11 20:26:47 MSD 2007


On Tue, Aug 07, 2007 at 02:20:48AM +0400, Alexey Tourbin wrote:
> On Mon, Aug 06, 2007 at 03:08:04PM +0400, Alexey Tourbin wrote:
> ЗАОСТРЯЮ ПРОБЛЕМУ "ПОЛУ-АНМЕТОВ".
> 
> 
> Это проблема проявляется тогда, когда зависимость имеет вид /ПУТЬ,
> но у соответствующего пакета не стоит Provides: /ПУТЬ.  На уровне
> rpm это не является unmet'ом: если при установке пакета с такой
> зависимостью имеется какой-либо другой пакет с файлом /ПУТЬ,
> то для rpm это "канает".
> 
> С другой стороны, apt видит такую зависимость именно как unmet.
> Вообще-то у апта к каждому пакету есть файловые листы, и он использует
> их для разрешения такого рода зависимостей.  Но при изготовлении
> репозитария аптовые листы у нас насильно "оптимизируются".
> 
> Два простых варианта решения это проблемы:
> 
> 1) Генерировать более полный content_index для hasher, чтобы любой путь
> более гарантированно трансформировался в название пакета (насколько
> более полный/гарантированно?).
> 
> 2) Восстановить файловые листы для апт.  Насколько потяжелеет
> pkglist.classic.bz2?

Я немного захачил апт, но это всё равно как следует не работает, см. ниже.

commit 30e27b0f1c74b4f67354a6035fae3e210131bca1
Author: Alexey Tourbin <at на altlinux>
Date:   Sat Aug 11 20:01:05 2007 +0400

    apt-0.5.15lorg2-alt-genpkglist-reqfiles.patch
    
    genpkglist strips file lists by default (without --bloat option).
    It keeps only some "useful files" by using a few ad hoc patterns.
    
    This can break file-level dependencies.  Consider pkgA requires
    /usr/lib/foo1/bar, and pkgB owns this file without explicitly
    providing it.  Now if genpkglist strips /usr/lib/foo1/bar
    from pkgB file list, this is going to be an unmet dependency.
    
    This patch changes genpkglist behaviour, so that, when genpkglist
    is invoked without --bloat option, it first finds all file-level
    dependencies (something like "rpm -qaR |grep ^/").  This requires
    a separate pass.  The list of file-level dependencies is saved into
    "reqfiles" global variable.  And on the second (normal) pass, the
    function usefulFile() is modified to check the "reqfiles" variable;
    that is, it should keep a file in the file list if it's been required
    by some package in the repo.
    
    (Unfortunately, this patch does not solve all of the problems
    I want it to solve; we have separate repos for i586 and noarch --
    inter-repo file-level dependencies cannot be resolved this way.)
----------- следующая часть -----------
--- apt-0.5.15lorg2/tools/genpkglist.cc-	2007-08-11 15:10:54 +0400
+++ apt-0.5.15lorg2/tools/genpkglist.cc	2007-08-11 19:36:03 +0400
@@ -18,6 +18,8 @@
 #include <map>
 #include <iostream>
 
+#include <tr1/unordered_set>
+
 #include <apt-pkg/error.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/configuration.h>
@@ -77,20 +79,30 @@ typedef struct {
    string url;
 } UpdateInfo;
 
+static std::tr1::unordered_set<std::string> reqfiles;
 
-static inline int usefullFile(char *a)
+static int usefulFile(const char *dir, const char *basename)
 {
-   int l = strlen(a);
-   
-   if (strstr(a, "bin") || strstr(a, "/etc") || strncmp(a, "/lib", 4) == 0)
-       return 1;
-   
-   if (l < 3)
-       return 0;
+   if (strstr(dir, "bin/"))
+      return 1;
+   if (strstr(dir, "/etc/"))
+      return 1;
    
-   if (strcmp(a + l - 3, ".so") == 0
-       || strstr(a, ".so."))
-       return 1;
+   const char *pos = strstr(basename, ".so");
+   if (pos > basename) {
+      int c = pos[3];
+      if (c == '.' || c == '\0')
+         return 1;
+   }
+
+   if (reqfiles.size() > 0) {
+      char fullname[strlen(dir) + strlen(basename) + 1];
+      strcpy(fullname, dir);
+      strcat(fullname, basename);
+      if (reqfiles.find(fullname) != reqfiles.end())
+         return 2;
+   }
+
    return 0;
 }
 
@@ -133,9 +145,8 @@ static void copyStrippedFileList(Header 
    {
       int ok = 0;
       
-      ok = usefullFile(basenames[i]);
-      if (!ok) 
-	  ok = usefullFile(dirnames[dirindexes[i]]);
+      ok = usefulFile(dirnames[dirindexes[i]], basenames[i]);
+      // if (ok > 1) cerr << "useful file: " << dirnames[dirindexes[i]] << basenames[i] <<endl;
       
       if (!ok) {
 	 int k = i;
@@ -599,6 +610,40 @@ int main(int argc, char ** argv) 
    int isSource;
 #endif   
 
+   if (!fullFileList) {
+      // first pass: initialize reqfiles
+      for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
+         fd = fdOpen(dirEntries[entry_cur]->d_name, O_RDONLY, 0666);
+         if (!fd)
+            continue;
+         int rc;
+         Header h;
+#if RPM_VERSION >= 0x040100
+         rc = rpmReadPackageFile(ts, fd, dirEntries[entry_cur]->d_name, &h);
+         if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY) {
+#else
+         rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
+         if (rc == 0) {
+#endif
+            int reqtype;
+            const char **requires;
+            int nreq;
+            rc = headerGetEntry(h, RPMTAG_REQUIRENAME, &reqtype, (void**)&requires, &nreq);
+            if (rc == 1 && reqtype == RPM_STRING_ARRAY_TYPE) {
+               int i;
+               for (i = 0; i < nreq; i++) {
+                  const char *req = requires[i];
+                  if (*req == '/') {
+                     // cerr << dirEntries[entry_cur]->d_name << " requires " << req << endl;
+                     reqfiles.insert(req);
+                  }
+               }
+            }
+            headerFree(h);
+         }
+         Fclose(fd);
+      }
+   }
    for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
       struct stat sb;
 
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип     : application/pgp-signature
Размер  : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url     : <http://lists.altlinux.org/pipermail/devel/attachments/20070811/11efb163/attachment-0001.bin>


Подробная информация о списке рассылки Devel