genpkglist: don't strip paths that are owned by 2 or more packages
Another attempt to deal with semi-unmet dependencies. This should fix most of the cross-arch semi-unmets generated via conetnts_index_all. Consider a few noarch packages which own /usr/share/foo. Now if i586 package somehow refers /usr/share/foo, contents_index_all search will produce as-is reference, which is going to be cross-arch semi-unmet. Note that if /usr/share/foo is owned by only one package, contents_index_all search will produce explicit package name. This is why genpkglist should not strip paths that are owned by 2 or more packages.
This commit is contained in:
parent
341bcecf1e
commit
bb7eaffe62
@ -1,5 +1,5 @@
|
||||
--- apt-0.5.15lorg2/tools/genpkglist.cc- 2007-08-11 21:39:13 +0400
|
||||
+++ apt-0.5.15lorg2/tools/genpkglist.cc 2007-08-11 21:47:17 +0400
|
||||
--- apt-0.5.15lorg2/tools/genpkglist.cc- 2007-10-08 03:24:54 +0400
|
||||
+++ apt-0.5.15lorg2/tools/genpkglist.cc 2007-10-08 22:29:14 +0400
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
@ -9,14 +9,17 @@
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/tagfile.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
@@ -77,20 +79,30 @@ typedef struct {
|
||||
@@ -77,20 +79,99 @@ typedef struct {
|
||||
string url;
|
||||
} UpdateInfo;
|
||||
|
||||
+static std::tr1::unordered_set<std::string> reqfiles;
|
||||
+// path-like Requires
|
||||
+static
|
||||
+std::tr1::unordered_set<std::string> reqfiles;
|
||||
|
||||
-static inline int usefullFile(char *a)
|
||||
+static int usefulFile(const char *dir, const char *basename)
|
||||
+static
|
||||
+void addRequiredPath(const char *str)
|
||||
{
|
||||
- int l = strlen(a);
|
||||
-
|
||||
@ -25,7 +28,71 @@
|
||||
-
|
||||
- if (l < 3)
|
||||
- return 0;
|
||||
+ if (strstr(dir, "bin/"))
|
||||
+ reqfiles.insert(str);
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+bool isRequiredPath(const char *dir, const char *basename)
|
||||
+{
|
||||
+ char fullname[strlen(dir) + strlen(basename) + 1];
|
||||
+ strcpy(fullname, dir);
|
||||
+ strcat(fullname, basename);
|
||||
+ if (reqfiles.find(fullname) != reqfiles.end())
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+// atoms are constant strings with fixed address
|
||||
+static
|
||||
+std::tr1::unordered_set<std::string> atoms;
|
||||
+
|
||||
+static
|
||||
+const char *atom(const char *str)
|
||||
+{
|
||||
+ return atoms.insert(str).first->c_str();
|
||||
+}
|
||||
+
|
||||
+// memory-efficient way to map path -> packages:
|
||||
+// dir -> <basename -> pkg+>
|
||||
+typedef std::multimap<const char * /* basename */, const char * /* pkg */> BPM;
|
||||
+static
|
||||
+std::map<const char * /* dir */, BPM> pathOwners;
|
||||
+
|
||||
+typedef BPM::const_iterator BPI;
|
||||
+
|
||||
+static
|
||||
+void addPathOwner(const char *dir, const char *basename, const char *pkg)
|
||||
+{
|
||||
+ BPM& bp = pathOwners[atom(dir)];
|
||||
+ basename = atom(basename);
|
||||
+ pkg = atom(pkg);
|
||||
+ // check if pkg is already there
|
||||
+ std::pair<BPI, BPI> ii = bp.equal_range(basename);
|
||||
+ for (BPI i = ii.first; i != ii.second; ++i) {
|
||||
+ if (i->second == pkg) {
|
||||
+ //fprintf(stderr, "already: %s%s %s\n", dir, basename, pkg);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ bp.insert(std::make_pair(basename, pkg));
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+int countPathOwners(const char *dir, const char *basename)
|
||||
+{
|
||||
+ BPM& bp = pathOwners[atom(dir)];
|
||||
+ basename = atom(basename);
|
||||
+ std::pair<BPI, BPI> ii = bp.equal_range(basename);
|
||||
+ return std::distance(ii.first, ii.second);
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+int usefulFile(const char *dir, const char *basename)
|
||||
+{
|
||||
+ // standard dirs
|
||||
+ if (strstr(dir, "/bin/"))
|
||||
+ return 1;
|
||||
+ if (strstr(dir, "/sbin/"))
|
||||
+ return 1;
|
||||
+ if (strstr(dir, "/etc/"))
|
||||
+ return 1;
|
||||
@ -33,6 +100,7 @@
|
||||
- if (strcmp(a + l - 3, ".so") == 0
|
||||
- || strstr(a, ".so."))
|
||||
- return 1;
|
||||
+ // libraries
|
||||
+ const char *pos = strstr(basename, ".so");
|
||||
+ if (pos > basename) {
|
||||
+ int c = pos[3];
|
||||
@ -40,35 +108,40 @@
|
||||
+ 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;
|
||||
+ }
|
||||
+ // if this path is required by any package, it is useful
|
||||
+ if (isRequiredPath(dir, basename))
|
||||
+ return 2;
|
||||
+
|
||||
+ // if the path is owned by two or more packages, it is still useful
|
||||
+ if (countPathOwners(dir, basename) > 1)
|
||||
+ return 3;
|
||||
+
|
||||
+ // other paths are not useful
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -133,9 +145,8 @@ static void copyStrippedFileList(Header
|
||||
@@ -131,11 +212,8 @@ static void copyStrippedFileList(Header
|
||||
i2 = 0;
|
||||
for (i = 0; i < count2 ; i++)
|
||||
{
|
||||
int ok = 0;
|
||||
|
||||
- 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;
|
||||
+ int ok = usefulFile(dirnames[dirindexes[i]], basenames[i]);
|
||||
+ // if (ok > 1) cerr << "useful(" << ok <<"): " << dirnames[dirindexes[i]] << basenames[i] << std::endl;
|
||||
|
||||
if (!ok) {
|
||||
int k = i;
|
||||
@@ -599,6 +610,50 @@ int main(int argc, char ** argv)
|
||||
@@ -599,6 +677,76 @@ int main(int argc, char ** argv)
|
||||
int isSource;
|
||||
#endif
|
||||
|
||||
+ if (!fullFileList) {
|
||||
+ // first pass: initialize reqfiles
|
||||
+ // ALT: file list cannot be stripped in a dumb manner -- this is going
|
||||
+ // to produce unmet dependencies. First pass is required to initialize
|
||||
+ // certain data structures.
|
||||
+ for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
|
||||
+ if (progressBar) {
|
||||
+ if (entry_cur)
|
||||
@ -89,9 +162,10 @@
|
||||
+ rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
|
||||
+ if (rc == 0) {
|
||||
+#endif
|
||||
+ int reqtype;
|
||||
+ const char **requires;
|
||||
+ int nreq;
|
||||
+ // path-like Requires
|
||||
+ int_32 reqtype = 0;
|
||||
+ const char **requires = NULL;
|
||||
+ int_32 nreq = 0;
|
||||
+ rc = headerGetEntry(h, RPMTAG_REQUIRENAME, &reqtype, (void**)&requires, &nreq);
|
||||
+ if (rc == 1) {
|
||||
+ if (reqtype == RPM_STRING_ARRAY_TYPE) {
|
||||
@ -100,12 +174,35 @@
|
||||
+ const char *req = requires[i];
|
||||
+ if (*req == '/') {
|
||||
+ // cerr << dirEntries[entry_cur]->d_name << " requires " << req << endl;
|
||||
+ reqfiles.insert(req);
|
||||
+ addRequiredPath(req);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ headerFreeTag(h, requires, (rpmTagType)reqtype);
|
||||
+ }
|
||||
+ headerFreeTag(h, requires, (rpmTagType)reqtype);
|
||||
+
|
||||
+ // path ownership
|
||||
+ const char *pkg = NULL;
|
||||
+ int_32 pkgt = 0;
|
||||
+ const char **bn = NULL, **dn = NULL;
|
||||
+ int_32 *di = NULL;
|
||||
+ int_32 bnt = 0, dnt = 0, dit = 0;
|
||||
+ int_32 bnc = 0;
|
||||
+ rc = headerGetEntry(h, RPMTAG_NAME, &pkgt, (void**)&pkg, NULL)
|
||||
+ && headerGetEntry(h, RPMTAG_BASENAMES, &bnt, (void**)&bn, &bnc)
|
||||
+ && headerGetEntry(h, RPMTAG_DIRNAMES, &dnt, (void**)&dn, NULL)
|
||||
+ && headerGetEntry(h, RPMTAG_DIRINDEXES, &dit, (void**)&di, NULL)
|
||||
+ ;
|
||||
+ if (rc == 1) {
|
||||
+ int i;
|
||||
+ for (i = 0; i < bnc; i++)
|
||||
+ addPathOwner(dn[di[i]], bn[i], pkg);
|
||||
+ }
|
||||
+ headerFreeTag(h, pkg, (rpmTagType)pkgt);
|
||||
+ headerFreeTag(h, bn, (rpmTagType)bnt);
|
||||
+ headerFreeTag(h, dn, (rpmTagType)dnt);
|
||||
+ headerFreeTag(h, di, (rpmTagType)dit);
|
||||
+
|
||||
+ headerFree(h);
|
||||
+ }
|
||||
+ Fclose(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user