diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-09-10 15:38:34 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-09-10 15:38:34 +0900 |
commit | 2491213c77850ed26991b572809a5ca4a61fa89b (patch) | |
tree | cd2e4928ad52795bc4a318a0721f487c282a33be | |
parent | 0e46e80434781d1acbc4f5716827bf8688450a30 (diff) | |
download | libsolv-2491213c77850ed26991b572809a5ca4a61fa89b.tar.gz libsolv-2491213c77850ed26991b572809a5ca4a61fa89b.tar.bz2 libsolv-2491213c77850ed26991b572809a5ca4a61fa89b.zip |
Imported Upstream version 0.7.0upstream/0.7.0
108 files changed, 3332 insertions, 2743 deletions
@@ -1,7 +0,0 @@ - -Having the same key in multiple repodatas of a repo does not work -- searching will return both entries -- repo_write will write a broken solv file -Fixing the search so that it only returns the last entry will also -fix repo_write. - diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c6a1be..1deef57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ OPTION (ENABLE_LZMA_COMPRESSION "Build with lzma/xz compression support?" OFF) OPTION (ENABLE_BZIP2_COMPRESSION "Build with bzip2 compression support?" OFF) OPTION (ENABLE_ZSTD_COMPRESSION "Build with zstd compression support?" OFF) OPTION (ENABLE_ZCHUNK_COMPRESSION "Build with zchunk compression support?" OFF) - +OPTION (WITH_SYSTEM_ZCHUNK "Use system zchunk library?" OFF) OPTION (WITH_LIBXML2 "Build with libxml2 instead of libexpat?" OFF) # Library @@ -156,6 +156,12 @@ IF (ENABLE_ARCHREPO OR ENABLE_DEBIAN) SET (ENABLE_LZMA_COMPRESSION ON) ENDIF (ENABLE_ARCHREPO OR ENABLE_DEBIAN) +IF (WITH_SYSTEM_ZCHUNK) +SET (ENABLE_ZCHUNK_COMPRESSION ON) +FIND_PACKAGE(PkgConfig REQUIRED) +PKG_CHECK_MODULES(ZCHUNK zck REQUIRED) +ENDIF (WITH_SYSTEM_ZCHUNK) + IF (ENABLE_ZCHUNK_COMPRESSION) SET (ENABLE_ZSTD_COMPRESSION ON) ENDIF (ENABLE_ZCHUNK_COMPRESSION) @@ -294,7 +300,8 @@ FOREACH (VAR ENABLE_SUSEREPO ENABLE_COMPS ENABLE_TESTCASE_HELIXREPO ENABLE_HELIXREPO ENABLE_MDKREPO ENABLE_ARCHREPO ENABLE_DEBIAN ENABLE_HAIKU ENABLE_ZLIB_COMPRESSION ENABLE_LZMA_COMPRESSION ENABLE_BZIP2_COMPRESSION - ENABLE_ZSTD_COMPRESSION ENABLE_ZCHUNK_COMPRESSION ENABLE_PGPVRFY ENABLE_APPDATA) + ENABLE_ZSTD_COMPRESSION ENABLE_ZCHUNK_COMPRESSION ENABLE_PGPVRFY ENABLE_APPDATA + WITH_SYSTEM_ZCHUNK) IF(${VAR}) ADD_DEFINITIONS (-D${VAR}=1) SET (SWIG_FLAGS ${SWIG_FLAGS} -D${VAR}) @@ -399,6 +406,9 @@ ENDIF (ENABLE_BZIP2_COMPRESSION) IF (ENABLE_ZSTD_COMPRESSION) SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${ZSTD_LIBRARY}) ENDIF (ENABLE_ZSTD_COMPRESSION) +IF (WITH_SYSTEM_ZCHUNK) +SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${ZCHUNK_LIBRARIES}) +ENDIF (WITH_SYSTEM_ZCHUNK) IF (ENABLE_RPMDB) SET (SYSTEM_LIBRARIES ${RPMDB_LIBRARY} ${SYSTEM_LIBRARIES}) ENDIF (ENABLE_RPMDB) @@ -2,17 +2,23 @@ This file contains the major changes between libsolv versions: -Version 0.6.36 -- bug fixes: - * do not autouninstall packages because of forcebest updates - * fixed a couple of null pointer derefs and potential memory - leaks - * no longer disable infarch rules when they don't conflict with - the job - * fix cleandeps updates not updating all packages - * fix SOLVER_FLAG_FOCUS_BEST updateing packages without reason - * be more correct with multiversion packages that obsolete their - own name +Version 0.7.0 +- soname bump to "1" +- incompatible API changes: + * bindings: Selection.flags is now an attribute + * repodata_lookup_num now works like the other lookup_num functions +- new functions: + * selection_make_matchsolvable + * selection_make_matchsolvablelist + * pool_whatmatchessolvable + * repodata_search_arrayelement + * repodata_lookup_kv_uninternalized + * repodata_search_uninternalized + * repodata_translate_dir +- new repowriter interface to write solv files allowing better + control over what gets written +- support for filtered file lists with a custom filter +- dropped support of (since a long time unused) REPOKEY_TYPE_U32 Version 0.6.35 - new configuration options: @@ -1,6 +1,4 @@ -- make dataiterator only return the last occurance of a key - - implement package priority (for things like Debian's pin feature) - merge SUSETAGS_FILE_* and REPOSITORY_REPOMD_* keys into REPOSITORY_RESOURCE @@ -11,18 +9,10 @@ - drop patchcheck -- rename repo2solv.sh to repo2solv (maybe rewrite in C?) - -- obey -A option in repo2solv - - make FAVOR handling deal with versions - write more manpages -- bindings: selection.flags() should be a attribute and not a method - -- rename repodata_lookup_id_uninternalized to repodata_lookup_id_voidid_uninternalized - and add a notfound argument - IDEAS: +drop SEARCH_FILES and add SEARCH_BASENAME instead? diff --git a/VERSION.cmake b/VERSION.cmake index d866276..6ed2c6f 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -44,10 +44,10 @@ # set COMPATMINOR to MINOR. (binary incompatible change) # -SET(LIBSOLV_SOVERSION "0") -SET(LIBSOLVEXT_SOVERSION "0") +SET(LIBSOLV_SOVERSION "1") +SET(LIBSOLVEXT_SOVERSION "1") SET(LIBSOLV_MAJOR "0") -SET(LIBSOLV_MINOR "6") -SET(LIBSOLV_PATCH "36") +SET(LIBSOLV_MINOR "7") +SET(LIBSOLV_PATCH "0") diff --git a/bindings/solv.i b/bindings/solv.i index 8fb469f..1a88917 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -954,6 +954,7 @@ typedef int Id; typedef struct { Pool* const pool; + int const flags; } Selection; typedef struct { @@ -1288,9 +1289,6 @@ typedef struct { queue_free(&$self->q); solv_free($self); } - int flags() { - return $self->flags; - } #ifdef SWIGRUBY %rename("isempty?") isempty; #endif @@ -3727,7 +3725,7 @@ rb_eval_string( int steptype(XSolvable *s, int mode) { return transaction_type($self, s->id, mode); } - int calc_installsizechange() { + long long calc_installsizechange() { return transaction_calc_installsizechange($self); } void order(int flags=0) { @@ -3870,9 +3868,15 @@ rb_eval_string( void set_id(Id solvid, Id keyname, DepId id) { repodata_set_id(repo_id2repodata($self->repo, $self->id), solvid, keyname, id); } + void set_num(Id solvid, Id keyname, unsigned long long num) { + repodata_set_num(repo_id2repodata($self->repo, $self->id), solvid, keyname, num); + } void set_str(Id solvid, Id keyname, const char *str) { repodata_set_str(repo_id2repodata($self->repo, $self->id), solvid, keyname, str); } + void set_void(Id solvid, Id keyname) { + repodata_set_void(repo_id2repodata($self->repo, $self->id), solvid, keyname); + } void set_poolstr(Id solvid, Id keyname, const char *str) { repodata_set_poolstr(repo_id2repodata($self->repo, $self->id), solvid, keyname, str); } @@ -3890,9 +3894,24 @@ rb_eval_string( void set_sourcepkg(Id solvid, const char *sourcepkg) { repodata_set_sourcepkg(repo_id2repodata($self->repo, $self->id), solvid, sourcepkg); } + void set_location(Id solvid, unsigned int mediano, const char *location) { + repodata_set_location(repo_id2repodata($self->repo, $self->id), solvid, mediano, 0, location); + } + void unset(Id solvid, Id keyname) { + repodata_unset(repo_id2repodata($self->repo, $self->id), solvid, keyname); + } const char *lookup_str(Id solvid, Id keyname) { return repodata_lookup_str(repo_id2repodata($self->repo, $self->id), solvid, keyname); } + Id lookup_id(Id solvid, Id keyname) { + return repodata_lookup_id(repo_id2repodata($self->repo, $self->id), solvid, keyname); + } + unsigned long long lookup_num(Id solvid, Id keyname, unsigned long long notfound = 0) { + return repodata_lookup_num(repo_id2repodata($self->repo, $self->id), solvid, keyname, notfound); + } + bool lookup_void(Id solvid, Id keyname) { + return repodata_lookup_void(repo_id2repodata($self->repo, $self->id), solvid, keyname); + } Queue lookup_idarray(Id solvid, Id keyname) { Queue r; queue_init(&r); diff --git a/doc/gen/helix2solv.1 b/doc/gen/helix2solv.1 index dacc5fe..1f37339 100644 --- a/doc/gen/helix2solv.1 +++ b/doc/gen/helix2solv.1 @@ -2,12 +2,12 @@ .\" Title: helix2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "HELIX2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "HELIX2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/installcheck.1 b/doc/gen/installcheck.1 index 7965f00..492bd80 100644 --- a/doc/gen/installcheck.1 +++ b/doc/gen/installcheck.1 @@ -2,12 +2,12 @@ .\" Title: installcheck .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "INSTALLCHECK" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "INSTALLCHECK" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/libsolv-bindings.3 b/doc/gen/libsolv-bindings.3 index 7ca0bb5..4bfab9c 100644 --- a/doc/gen/libsolv-bindings.3 +++ b/doc/gen/libsolv-bindings.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-Bindings .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 06/15/2018 +.\" Date: 10/24/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV\-BINDINGS" "3" "06/15/2018" "libsolv" "LIBSOLV" +.TH "LIBSOLV\-BINDINGS" "3" "10/24/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2392,8 +2392,8 @@ my \fI$string\fR \fB=\fR \fI$solvable\fR\fB\->lookup_str(\fR\fI$keyname\fR\fB)\f .nf \fBId lookup_id(Id\fR \fIkeyname\fR\fB)\fR my \fI$id\fR \fB=\fR \fI$solvable\fR\fB\->lookup_id(\fR\fI$keyname\fR\fB)\fR; -\fIid\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_id(\fR\fIsolvid\fR\fB)\fR -\fIid\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_id(\fR\fIsolvid\fR\fB)\fR +\fIid\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_id(\fR\fIkeyname\fR\fB)\fR +\fIid\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_id(\fR\fIkeyname\fR\fB)\fR .fi .if n \{\ .RE @@ -2403,7 +2403,7 @@ my \fI$id\fR \fB=\fR \fI$solvable\fR\fB\->lookup_id(\fR\fI$keyname\fR\fB)\fR; .RS 4 .\} .nf -\fBunsigned long long lookup_num(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, unsigned long long\fR \fInotfound\fR \fB= 0)\fR +\fBunsigned long long lookup_num(Id\fR \fIkeyname\fR\fB, unsigned long long\fR \fInotfound\fR \fB= 0)\fR my \fI$num\fR \fB=\fR \fI$solvable\fR\fB\->lookup_num(\fR\fI$keyname\fR\fB)\fR; \fInum\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_num(\fR\fIkeyname\fR\fB)\fR \fInum\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_num(\fR\fIkeyname\fR\fB)\fR @@ -2471,9 +2471,9 @@ Generic lookup methods\&. Retrieve data stored for the specific keyname\&. The l .\} .nf \fBconst char *lookup_location(unsigned int *\fR\fIOUTPUT\fR\fB)\fR; -my \fB(\fR\fI$location\fR\fB,\fR \fI$medianr\fR\fB) =\fR \fI$solvable\fR\fB\->lookup_location()\fR; -\fIlocation\fR\fB,\fR \fImedianr\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_location()\fR -\fIlocation\fR\fB,\fR \fImedianr\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_location()\fR +my \fB(\fR\fI$location\fR\fB,\fR \fI$mediano\fR\fB) =\fR \fI$solvable\fR\fB\->lookup_location()\fR; +\fIlocation\fR\fB,\fR \fImediano\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_location()\fR +\fIlocation\fR\fB,\fR \fImediano\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_location()\fR .fi .if n \{\ .RE @@ -3161,22 +3161,22 @@ Intersect the result of the match to the current selection instead of replacing .\} .sp Back pointer to pool\&. -.SS "METHODS" .sp .if n \{\ .RS 4 .\} .nf -\fBint flags()\fR -my \fI$flags\fR \fB=\fR \fI$sel\fR\fB\->flags()\fR; -\fIflags\fR \fB=\fR \fIsel\fR\fB\&.flags()\fR -\fIflags\fR \fB=\fR \fIsel\fR\fB\&.flags()\fR +\fBint flags;\fR /* read only */ +\fI$sel\fR\fB\->{flags}\fR +\fIflags\fR \fB=\fR \fIsel\fR\fB\&.flags\fR +\fIflags\fR \fB=\fR \fIsel\fR\fB\&.flags\fR .fi .if n \{\ .RE .\} .sp -Return the result flags of the selection\&. The flags are a subset of the ones used when creating the selection, they describe which method was used to get the result\&. For example, if you create the selection with \(lqSELECTION_NAME | SELECTION_PROVIDES\(rq, the resulting flags will either be SELECTION_NAME or SELECTION_PROVIDES depending if there was a package that matched the name or not\&. If there was no match at all, the flags will be zero\&. +The result flags of the selection\&. The flags are a subset of the ones used when creating the selection, they describe which method was used to get the result\&. For example, if you create the selection with \(lqSELECTION_NAME | SELECTION_PROVIDES\(rq, the resulting flags will either be SELECTION_NAME or SELECTION_PROVIDES depending if there was a package that matched the name or not\&. If there was no match at all, the flags will be zero\&. +.SS "METHODS" .sp .if n \{\ .RS 4 @@ -5049,7 +5049,7 @@ For installed packages, returns all of the packages that replace us\&. For to be .RS 4 .\} .nf -\fBint calc_installsizechange()\fR; +\fBlong long calc_installsizechange()\fR; my \fI$change\fR \fB=\fR \fI$trans\fR\fB\->calc_installsizechange()\fR; \fIchange\fR \fB=\fR \fItrans\fR\fB\&.calc_installsizechange()\fR \fIchange\fR \fB=\fR \fItrans\fR\fB\&.calc_installsizechange()\fR @@ -5739,6 +5739,45 @@ my \fI$string\fR \fB=\fR \fI$data\fR\fB\->lookup_str(\fR\fI$solvid\fR\fB,\fR \fI .RS 4 .\} .nf +\fBconst char *lookup_id(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB)\fR +my \fI$string\fR \fB=\fR \fI$data\fR\fB\->lookup_id(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; +\fIstring\fR \fB=\fR \fIdata\fR\fB\&.lookup_id(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +\fIstring\fR \fB=\fR \fIdata\fR\fB\&.lookup_id(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf +\fBunsigned long long lookup_num(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, unsigned long long\fR \fInotfound\fR \fB= 0)\fR +my \fI$num\fR \fB=\fR \fI$data\fR\fB\->lookup_num(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; +\fInum\fR \fB=\fR \fIdata\fR\fB\&.lookup_num(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +\fInum\fR \fB=\fR \fIdata\fR\fB\&.lookup_num(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf +\fBbool lookup_void(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB)\fR +my \fI$bool\fR \fB=\fR \fI$data\fR\fB\->lookup_void(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; +\fIbool\fR \fB=\fR \fIdata\fR\fB\&.lookup_void(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +\fIbool\fR \fB=\fR \fIdata\fR\fB\&.lookup_void(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf \fBId *lookup_idarray(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB)\fR my \fI@ids\fR \fB=\fR \fI$data\fR\fB\->lookup_idarray(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; \fIids\fR \fB=\fR \fIdata\fR\fB\&.lookup_idarray(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR @@ -5768,6 +5807,19 @@ Lookup functions\&. Return the data element stored in the specified solvable\&. .RS 4 .\} .nf +\fBvoid set_str(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, const char *\fR\fIstr\fR\fB)\fR; +\fI$data\fR\fB\->set_str(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB,\fR \fI$str\fR\fB)\fR; +\fIdata\fR\fB\&.set_str(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIstr\fR\fB)\fR +\fIdata\fR\fB\&.set_str(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIstr\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf \fBvoid set_id(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, DepId\fR \fIid\fR\fB)\fR; \fI$data\fR\fB\->set_id(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB,\fR \fI$id\fR\fB)\fR; \fIdata\fR\fB\&.set_id(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIid\fR\fB)\fR @@ -5781,10 +5833,23 @@ Lookup functions\&. Return the data element stored in the specified solvable\&. .RS 4 .\} .nf -\fBvoid set_str(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, const char *\fR\fIstr\fR\fB)\fR; -\fI$data\fR\fB\->set_str(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB,\fR \fI$str\fR\fB)\fR; -\fIdata\fR\fB\&.set_str(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIstr\fR\fB)\fR -\fIdata\fR\fB\&.set_str(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIstr\fR\fB)\fR +\fBvoid set_num(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, unsigned long long\fR \fInum\fR\fB)\fR; +\fI$data\fR\fB\->set_num(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB,\fR \fI$num\fR\fB)\fR; +\fIdata\fR\fB\&.set_num(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fInum\fR\fB)\fR +\fIdata\fR\fB\&.set_num(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fInum\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf +\fBvoid set_void(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB)\fR; +\fI$data\fR\fB\->set_void(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; +\fIdata\fR\fB\&.set_void(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +\fIdata\fR\fB\&.set_void(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR .fi .if n \{\ .RE @@ -5833,6 +5898,19 @@ Lookup functions\&. Return the data element stored in the specified solvable\&. .RS 4 .\} .nf +\fBvoid set_location(Id\fR \fIsolvid\fR\fB, unsigned int\fR \fImediano\fR\fB, const char *\fR\fIlocation\fR\fB)\fR; +\fI$data\fR\fB\&.set_location(\fR\fI$solvid\fR\fB,\fR \fI$mediano\fR\fB,\fR \fI$location\fR\fB)\fR; +\fIdata\fR\fB\&.set_location(\fR\fIsolvid\fR\fB,\fR \fImediano\fR\fB,\fR \fIlocation\fR\fB)\fR +\fIdata\fR\fB\&.set_location(\fR\fIsolvid\fR\fB,\fR \fImediano\fR\fB,\fR \fIlocation\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp +.if n \{\ +.RS 4 +.\} +.nf \fBvoid add_idarray(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB, DepId\fR \fIid\fR\fB)\fR; \fI$data\fR\fB\->add_idarray(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB,\fR \fI$id\fR\fB)\fR; \fIdata\fR\fB\&.add_idarray(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB,\fR \fIid\fR\fB)\fR @@ -5868,6 +5946,19 @@ my \fI$handle\fR \fB=\fR \fI$data\fR\fB\->new_handle()\fR; .RE .\} .sp +.if n \{\ +.RS 4 +.\} +.nf +\fBvoid unset(Id\fR \fIsolvid\fR\fB, Id\fR \fIkeyname\fR\fB)\fR; +\fI$data\fR\fB\->unset(\fR\fI$solvid\fR\fB,\fR \fI$keyname\fR\fB)\fR; +\fIdata\fR\fB\&.unset(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +\fIdata\fR\fB\&.unset(\fR\fIsolvid\fR\fB,\fR \fIkeyname\fR\fB)\fR +.fi +.if n \{\ +.RE +.\} +.sp Data storage methods\&. Probably only useful to store data in the special SOLVID_META solvid that stores repodata meta information\&. Note that repodata areas can have their own Id pool (see the REPO_LOCALPOOL flag), so be careful if you need to store ids\&. Arrays are created by calling the add function for every element\&. A flexarray is an array of sub\-structures, call new_handle to create a new structure, use the handle as solvid to fill the structure with data and call add_flexarray to put the structure in an array\&. .SH "THE DATAPOS CLASS" .sp @@ -5910,9 +6001,9 @@ Create a Dataiterator at the position of the datapos object\&. .\} .nf \fBconst char *lookup_deltalocation(unsigned int *\fR\fIOUTPUT\fR\fB)\fR; -my \fB(\fR\fI$location\fR\fB,\fR \fI$medianr\fR\fB) =\fR \fI$datapos\fR\fB\->lookup_deltalocation()\fR; -\fIlocation\fR\fB,\fR \fImedianr\fR \fB=\fR \fIdatapos\fR\fB\&.lookup_deltalocation()\fR -\fIlocation\fR\fB,\fR \fImedianr\fR \fB=\fR \fIdatapos\fR\fB\&.lookup_deltalocation()\fR +my \fB(\fR\fI$location\fR\fB,\fR \fI$mediano\fR\fB) =\fR \fI$datapos\fR\fB\->lookup_deltalocation()\fR; +\fIlocation\fR\fB,\fR \fImediano\fR \fB=\fR \fIdatapos\fR\fB\&.lookup_deltalocation()\fR +\fIlocation\fR\fB,\fR \fImediano\fR \fB=\fR \fIdatapos\fR\fB\&.lookup_deltalocation()\fR .fi .if n \{\ .RE diff --git a/doc/gen/libsolv-constantids.3 b/doc/gen/libsolv-constantids.3 index 87a14e6..228dfdd 100644 --- a/doc/gen/libsolv-constantids.3 +++ b/doc/gen/libsolv-constantids.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-Constantids .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV\-CONSTANTIDS" "3" "08/04/2017" "libsolv" "LIBSOLV" +.TH "LIBSOLV\-CONSTANTIDS" "3" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/libsolv-history.3 b/doc/gen/libsolv-history.3 index 6a600ac..fc2d69b 100644 --- a/doc/gen/libsolv-history.3 +++ b/doc/gen/libsolv-history.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-History .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV\-HISTORY" "3" "08/04/2017" "libsolv" "LIBSOLV" +.TH "LIBSOLV\-HISTORY" "3" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/libsolv-pool.3 b/doc/gen/libsolv-pool.3 index c64eeb1..51dc1a4 100644 --- a/doc/gen/libsolv-pool.3 +++ b/doc/gen/libsolv-pool.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-Pool .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 07/16/2018 +.\" Date: 10/22/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV\-POOL" "3" "07/16/2018" "libsolv" "LIBSOLV" +.TH "LIBSOLV\-POOL" "3" "10/22/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/libsolv.3 b/doc/gen/libsolv.3 index dcebb02..a6ac359 100644 --- a/doc/gen/libsolv.3 +++ b/doc/gen/libsolv.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV" "3" "08/04/2017" "libsolv" "LIBSOLV" +.TH "LIBSOLV" "3" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/mdk2solv.1 b/doc/gen/mdk2solv.1 index 513187a..ac593f1 100644 --- a/doc/gen/mdk2solv.1 +++ b/doc/gen/mdk2solv.1 @@ -2,12 +2,12 @@ .\" Title: mdk2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "MDK2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "MDK2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/mergesolv.1 b/doc/gen/mergesolv.1 index 1c706c7..65fd756 100644 --- a/doc/gen/mergesolv.1 +++ b/doc/gen/mergesolv.1 @@ -2,12 +2,12 @@ .\" Title: mergesolv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "MERGESOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "MERGESOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/repo2solv.1 b/doc/gen/repo2solv.1 index 5f21465..0a8c3cf 100644 --- a/doc/gen/repo2solv.1 +++ b/doc/gen/repo2solv.1 @@ -2,12 +2,12 @@ .\" Title: repo2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 07/16/2018 +.\" Date: 10/22/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "REPO2SOLV" "1" "07/16/2018" "libsolv" "LIBSOLV" +.TH "REPO2SOLV" "1" "10/22/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/repomdxml2solv.1 b/doc/gen/repomdxml2solv.1 index aeac7bd..5d459cc 100644 --- a/doc/gen/repomdxml2solv.1 +++ b/doc/gen/repomdxml2solv.1 @@ -2,12 +2,12 @@ .\" Title: repomdxml2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "REPOMDXML2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "REPOMDXML2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/rpmdb2solv.1 b/doc/gen/rpmdb2solv.1 index 79c6d26..6f84a7f 100644 --- a/doc/gen/rpmdb2solv.1 +++ b/doc/gen/rpmdb2solv.1 @@ -2,12 +2,12 @@ .\" Title: rpmdb2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "RPMDB2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "RPMDB2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/rpmmd2solv.1 b/doc/gen/rpmmd2solv.1 index 44ea70f..5149a1c 100644 --- a/doc/gen/rpmmd2solv.1 +++ b/doc/gen/rpmmd2solv.1 @@ -2,12 +2,12 @@ .\" Title: rpmmd2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "RPMMD2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "RPMMD2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/rpms2solv.1 b/doc/gen/rpms2solv.1 index 11b3671..75a89f3 100644 --- a/doc/gen/rpms2solv.1 +++ b/doc/gen/rpms2solv.1 @@ -2,12 +2,12 @@ .\" Title: rpms2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "RPMS2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "RPMS2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/solv.1 b/doc/gen/solv.1 index b61538d..aae1c6d 100644 --- a/doc/gen/solv.1 +++ b/doc/gen/solv.1 @@ -2,12 +2,12 @@ .\" Title: solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 07/19/2018 +.\" Date: 10/22/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "SOLV" "1" "07/19/2018" "libsolv" "LIBSOLV" +.TH "SOLV" "1" "10/22/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/susetags2solv.1 b/doc/gen/susetags2solv.1 index 43a616a..8dd83d4 100644 --- a/doc/gen/susetags2solv.1 +++ b/doc/gen/susetags2solv.1 @@ -2,12 +2,12 @@ .\" Title: susetags2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "SUSETAGS2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "SUSETAGS2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/testsolv.1 b/doc/gen/testsolv.1 index 158aedc..50254f7 100644 --- a/doc/gen/testsolv.1 +++ b/doc/gen/testsolv.1 @@ -2,12 +2,12 @@ .\" Title: testsolv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "TESTSOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "TESTSOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/gen/updateinfoxml2solv.1 b/doc/gen/updateinfoxml2solv.1 index cd0386d..aa60372 100644 --- a/doc/gen/updateinfoxml2solv.1 +++ b/doc/gen/updateinfoxml2solv.1 @@ -2,12 +2,12 @@ .\" Title: updateinfoxml2solv .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 08/04/2017 +.\" Date: 09/14/2018 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "UPDATEINFOXML2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV" +.TH "UPDATEINFOXML2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/doc/libsolv-bindings.txt b/doc/libsolv-bindings.txt index 5db1116..d28b8b5 100644 --- a/doc/libsolv-bindings.txt +++ b/doc/libsolv-bindings.txt @@ -1342,10 +1342,10 @@ a specific id and want to avoid the string compare overhead. Id lookup_id(Id keyname) my $id = $solvable->lookup_id($keyname); - id = solvable.lookup_id(solvid) - id = solvable.lookup_id(solvid) + id = solvable.lookup_id(keyname) + id = solvable.lookup_id(keyname) - unsigned long long lookup_num(Id solvid, Id keyname, unsigned long long notfound = 0) + unsigned long long lookup_num(Id keyname, unsigned long long notfound = 0) my $num = $solvable->lookup_num($keyname); num = solvable.lookup_num(keyname) num = solvable.lookup_num(keyname) @@ -1382,9 +1382,9 @@ array, use 1 to select the second part or 0 to retrieve all ids including the marker. const char *lookup_location(unsigned int *OUTPUT); - my ($location, $medianr) = $solvable->lookup_location(); - location, medianr = solvable.lookup_location() - location, medianr = solvable.lookup_location() + my ($location, $mediano) = $solvable->lookup_location(); + location, mediano = solvable.lookup_location() + location, mediano = solvable.lookup_location() Return a tuple containing the on-media location and an optional media number for multi-part repositories (e.g. repositories @@ -1780,14 +1780,12 @@ Intersect the result of the match to the current selection instead of replacing Back pointer to pool. -=== METHODS === - - int flags() - my $flags = $sel->flags(); - flags = sel.flags() - flags = sel.flags() + int flags; /* read only */ + $sel->{flags} + flags = sel.flags + flags = sel.flags -Return the result flags of the selection. The flags are a subset +The result flags of the selection. The flags are a subset of the ones used when creating the selection, they describe which method was used to get the result. For example, if you create the selection with ``SELECTION_NAME | SELECTION_PROVIDES'', the resulting @@ -1795,6 +1793,8 @@ flags will either be SELECTION_NAME or SELECTION_PROVIDES depending if there was a package that matched the name or not. If there was no match at all, the flags will be zero. +=== METHODS === + bool isempty() $sel->isempty() sel.isempty() @@ -3128,7 +3128,7 @@ be installed packages, returns all of the packages that the new package replaces. The special ``other'' solvable is always the first entry of the returned array. - int calc_installsizechange(); + long long calc_installsizechange(); my $change = $trans->calc_installsizechange(); change = trans.calc_installsizechange() change = trans.calc_installsizechange() @@ -3520,6 +3520,21 @@ the same id. string = data.lookup_str(solvid, keyname) string = data.lookup_str(solvid, keyname) + const char *lookup_id(Id solvid, Id keyname) + my $string = $data->lookup_id($solvid, $keyname); + string = data.lookup_id(solvid, keyname) + string = data.lookup_id(solvid, keyname) + + unsigned long long lookup_num(Id solvid, Id keyname, unsigned long long notfound = 0) + my $num = $data->lookup_num($solvid, $keyname); + num = data.lookup_num(solvid, keyname) + num = data.lookup_num(solvid, keyname) + + bool lookup_void(Id solvid, Id keyname) + my $bool = $data->lookup_void($solvid, $keyname); + bool = data.lookup_void(solvid, keyname) + bool = data.lookup_void(solvid, keyname) + Id *lookup_idarray(Id solvid, Id keyname) my @ids = $data->lookup_idarray($solvid, $keyname); ids = data.lookup_idarray(solvid, keyname) @@ -3536,15 +3551,25 @@ SOLVID_META solvid that stores repodata meta information. === DATA STORAGE METHODS === + void set_str(Id solvid, Id keyname, const char *str); + $data->set_str($solvid, $keyname, $str); + data.set_str(solvid, keyname, str) + data.set_str(solvid, keyname, str) + void set_id(Id solvid, Id keyname, DepId id); $data->set_id($solvid, $keyname, $id); data.set_id(solvid, keyname, id) data.set_id(solvid, keyname, id) - void set_str(Id solvid, Id keyname, const char *str); - $data->set_str($solvid, $keyname, $str); - data.set_str(solvid, keyname, str) - data.set_str(solvid, keyname, str) + void set_num(Id solvid, Id keyname, unsigned long long num); + $data->set_num($solvid, $keyname, $num); + data.set_num(solvid, keyname, num) + data.set_num(solvid, keyname, num) + + void set_void(Id solvid, Id keyname); + $data->set_void($solvid, $keyname); + data.set_void(solvid, keyname) + data.set_void(solvid, keyname) void set_poolstr(Id solvid, Id keyname, const char *str); $data->set_poolstr($solvid, $keyname, $str); @@ -3561,6 +3586,11 @@ SOLVID_META solvid that stores repodata meta information. data.set_sourcepkg(solvid, sourcepkg) data.set_sourcepkg(solvid, sourcepkg) + void set_location(Id solvid, unsigned int mediano, const char *location); + $data.set_location($solvid, $mediano, $location); + data.set_location(solvid, mediano, location) + data.set_location(solvid, mediano, location) + void add_idarray(Id solvid, Id keyname, DepId id); $data->add_idarray($solvid, $keyname, $id); data.add_idarray(solvid, keyname, id) @@ -3576,6 +3606,11 @@ SOLVID_META solvid that stores repodata meta information. data.add_flexarray(solvid, keyname, handle) data.add_flexarray(solvid, keyname, handle) + void unset(Id solvid, Id keyname); + $data->unset($solvid, $keyname); + data.unset(solvid, keyname) + data.unset(solvid, keyname) + Data storage methods. Probably only useful to store data in the special SOLVID_META solvid that stores repodata meta information. Note that repodata areas can have their own Id pool (see the REPO_LOCALPOOL flag), @@ -3612,9 +3647,9 @@ Back pointer to repository object. Create a Dataiterator at the position of the datapos object. const char *lookup_deltalocation(unsigned int *OUTPUT); - my ($location, $medianr) = $datapos->lookup_deltalocation(); - location, medianr = datapos.lookup_deltalocation() - location, medianr = datapos.lookup_deltalocation() + my ($location, $mediano) = $datapos->lookup_deltalocation(); + location, mediano = datapos.lookup_deltalocation() + location, mediano = datapos.lookup_deltalocation() Return a tuple containing the on-media location and an optional media number for a delta rpm. This obviously only works if the data position points to diff --git a/doc/rpmdb2solv.txt b/doc/rpmdb2solv.txt index 128e179..ad8314f 100644 --- a/doc/rpmdb2solv.txt +++ b/doc/rpmdb2solv.txt @@ -47,9 +47,6 @@ standard directory is */etc/products.d*. Do not read any packages from the rpm database. This is useful together with *-p* to only convert SUSE products. -*-C*:: -Include the package changelog in the generated solv file. - *-X*:: Autoexpand SUSE pattern and product provides into packages. diff --git a/examples/p5solv b/examples/p5solv index 9e90670..6f54247 100755 --- a/examples/p5solv +++ b/examples/p5solv @@ -582,8 +582,8 @@ for my $arg (@ARGV) { print "[ignoring case for '$arg']\n" unless $sel->isempty(); } die("nothing matches '$arg'\n") if $sel->isempty(); - print "[using file list match for '$arg']\n" if $sel->flags() & $solv::Selection::SELECTION_FILELIST; - print "[using capability match for '$arg']\n" if $sel->flags() & $solv::Selection::SELECTION_PROVIDES; + print "[using file list match for '$arg']\n" if $sel->{flags} & $solv::Selection::SELECTION_FILELIST; + print "[using capability match for '$arg']\n" if $sel->{flags} & $solv::Selection::SELECTION_PROVIDES; push @jobs, $sel->jobs($cmdactionmap{$cmd}); } diff --git a/examples/pysolv b/examples/pysolv index 891c237..75067f2 100755 --- a/examples/pysolv +++ b/examples/pysolv @@ -717,9 +717,9 @@ for arg in args: if sel.isempty(): print("nothing matches '%s'" % arg) sys.exit(1) - if sel.flags() & solv.Selection.SELECTION_FILELIST: + if sel.flags & solv.Selection.SELECTION_FILELIST: print("[using file list match for '%s']" % arg) - if sel.flags() & solv.Selection.SELECTION_PROVIDES: + if sel.flags & solv.Selection.SELECTION_PROVIDES: print("[using capability match for '%s']" % arg) jobs += sel.jobs(cmdactionmap[cmd]) diff --git a/examples/solv/fastestmirror.c b/examples/solv/fastestmirror.c index 0ee4e73..d2ebd97 100644 --- a/examples/solv/fastestmirror.c +++ b/examples/solv/fastestmirror.c @@ -68,11 +68,7 @@ findfastest(char **urls, int nurls) socks[i] = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (socks[i] >= 0) { - if (fcntl(socks[i], F_SETFL, O_NONBLOCK) == -1) - { - close(socks[i]); - socks[i] = -1; - } + fcntl(socks[i], F_SETFL, O_NONBLOCK); if (connect(socks[i], result->ai_addr, result->ai_addrlen) == -1) { if (errno != EINPROGRESS) diff --git a/examples/solv/solv.c b/examples/solv/solv.c index 42ab751..3deb1a0 100644 --- a/examples/solv/solv.c +++ b/examples/solv/solv.c @@ -130,7 +130,7 @@ showdiskusagechanges(Transaction *trans) duc[3].path = "/etc"; transaction_calc_duchanges(trans, duc, 4); for (i = 0; i < 4; i++) - printf("duchanges %s: %d K %d inodes\n", duc[i].path, duc[i].kbytes, duc[i].files); + printf("duchanges %s: %lld K %lld inodes\n", duc[i].path, duc[i].kbytes, duc[i].files); } #endif @@ -169,7 +169,6 @@ find_repo(const char *name, Pool *pool, struct repoinfo *repoinfos, int nrepoinf return 0; } - #define MODE_LIST 0 #define MODE_INSTALL 1 #define MODE_ERASE 2 @@ -227,6 +226,7 @@ main(int argc, char **argv) char *rootdir = 0; char *keyname = 0; int keyname_depstr = 0; + int keyname_alldeps = 0; /* dnf repoquesy --alldeps */ int debuglevel = 0; int answer, acnt = 0; char *testcase = 0; @@ -316,9 +316,15 @@ main(int argc, char **argv) argc--; argv++; } + else if (argc > 1 && !strcmp(argv[1], "--alldeps")) + { + keyname_alldeps = 1; /* dnf repoquesy --alldeps */ + argc--; + argv++; + } else if (argc > 1 && !strcmp(argv[1], "--depstr")) { - keyname_depstr = 1; + keyname_depstr = 1; /* do literal matching instead of dep intersection */ argc--; argv++; } @@ -539,7 +545,7 @@ main(int argc, char **argv) flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0); if (keyname && keyname_depstr) flags |= SELECTION_MATCH_DEPSTR; - if (!keyname) + if (!keyname || keyname_alldeps) rflags = selection_make(pool, &job2, argv[i], flags); else rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); @@ -552,7 +558,7 @@ main(int argc, char **argv) if (!job2.count) { flags |= SELECTION_NOCASE; - if (!keyname) + if (!keyname || keyname_alldeps) rflags = selection_make(pool, &job2, argv[i], flags); else rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0); @@ -574,6 +580,14 @@ main(int argc, char **argv) printf("[using file list match for '%s']\n", argv[i]); if (rflags & SELECTION_PROVIDES) printf("[using capability match for '%s']\n", argv[i]); + if (keyname && keyname_alldeps) + { + Queue q; + queue_init(&q); + selection_solvables(pool, &job2, &q); + selection_make_matchsolvablelist(pool, &job2, &q, 0, pool_str2id(pool, keyname, 1), 0); + queue_free(&q); + } queue_insertn(&job, job.count, job2.count, job2.elements); queue_free(&job2); } @@ -773,7 +787,7 @@ rerunsolver: #if defined(SUSE) showdiskusagechanges(trans); #endif - printf("install size change: %d K\n", transaction_calc_installsizechange(trans)); + printf("install size change: %lld K\n", transaction_calc_installsizechange(trans)); printf("\n"); acnt = solver_alternatives_count(solv); diff --git a/ext/repo_appdata.c b/ext/repo_appdata.c index 62faf2d..03098e2 100644 --- a/ext/repo_appdata.c +++ b/ext/repo_appdata.c @@ -467,13 +467,40 @@ repo_add_appdata(Repo *repo, FILE *fp, int flags) return repo_add_appdata_fn(repo, fp, flags, 0, 0); } +struct uninternalized_filelist_data { + Id did; + Queue *res; +}; + +static int +search_uninternalized_filelist_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +{ + struct uninternalized_filelist_data *uf = cbdata; + const char *str; + Id id; + size_t l; + if (key->type != REPOKEY_TYPE_DIRSTRARRAY || kv->id != uf->did) + return 0; + str = kv->str; + l = strlen(str); + if (l > 12 && strncmp(str + l - 12, ".appdata.xml", 12)) + id = pool_str2id(data->repo->pool, str, 1); + else if (l > 13 && strncmp(str + l - 13, ".metainfo.xml", 13)) + id = pool_str2id(data->repo->pool, str, 1); + else + return 0; + queue_push2(uf->res, s - data->repo->pool->solvables, id); + return 0; +} + static void search_uninternalized_filelist(Repo *repo, const char *dir, Queue *res) { Pool *pool = repo->pool; - Id rdid, p; - Id iter, did, idid; + Id did, rdid, p; + struct uninternalized_filelist_data uf; + uf.res = res; for (rdid = 1; rdid < repo->nrepodata; rdid++) { Repodata *data = repo_id2repodata(repo, rdid); @@ -486,31 +513,12 @@ search_uninternalized_filelist(Repo *repo, const char *dir, Queue *res) did = repodata_str2dir(data, dir, 0); if (!did) continue; + uf.did = did; for (p = data->start; p < data->end; p++) { - if (p >= pool->nsolvables) + if (p >= pool->nsolvables || pool->solvables[p].repo != repo) continue; - if (pool->solvables[p].repo != repo) - continue; - iter = 0; - for (;;) - { - const char *str; - int l; - Id id; - idid = did; - str = repodata_lookup_dirstrarray_uninternalized(data, p, SOLVABLE_FILELIST, &idid, &iter); - if (!iter) - break; - l = strlen(str); - if (l > 12 && strncmp(str + l - 12, ".appdata.xml", 12)) - id = pool_str2id(pool, str, 1); - else if (l > 13 && strncmp(str + l - 13, ".metainfo.xml", 13)) - id = pool_str2id(pool, str, 1); - else - continue; - queue_push2(res, p, id); - } + repodata_search_uninternalized(data, p, SOLVABLE_FILELIST, 0, search_uninternalized_filelist_cb, &uf); } } } diff --git a/ext/repo_autopattern.c b/ext/repo_autopattern.c index 7cef78c..f6e1004 100644 --- a/ext/repo_autopattern.c +++ b/ext/repo_autopattern.c @@ -103,8 +103,8 @@ repo_add_autopattern(Repo *repo, int flags) if (repo == pool->installed) flags |= ADD_NO_AUTOPRODUCTS; /* no auto products for installed repos */ - pattern_id = pool_str2id(pool, "pattern()", 1); - product_id = pool_str2id(pool, "product()", 1); + pattern_id = pool_str2id(pool, "pattern()", 9); + product_id = pool_str2id(pool, "product()", 9); FOR_REPO_SOLVABLES(repo, p, s) { const char *n = pool_id2str(pool, s->name); diff --git a/ext/repo_pubkey.h b/ext/repo_pubkey.h index dbc7f9c..26cf0e1 100644 --- a/ext/repo_pubkey.h +++ b/ext/repo_pubkey.h @@ -19,7 +19,7 @@ extern int repo_add_keyring(Repo *repo, FILE *fp, int flags); extern int repo_add_keydir(Repo *repo, const char *keydir, const char *suffix, int flags); /* signature parsing */ -typedef struct _solvsig { +typedef struct s_Solvsig { unsigned char *sigpkt; int sigpktl; Id htype; diff --git a/ext/repo_repomdxml.c b/ext/repo_repomdxml.c index b2a5b8d..760d481 100644 --- a/ext/repo_repomdxml.c +++ b/ext/repo_repomdxml.c @@ -181,7 +181,7 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha while (value) { char *p = strchr(value, ','); - if (p) + if (*p) *p++ = 0; if (*value) repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_UPDATES, value); diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index daf22e9..a2d518f 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -1385,44 +1385,6 @@ copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) return ido; } -#define COPYDIR_DIRCACHE_SIZE 512 - -static Id copydir_complex(Repodata *data, Repodata *fromdata, Id did, Id *cache); - -static inline Id -copydir(Repodata *data, Repodata *fromdata, Id did, Id *cache) -{ - if (cache && did && cache[did & 255] == did) - return cache[(did & 255) + 256]; - return copydir_complex(data, fromdata, did, cache); -} - -static Id -copydir_complex(Repodata *data, Repodata *fromdata, Id did, Id *cache) -{ - Id parent, compid; - if (!did) - { - /* make sure that the dirpool has an entry */ - if (!data->dirpool.ndirs) - dirpool_add_dir(&data->dirpool, 0, 0, 1); - return 0; - } - parent = dirpool_parent(&fromdata->dirpool, did); - compid = dirpool_compid(&fromdata->dirpool, did); - if (parent) - parent = copydir(data, fromdata, parent, cache); - if (data->localpool || fromdata->localpool) - compid = repodata_translate_id(data, fromdata, compid, 1); - compid = dirpool_add_dir(&data->dirpool, parent, compid, 1); - if (cache) - { - cache[did & 255] = did; - cache[(did & 255) + 256] = compid; - } - return compid; -} - struct solvable_copy_cbdata { Repodata *data; Id handle; @@ -1447,23 +1409,19 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K break; case REPOKEY_TYPE_DIRNUMNUMARRAY: case REPOKEY_TYPE_DIRSTRARRAY: - kv->id = copydir(data, fromdata, kv->id, cbdata->dircache); + kv->id = repodata_translate_dir(data, fromdata, kv->id, 1, fromdata->repodataid == 1 ? cbdata->dircache : 0); break; + case REPOKEY_TYPE_FIXARRAY: + cbdata->handle = repodata_new_handle(data); + repodata_add_fixarray(data, handle, key->name, cbdata->handle); + repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); + cbdata->handle = handle; + return 0; case REPOKEY_TYPE_FLEXARRAY: - if (kv->eof == 2) - { - assert(cbdata->subhandle); - cbdata->handle = cbdata->subhandle; - cbdata->subhandle = 0; - break; - } - if (!kv->entry) - { - assert(!cbdata->subhandle); - cbdata->subhandle = cbdata->handle; - } cbdata->handle = repodata_new_handle(data); - repodata_add_flexarray(data, cbdata->subhandle, key->name, cbdata->handle); + repodata_add_flexarray(data, handle, key->name, cbdata->handle); + repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); + cbdata->handle = handle; return 0; default: break; @@ -1473,13 +1431,14 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K } static void -solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) +solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache, Id **oldkeyskip) { int p, i; Repo *repo = s->repo; Pool *pool = repo->pool; Repo *fromrepo = r->repo; struct solvable_copy_cbdata cbdata; + Id *keyskip; /* copy solvable data */ s->name = r->name; @@ -1507,19 +1466,15 @@ solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) { Repodata *fromdata = repo_id2repodata(fromrepo, 1); if (p >= fromdata->start && p < fromdata->end) - repodata_search(fromdata, p, 0, SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); + repodata_search(fromdata, p, 0, 0, solvable_copy_cb, &cbdata); return; } -#if 0 - repo_search(fromrepo, p, 0, 0, SEARCH_NO_STORAGE_SOLVABLE | SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); -#else + keyskip = repo_create_keyskip(repo, p, oldkeyskip); FOR_REPODATAS(fromrepo, i, data) { if (p >= data->start && p < data->end) - repodata_search(data, p, 0, SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); - cbdata.dircache = 0; /* only for first repodata */ + repodata_search_keyskip(data, p, 0, 0, keyskip, solvable_copy_cb, &cbdata); } -#endif } /* used to sort entries by package name that got returned in some database order */ @@ -1731,7 +1686,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) } else { - Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */ + Id *dircache; + Id *oldkeyskip = 0; struct rpmdbentry *entries = 0, *rp; int nentries = 0; char *namedata = 0; @@ -1739,8 +1695,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) Id id, *refhash; int res; - memset(dircache, 0, sizeof(dircache)); - /* get ids of installed rpms */ entries = getinstalledrpmdbids(&state, "Name", 0, &nentries, &namedata, flags & RPMDB_KEEP_GPG_PUBKEY); if (!entries) @@ -1795,10 +1749,11 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); + dircache = repodata_create_dirtranscache(data); for (i = 0, rp = entries; i < nentries; i++, rp++, s++) { Id dbid = rp->rpmdbid; - repo->rpmdbid[(s - pool->solvables) - repo->start] = rp->rpmdbid; + repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; if (refhash) { h = dbid & refmask; @@ -1813,7 +1768,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) Solvable *r = ref->pool->solvables + ref->start + (id - 1); if (r->repo == ref) { - solvable_copy(s, r, data, dircache); + solvable_copy(s, r, data, dircache, &oldkeyskip); continue; } } @@ -1827,6 +1782,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) solv_free(entries); solv_free(namedata); solv_free(refhash); + dircache = repodata_free_dirtranscache(dircache); return -1; } rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS); @@ -1838,7 +1794,9 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) pool_debug(pool, SOLV_ERROR, "%%%% %d\n", done * 100 / count); } } + dircache = repodata_free_dirtranscache(dircache); + solv_free(oldkeyskip); solv_free(entries); solv_free(namedata); solv_free(refhash); @@ -1939,8 +1897,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) { pool_error(pool, -1, "%s: not a rpm", rpm); - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -1953,16 +1909,12 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (lead[78] != 0 || lead[79] != 5) { pool_error(pool, -1, "%s: not a rpm v5 header", rpm); - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } if (getu32(lead + 96) != 0x8eade801) { pool_error(pool, -1, "%s: bad signature header", rpm); - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -1971,8 +1923,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE) { pool_error(pool, -1, "%s: bad signature header", rpm); - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -1983,8 +1933,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) { if (!headfromfp(&state, rpm, fp, lead + 96, sigcnt, sigdsize, sigpad, chksumh, leadsigchksumh)) { - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -2024,8 +1972,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (fread(lead, l, 1, fp) != 1) { pool_error(pool, -1, "%s: unexpected EOF", rpm); - solv_chksum_free(leadsigchksumh, 0); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -2046,7 +1992,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (fread(lead, 16, 1, fp) != 1) { pool_error(pool, -1, "%s: unexpected EOF", rpm); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -2055,7 +2000,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (getu32(lead) != 0x8eade801) { pool_error(pool, -1, "%s: bad header", rpm); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -2064,7 +2008,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE) { pool_error(pool, -1, "%s: bad header", rpm); - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } @@ -2072,7 +2015,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) if (!headfromfp(&state, rpm, fp, lead, sigcnt, sigdsize, 0, chksumh, 0)) { - solv_chksum_free(chksumh, 0); fclose(fp); return 0; } diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c index 6c05281..9f49bd3 100644 --- a/ext/repo_rpmmd.c +++ b/ext/repo_rpmmd.c @@ -603,17 +603,18 @@ static void fill_cshash_from_new_solvables(struct parsedata *pd) { Pool *pool = pd->pool; - Id cstype = 0; - unsigned const char *cs; - int i; + int i, l; + KeyValue kv; + Repokey *key; for (i = pd->first; i < pool->nsolvables; i++) { if (pool->solvables[i].repo != pd->repo) continue; - cs = repodata_lookup_bin_checksum_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &cstype); - if (cs) - put_in_cshash(pd, cs, solv_chksum_len(cstype), i); + if ((key = repodata_lookup_kv_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &kv)) == 0) + continue; + if ((l = solv_chksum_len(key->type)) != 0) + put_in_cshash(pd, (const unsigned char *)kv.str, l, i); } } @@ -1144,6 +1145,22 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) repodata_free_dircache(data); queue_free(&pd.diskusageq); + if ((flags & REPO_EXTEND_SOLVABLES) != 0) + { + /* is this a filelist extension? */ + if (repodata_has_keyname(data, SOLVABLE_FILELIST)) + repodata_set_filelisttype(data, REPODATA_FILELIST_EXTENSION); + } + else + { + /* is this a primary with a filtered filelist? */ + if (data->end > data->start) + { + repodata_set_filelisttype(data, REPODATA_FILELIST_FILTERED); + repodata_set_void(data, SOLVID_META, REPOSITORY_FILTEREDFILELIST); + } + } + if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", solv_timems(now)); diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c index 52d5e5e..561c789 100644 --- a/ext/repo_susetags.c +++ b/ext/repo_susetags.c @@ -333,7 +333,16 @@ lookup_shared_id(Repodata *data, Id p, Id keyname, Id voidid, int uninternalized return r; } if (uninternalized) - return repodata_lookup_id_uninternalized(data, p, keyname, voidid); + { + KeyValue kv; + Repokey *key = repodata_lookup_kv_uninternalized(data, p, keyname, &kv); + if (!key) + return 0; + if (key->type == REPOKEY_TYPE_VOID) + return voidid; + if (key->type == REPOKEY_TYPE_ID) + return kv.id; + } return 0; } @@ -1062,6 +1071,23 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int solv_free(joinhash); repodata_free_dircache(data); + + if ((flags & REPO_EXTEND_SOLVABLES) != 0) + { + /* is this a filelist extension? */ + if (repodata_has_keyname(data, SOLVABLE_FILELIST)) + repodata_set_filelisttype(data, REPODATA_FILELIST_EXTENSION); + } + else + { + /* is this a primary with a filtered filelist? */ + if (data->end > data->start) + { + repodata_set_filelisttype(data, REPODATA_FILELIST_FILTERED); + repodata_set_void(data, SOLVID_META, REPOSITORY_FILTEREDFILELIST); + } + } + if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c index a74762f..343aed8 100644 --- a/ext/solv_xfopen.c +++ b/ext/solv_xfopen.c @@ -504,7 +504,69 @@ static inline FILE *myzstdfdopen(int fd, const char *mode) #ifdef ENABLE_ZCHUNK_COMPRESSION +#ifdef WITH_SYSTEM_ZCHUNK +/* use the system's zchunk library that supports reading and writing of zchunk files */ + +#include <zck.h> + +static ssize_t cookie_zckread(void *cookie, char *buf, size_t nbytes) +{ + return zck_read((zckCtx *)cookie, buf, nbytes); +} + +static ssize_t cookie_zckwrite(void *cookie, const char *buf, size_t nbytes) +{ + return zck_write((zckCtx *)cookie, buf, nbytes); +} + +static int cookie_zckclose(void *cookie) +{ + zckCtx *zck = (zckCtx *)cookie; + int fd = zck_get_fd(zck); + if (fd != -1) + close(fd); + zck_free(&zck); + return 0; +} + +static void *zchunkopen(const char *path, const char *mode, int fd) +{ + zckCtx *f; + + if (!path && fd < 0) + return 0; + if (fd == -1) + { + if (*mode != 'w') + fd = open(path, O_RDONLY); + else + fd = open(path, O_WRONLY | O_CREAT, 0666); + if (fd == -1) + return 0; + } + f = zck_create(); + if (!f) + { + close(fd); + return 0; + } + if (*mode != 'w') + { + if(!zck_init_read(f, fd)) + return 0; + } + else + { + if(!zck_init_write(f, fd)) + return 0; + } + return cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose); +} + +#else + #include "solv_zchunk.h" +/* use the libsolv's limited zchunk implementation that only supports reading of zchunk files */ static void *zchunkopen(const char *path, const char *mode, int fd) { @@ -512,20 +574,22 @@ static void *zchunkopen(const char *path, const char *mode, int fd) void *f; if (!path && fd < 0) return 0; - if (strcmp(mode, "r") != 0) - return 0; if (fd != -1) fp = fdopen(fd, mode); else fp = fopen(path, mode); if (!fp) return 0; + if (strcmp(mode, "r") != 0) + return 0; f = solv_zchunk_open(fp, 1); if (!f) fclose(fp); return cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close); } +#endif + static inline FILE *myzchunkfopen(const char *fn, const char *mode) { return zchunkopen(fn, mode, -1); @@ -536,7 +600,8 @@ static inline FILE *myzchunkfdopen(int fd, const char *mode) return zchunkopen(0, mode, fd); } -#endif +#endif /* ENABLE_ZCHUNK_COMPRESSION */ + FILE * solv_xfopen(const char *fn, const char *mode) @@ -584,7 +649,7 @@ solv_xfopen(const char *fn, const char *mode) if (suf && !strcmp(suf, ".zck")) return myzchunkfopen(fn, mode); #else - if (suf && !strcmp(suf, ".zst")) + if (suf && !strcmp(suf, ".zck")) return 0; #endif return fopen(fn, mode); @@ -649,7 +714,7 @@ solv_xfopen_fd(const char *fn, int fd, const char *mode) if (suf && !strcmp(suf, ".zck")) return myzchunkfdopen(fd, simplemode); #else - if (suf && !strcmp(suf, ".zst")) + if (suf && !strcmp(suf, ".zck")) return 0; #endif return fdopen(fd, mode); diff --git a/ext/testcase.c b/ext/testcase.c index 0bac26b..ffc8b8a 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -174,6 +174,9 @@ static struct selflags2str { { SELECTION_MATCH_DEPSTR, "depstr" }, { SELECTION_WITH_DISABLED, "withdisabled" }, { SELECTION_WITH_BADARCH, "withbadarch" }, + { SELECTION_ADD, "add" }, + { SELECTION_SUBTRACT, "subtract" }, + { SELECTION_FILTER, "filter" }, { 0, 0 } }; @@ -571,8 +574,6 @@ testcase_str2dep_complex(Pool *pool, const char **sp, int relop) Id flags, id, id2, namespaceid = 0; struct oplist *op; - if (!s) - return 0; while (*s == ' ' || *s == '\t') s++; if (!strncmp(s, "namespace:", 10)) @@ -1070,7 +1071,7 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) Queue q; job |= SOLVER_SOLVABLE_ONE_OF; queue_init(&q); - if (npieces > 2 && strcmp(pieces[2], "nothing") != 0) + if (npieces > 3 && strcmp(pieces[2], "nothing") != 0) { for (i = 2; i < npieces; i++) { @@ -1129,11 +1130,15 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp) return job; } +#define SELECTIONJOB_MATCHDEPS 1 +#define SELECTIONJOB_MATCHDEPID 2 +#define SELECTIONJOB_MATCHSOLVABLE 3 + static int -addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue, int keyname) +addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue, int type, int keyname) { Id job; - int i, r; + int i, r = 0; int selflags; Queue sel; char *sp; @@ -1163,12 +1168,20 @@ addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue, int key if (*sp == 0) *sp = ' '; queue_init(&sel); - if (keyname > 0) - r = selection_make_matchdeps(pool, &sel, pieces[2], selflags, keyname, 0); - else if (keyname < 0) - r = selection_make_matchdepid(pool, &sel, testcase_str2dep(pool, pieces[2]), selflags, -keyname, 0); - else + if (selflags & (SELECTION_ADD | SELECTION_SUBTRACT | SELECTION_FILTER)) + { + for (i = 0; i < jobqueue->count; i += 2) + queue_push2(&sel, jobqueue->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK), jobqueue->elements[i + 1]); + queue_empty(jobqueue); + } + if (!type) r = selection_make(pool, &sel, pieces[2], selflags); + else if (type == SELECTIONJOB_MATCHDEPS) + r = selection_make_matchdeps(pool, &sel, pieces[2], selflags, keyname, 0); + else if (type == SELECTIONJOB_MATCHDEPID) + r = selection_make_matchdepid(pool, &sel, testcase_str2dep(pool, pieces[2]), selflags, keyname, 0); + else if (type == SELECTIONJOB_MATCHSOLVABLE) + r = selection_make_matchsolvable(pool, &sel, testcase_str2solvid(pool, pieces[2]), selflags, keyname, 0); for (i = 0; i < sel.count; i += 2) queue_push2(jobqueue, job | sel.elements[i], sel.elements[i + 1]); queue_free(&sel); @@ -2015,7 +2028,7 @@ testcase_solverresult(Solver *solv, int resultflags) if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB) { const char *js = testcase_job2str(pool, rq.elements[i + 2], rq.elements[i + 3]); - char *s = pool_tmpjoin(pool, altprefix, num, "job "); + char *s = pool_tmpjoin(pool, altprefix, num, " job "); s = pool_tmpappend(pool, s, js, 0); strqueue_push(&sq, s); } @@ -2025,13 +2038,6 @@ testcase_solverresult(Solver *solv, int resultflags) s = pool_tmpappend(pool, s, " requires ", testcase_dep2str(pool, rq.elements[i + 3])); strqueue_push(&sq, s); } - else if (rtype == SOLVER_RULE_UPDATE || rtype == SOLVER_RULE_FEATURE) - { - const char *js = testcase_solvid2str(pool, rq.elements[i + 1]); - char *s = pool_tmpjoin(pool, altprefix, num, "update "); - s = pool_tmpappend(pool, s, js, 0); - strqueue_push(&sq, s); - } } } for (i = 0; i < q.count; i++) @@ -2179,7 +2185,7 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha Id lowscore; FILE *fp; Strqueue sq; - char *cmd, *out, *result; + char *cmd, *out; const char *s; if (!testcasename) @@ -2314,6 +2320,7 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) != 0) { + char *result; cmd = 0; for (i = 0; resultflags2str[i].str; i++) if ((resultflags & resultflags2str[i].flag) != 0) @@ -2324,6 +2331,7 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha result = testcase_solverresult(solv, resultflags); if (!strcmp(resultname, "<inline>")) { + int i; Strqueue rsq; strqueue_init(&rsq); strqueue_split(&rsq, result); @@ -2355,7 +2363,6 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha if (fclose(fp)) { pool_error(solv->pool, 0, "testcase_write: write error"); - solv_free(result); strqueue_free(&sq); return 0; } @@ -2363,29 +2370,29 @@ testcase_write_mangled(Solver *solv, const char *dir, int resultflags, const cha solv_free(result); } - result = strqueue_join(&sq); - strqueue_free(&sq); + cmd = strqueue_join(&sq); out = pool_tmpjoin(pool, dir, "/", testcasename); if (!(fp = fopen(out, "w"))) { pool_error(solv->pool, 0, "testcase_write: could not open '%s' for writing", out); - solv_free(result); + strqueue_free(&sq); return 0; } - if (*result && fwrite(result, strlen(result), 1, fp) != 1) + if (*cmd && fwrite(cmd, strlen(cmd), 1, fp) != 1) { pool_error(solv->pool, 0, "testcase_write: write error"); - solv_free(result); + strqueue_free(&sq); fclose(fp); return 0; } if (fclose(fp)) { pool_error(solv->pool, 0, "testcase_write: write error"); - solv_free(result); + strqueue_free(&sq); return 0; } - solv_free(result); + solv_free(cmd); + strqueue_free(&sq); return 1; } @@ -2743,19 +2750,25 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res } if (npieces >= 3 && !strcmp(pieces[2], "selection")) { - addselectionjob(pool, pieces + 1, npieces - 1, job, 0); + addselectionjob(pool, pieces + 1, npieces - 1, job, 0, 0); continue; } if (npieces >= 4 && !strcmp(pieces[2], "selection_matchdeps")) { pieces[2] = pieces[1]; - addselectionjob(pool, pieces + 2, npieces - 2, job, pool_str2id(pool, pieces[3], 1)); + addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHDEPS, pool_str2id(pool, pieces[3], 1)); continue; } if (npieces >= 4 && !strcmp(pieces[2], "selection_matchdepid")) { pieces[2] = pieces[1]; - addselectionjob(pool, pieces + 2, npieces - 2, job, -pool_str2id(pool, pieces[3], 1)); + addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHDEPID, pool_str2id(pool, pieces[3], 1)); + continue; + } + if (npieces >= 4 && !strcmp(pieces[2], "selection_matchsolvable")) + { + pieces[2] = pieces[1]; + addselectionjob(pool, pieces + 2, npieces - 2, job, SELECTIONJOB_MATCHSOLVABLE, pool_str2id(pool, pieces[3], 1)); continue; } /* rejoin */ @@ -2774,7 +2787,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res { int i = strlen(pieces[1]); s = strchr(pieces[1], '('); - if (!s || pieces[1][i - 1] != ')') + if (!s && pieces[1][i - 1] != ')') { pool_error(pool, 0, "testcase_read: bad namespace '%s'", pieces[1]); } diff --git a/package/libsolv.changes b/package/libsolv.changes index dcdbabd..6146e99 100644 --- a/package/libsolv.changes +++ b/package/libsolv.changes @@ -1,20 +1,11 @@ ------------------------------------------------------------------- -Thu Jun 27 16:36:00 CEST 2019 - mls@suse.de - -- make cleandeps jobs on patterns work [bnc#1137977] -- fix SOLVER_FLAG_FOCUS_BEST updateing packages without reason -- be more correct with multiversion packages that obsolete their - own name [bnc#1127155] -- always prefer to stay with the same package name if there are - multiple alternatives [bnc#1131823] -- fix cleandeps updates not updating all packages -- fixed a couple of null pointer derefs - [bnc#1120629] [bnc#1120630] [bnc#1120631] - [CVE-2018-20532] [CVE-2018-20533] [CVE-2018-20534] -- no longer disable infarch rules when they don't conflict with - the job -- do not autouninstall packages because of forcebest updates -- bump version to 0.6.36 +Wed Oct 24 10:48:56 CEST 2018 - mls@suse.de + +- new repowriter interface +- new selection_make_matchsolvable function +- dropped support of REPOKEY_TYPE_U32 +- bindings: Selection.flags is now an attribute +- bump version to 0.7.0 ------------------------------------------------------------------- Thu Aug 9 17:09:41 CEST 2018 - mls@suse.de diff --git a/package/libsolv.spec.in b/package/libsolv.spec.in index 63d8f38..dd35ea9 100644 --- a/package/libsolv.spec.in +++ b/package/libsolv.spec.in @@ -24,7 +24,7 @@ %bcond_with bz2 %bcond_with xz %endif -%if 0%{?is_opensuse} && ( 0%{?sle_version} >= 150000 || 0%{?suse_version} >= 1500 ) +%if 0%{?is_opensuse} && (0%{?sle_version} >= 150000 || 0%{?suse_version} >= 1500) %bcond_without zstd %else %bcond_with zstd diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8951f6..2e32968 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ SET (libsolv_SRCS transaction.c order.c rules.c problems.c linkedpkg.c cplxdeps.c chksum.c md5.c sha1.c sha2.c solvversion.c selection.c fileprovides.c diskusage.c suse.c solver_util.c cleandeps.c - userinstalled.c) + userinstalled.c filelistfilter.c) SET (libsolv_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h diff --git a/src/bitmap.h b/src/bitmap.h index 1e89590..6609678 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef struct _Map { +typedef struct s_Map { unsigned char *map; int size; } Map; diff --git a/src/chksum.c b/src/chksum.c index 935aea8..df46145 100644 --- a/src/chksum.c +++ b/src/chksum.c @@ -19,7 +19,7 @@ #include "sha1.h" #include "sha2.h" -struct _Chksum { +struct s_Chksum { Id type; int done; unsigned char result[64]; diff --git a/src/chksum.h b/src/chksum.h index 479923a..65b775b 100644 --- a/src/chksum.h +++ b/src/chksum.h @@ -14,8 +14,8 @@ extern "C" { #endif -struct _Chksum; -typedef struct _Chksum Chksum; +struct s_Chksum; +typedef struct s_Chksum Chksum; Chksum *solv_chksum_create(Id type); Chksum *solv_chksum_create_clone(Chksum *chk); diff --git a/src/cleandeps.c b/src/cleandeps.c index ef9a528..1da28f6 100644 --- a/src/cleandeps.c +++ b/src/cleandeps.c @@ -837,7 +837,7 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) if (MAPTST(&solv->multiversion, p)) break; if (p) - continue; /* found a multiversion package that will not obsolate anything */ + continue; } om.size = 0; diff --git a/src/dataiterator.h b/src/dataiterator.h index 3133686..0649258 100644 --- a/src/dataiterator.h +++ b/src/dataiterator.h @@ -20,9 +20,9 @@ extern "C" { #endif -struct _Repo; +struct s_Repo; -typedef struct _KeyValue { +typedef struct s_KeyValue { Id id; const char *str; unsigned int num; @@ -31,7 +31,7 @@ typedef struct _KeyValue { int entry; /* array entry, starts with 0 */ int eof; /* last entry reached */ - struct _KeyValue *parent; + struct s_KeyValue *parent; } KeyValue; #define SOLV_KV_NUM64(kv) (((unsigned long long)((kv)->num2)) << 32 | (kv)->num) @@ -52,7 +52,7 @@ typedef struct _KeyValue { #define SEARCH_SUB (1<<9) #define SEARCH_ARRAYSENTINEL (1<<10) #define SEARCH_DISABLED_REPOS (1<<11) -#define SEARCH_COMPLETE_FILELIST (1<<12) +#define SEARCH_KEEP_TYPE_DELETED (1<<12) /* only has effect if no keyname is given */ /* stringification flags */ #define SEARCH_SKIP_KIND (1<<16) @@ -62,13 +62,17 @@ typedef struct _KeyValue { #define SEARCH_FILES (1<<17) #define SEARCH_CHECKSUMS (1<<18) -/* dataiterator internal */ +/* internal */ +#define SEARCH_SUBSCHEMA (1<<30) #define SEARCH_THISSOLVID (1<<31) +/* obsolete */ +#define SEARCH_COMPLETE_FILELIST 0 /* ignored, this is the default */ + /* * Datamatcher: match a string against a query */ -typedef struct _Datamatcher { +typedef struct s_Datamatcher { int flags; /* see matcher flags above */ const char *match; /* the query string */ void *matchdata; /* e.g. compiled regexp */ @@ -96,14 +100,14 @@ int datamatcher_checkbasename(Datamatcher *ma, const char *str); * dosomething(di.solvid, di.key, di.kv); * dataiterator_free(&di); */ -typedef struct _Dataiterator +typedef struct s_Dataiterator { int state; int flags; Pool *pool; - struct _Repo *repo; - struct _Repodata *data; + struct s_Repo *repo; + struct s_Repodata *data; /* data pointers */ unsigned char *dp; @@ -112,7 +116,7 @@ typedef struct _Dataiterator Id *keyp; /* the result */ - struct _Repokey *key; + struct s_Repokey *key; KeyValue kv; /* our matcher */ @@ -146,6 +150,8 @@ typedef struct _Dataiterator char *dupstr; int dupstrn; + Id *keyskip; + Id *oldkeyskip; } Dataiterator; @@ -159,9 +165,9 @@ typedef struct _Dataiterator * keyname: if non-null, limit search to this keyname * match: if non-null, limit search to this match */ -int dataiterator_init(Dataiterator *di, Pool *pool, struct _Repo *repo, Id p, Id keyname, const char *match, int flags); +int dataiterator_init(Dataiterator *di, Pool *pool, struct s_Repo *repo, Id p, Id keyname, const char *match, int flags); void dataiterator_init_clone(Dataiterator *di, Dataiterator *from); -void dataiterator_set_search(Dataiterator *di, struct _Repo *repo, Id p); +void dataiterator_set_search(Dataiterator *di, struct s_Repo *repo, Id p); void dataiterator_set_keyname(Dataiterator *di, Id keyname); int dataiterator_set_match(Dataiterator *di, const char *match, int flags); @@ -175,7 +181,7 @@ void dataiterator_skip_attribute(Dataiterator *di); void dataiterator_skip_solvable(Dataiterator *di); void dataiterator_skip_repo(Dataiterator *di); void dataiterator_jump_to_solvid(Dataiterator *di, Id solvid); -void dataiterator_jump_to_repo(Dataiterator *di, struct _Repo *repo); +void dataiterator_jump_to_repo(Dataiterator *di, struct s_Repo *repo); void dataiterator_entersub(Dataiterator *di); void dataiterator_clonepos(Dataiterator *di, Dataiterator *from); void dataiterator_seek(Dataiterator *di, int whence); diff --git a/src/dirpool.h b/src/dirpool.h index fe05cc6..ca92954 100644 --- a/src/dirpool.h +++ b/src/dirpool.h @@ -15,7 +15,7 @@ extern "C" { #endif -typedef struct _Dirpool { +typedef struct s_Dirpool { Id *dirs; int ndirs; Id *dirtraverse; diff --git a/src/diskusage.c b/src/diskusage.c index b764b98..63c43bf 100644 --- a/src/diskusage.c +++ b/src/diskusage.c @@ -308,7 +308,7 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) { if (MAPTST(installedmap, sp)) continue; - if (ignoredu.map && MAPTST(&ignoredu, sp - oldinstalled->start)) + if (ignoredu.size && MAPTST(&ignoredu, sp - oldinstalled->start)) continue; repo_search(oldinstalled, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); } @@ -318,12 +318,12 @@ pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) solv_free(mptree); } -int +long long pool_calc_installsizechange(Pool *pool, Map *installedmap) { Id sp; Solvable *s; - int change = 0; + long long change = 0; Repo *oldinstalled = pool->installed; for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) diff --git a/src/filelistfilter.c b/src/filelistfilter.c new file mode 100644 index 0000000..e698d6f --- /dev/null +++ b/src/filelistfilter.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018, SUSE LLC + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* + * filelistfilter.c + * + * Support repodata with a filelist filtered by a custom filter + */ + +#define _GNU_SOURCE +#include <string.h> +#include <fnmatch.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> + +#include "repo.h" +#include "pool.h" +#include "util.h" + +static Id default_filelist_filter; + +#define FF_EXACT 0 +#define FF_END 1 +#define FF_START 2 +#define FF_SUB 3 /* FF_END | FF_START */ +#define FF_GLOB 4 +#define FF_START5 5 + +void +repodata_free_filelistfilter(Repodata *data) +{ + if (data->filelistfilter) + { + if (data->filelistfilter != &default_filelist_filter) + solv_free(data->filelistfilter); + data->filelistfilter = 0; + } + data->filelistfilterdata = solv_free(data->filelistfilterdata); +} + +static void +repodata_set_filelistfilter(Repodata *data) +{ + Id type; + Queue q; + int i, j; + char *filterdata; + int nfilterdata; + + if (data->filelistfilter && data->filelistfilter != &default_filelist_filter) + data->filelistfilter = solv_free(data->filelistfilter); + data->filelistfilterdata = solv_free(data->filelistfilterdata); + type = repodata_lookup_type(data, SOLVID_META, REPOSITORY_FILTEREDFILELIST); + if (type != REPOKEY_TYPE_IDARRAY) + { + data->filelistfilter = &default_filelist_filter; + return; + } + queue_init(&q); + repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_FILTEREDFILELIST, &q); + if (q.count == 3) + { + /* check if this is the default filter */ + int t = 0; + for (i = 0; i < 3; i++) + { + Id id = q.elements[i]; + const char *g = data->localpool ? stringpool_id2str(&data->spool, id) : pool_id2str(data->repo->pool, id); + if (!strcmp(g, "*bin/*")) + t |= 1; + else if (!strcmp(g, "/etc/*")) + t |= 2; + else if (!strcmp(g, "/usr/lib/sendmail")) + t |= 4; + } + if (t == 7) + { + queue_free(&q); + data->filelistfilter = &default_filelist_filter; + return; + } + } + data->filelistfilter = solv_calloc(q.count * 2 + 1, sizeof(Id)); + filterdata = solv_calloc_block(1, 1, 255); + nfilterdata = 1; + + for (i = j = 0; i < q.count; i++) + { + Id id = q.elements[i]; + const char *g = data->localpool ? stringpool_id2str(&data->spool, id) : pool_id2str(data->repo->pool, id); + const char *p; + int t = FF_EXACT; + int gl; + if (!id || !g || !*g) + continue; + for (p = g; *p && t != FF_GLOB; p++) + { + if (*p == '*') + { + if (p == g) + t |= FF_END; + else if (!p[1]) + t |= FF_START; + else + t = FF_GLOB; + } + else if (*p == '[' || *p == '?') + t = FF_GLOB; + } + gl = strlen(g); + if (t == FF_END) /* not supported */ + t = FF_GLOB; + if (t == FF_START && gl == 5) + t = FF_START5; + filterdata = solv_extend(filterdata, nfilterdata, gl + 1, 1, 255); + data->filelistfilter[j++] = nfilterdata; + data->filelistfilter[j++] = t; + switch (t) + { + case FF_START: + case FF_START5: + strcpy(filterdata + nfilterdata, g); + filterdata[nfilterdata + gl - 1] = 0; + nfilterdata += gl; + break; + case FF_SUB: + strcpy(filterdata + nfilterdata, g + 1); + filterdata[nfilterdata + gl - 2] = 0; + nfilterdata += gl - 1; + break; + default: + strcpy(filterdata + nfilterdata, g); + nfilterdata += gl + 1; + break; + } + } + filterdata = solv_realloc(filterdata, nfilterdata); + data->filelistfilter[j++] = 0; + data->filelistfilterdata = filterdata; + queue_free(&q); +} + +int +repodata_filelistfilter_matches(Repodata *data, const char *str) +{ + Id *ff; + if (data && !data->filelistfilter) + repodata_set_filelistfilter(data); + if (!data || data->filelistfilter == &default_filelist_filter) + { + /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */ + if (strstr(str, "bin/")) + return 1; + if (!strncmp(str, "/etc/", 5)) + return 1; + if (!strcmp(str, "/usr/lib/sendmail")) + return 1; + return 0; + } + for (ff = data->filelistfilter; *ff; ff += 2) + { + const char *g = data->filelistfilterdata + *ff; + switch (ff[1]) + { + case FF_EXACT: + if (!strcmp(str, g)) + return 1; + break; + case FF_START: + if (!strncmp(str, g, strlen(g))) + return 1; + break; + case FF_SUB: + if (!strstr(str, g)) + return 1; + break; + case FF_START5: + if (!strncmp(str, g, 5)) + return 1; + break; + default: + if (!fnmatch(g, str, 0)) + return 1; + break; + } + } + return 0; +} + diff --git a/src/fileprovides.c b/src/fileprovides.c index 11ff4f5..ec80831 100644 --- a/src/fileprovides.c +++ b/src/fileprovides.c @@ -22,6 +22,7 @@ #include "util.h" #include "bitmap.h" + struct searchfiles { Id *ids; int nfiles; @@ -101,188 +102,450 @@ struct addfileprovides_cbdata { Id *ids; char **dirs; char **names; - Id *dids; - Map providedids; + Map *providedids; + int provstart; + int provend; - Map useddirs; + Map *todo; + int todo_start; + int todo_end; }; -static int -addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) +/* split filelist dep into basename and dirname */ +static void +create_dirs_names_array(struct addfileprovides_cbdata *cbd, Pool *pool) { - struct addfileprovides_cbdata *cbd = cbdata; int i; + cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *)); + cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *)); + for (i = 0; i < cbd->nfiles; i++) + { + char *s = solv_strdup(pool_id2str(pool, cbd->ids[i])); + cbd->dirs[i] = s; + s = strrchr(s, '/'); + *s = 0; + cbd->names[i] = s + 1; + } +} - if (!cbd->useddirs.size) +static void +free_dirs_names_array(struct addfileprovides_cbdata *cbd) +{ + int i; + if (cbd->dirs) { - map_init(&cbd->useddirs, data->dirpool.ndirs + 1); - if (!cbd->dirs) - { - cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *)); - cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *)); - for (i = 0; i < cbd->nfiles; i++) - { - char *s = solv_strdup(pool_id2str(data->repo->pool, cbd->ids[i])); - cbd->dirs[i] = s; - s = strrchr(s, '/'); - *s = 0; - cbd->names[i] = s + 1; - } - } for (i = 0; i < cbd->nfiles; i++) - { - Id did; - if (MAPTST(&cbd->providedids, cbd->ids[i])) - { - cbd->dids[i] = 0; - continue; - } - did = repodata_str2dir(data, cbd->dirs[i], 0); - cbd->dids[i] = did; - if (did) - MAPSET(&cbd->useddirs, did); - } - repodata_free_dircache(data); + solv_free(cbd->dirs[i]); + cbd->dirs = solv_free(cbd->dirs); + cbd->names = solv_free(cbd->names); } - if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id)) +} + +static void +prune_todo_range(Repo *repo, struct addfileprovides_cbdata *cbd) +{ + int start = cbd->todo_start, end = cbd->todo_end; + while (start < end && !MAPTST(cbd->todo, start - repo->start)) + start++; + while (end > start && !MAPTST(cbd->todo, end - 1 - repo->start)) + end--; + cbd->todo_start = start; + cbd->todo_end = end; +} + +static int +repodata_intersects_todo(Repodata *data, struct addfileprovides_cbdata *cbd) +{ + Repo *repo; + int p, start = data->start, end = data->end; + if (start >= cbd->todo_end || end <= cbd->todo_start) return 0; - for (i = 0; i < cbd->nfiles; i++) - if (cbd->dids[i] == value->id && !strcmp(cbd->names[i], value->str)) - s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); + repo = data->repo; + if (start < cbd->todo_start) + start = cbd->todo_start; + if (end > cbd->todo_end) + end = cbd->todo_end; + for (p = start; p < end; p++) + if (MAPTST(cbd->todo, p - repo->start)) + return 1; return 0; } +/* forward declaration */ +static void repodata_addfileprovides_search(Repodata *data, struct addfileprovides_cbdata *cbd); + +/* search a subset of the todo range */ static void -pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly) +repodata_addfileprovides_search_limited(Repodata *data, struct addfileprovides_cbdata *cbd, int start, int end) { - Id p; - Repodata *data; - Repo *repo; - Queue fileprovidesq; - int i, j, repoid, repodataid; - int provstart, provend; - Map donemap; - int ndone, incomplete; - if (!pool->urepos) + int old_todo_start = cbd->todo_start; + int old_todo_end = cbd->todo_end; + if (start < cbd->todo_start) + start = cbd->todo_start; + if (end > cbd->todo_end) + end = cbd->todo_end; + if (start >= end) return; + cbd->todo_start = start; + cbd->todo_end = end; + repodata_addfileprovides_search(data, cbd); + cbd->todo_start = old_todo_start; + cbd->todo_end = old_todo_end; + prune_todo_range(data->repo, cbd); +} - cbd->nfiles = sf->nfiles; - cbd->ids = sf->ids; - cbd->dirs = 0; - cbd->names = 0; - cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); - map_init(&cbd->providedids, pool->ss.nstrings); - - repoid = 1; - repo = repoonly ? repoonly : pool->repos[repoid]; - map_init(&donemap, pool->nsolvables); - queue_init(&fileprovidesq); - provstart = provend = 0; - for (;;) +static void +repodata_addfileprovides_search(Repodata *data, struct addfileprovides_cbdata *cbd) +{ + Repo *repo = data->repo; + int i, p, start, end; + Map useddirs; + Map *providedids = 0; + + /* make it available */ + if (data->state == REPODATA_STUB) + repodata_load(data); + if (data->state != REPODATA_AVAILABLE) + return; + if (!data->incoredata || !data->dirpool.ndirs) + return; + + start = cbd->todo_start > data->start ? cbd->todo_start : data->start; + end = cbd->todo_end > data->end ? data->end : cbd->todo_end; + + if (start >= end) + return; + + /* deal with provideids overlap */ + if (cbd->providedids) { - if (!repo || repo->disabled) + if (start >= cbd->provstart && end <= cbd->provend) + providedids = cbd->providedids; /* complete overlap */ + else if (start < cbd->provend && end > cbd->provstart) { - if (repoonly || ++repoid == pool->nrepos) - break; - repo = pool->repos[repoid]; + /* partial overlap, need to split search */ + if (start < cbd->provstart) + { + repodata_addfileprovides_search_limited(data, cbd, start, cbd->provstart); + start = cbd->provstart; + } + if (end > cbd->provend) + { + repodata_addfileprovides_search_limited(data, cbd, cbd->provend, end); + end = cbd->provend; + } + if (start < end) + repodata_addfileprovides_search_limited(data, cbd, start, end); + return; + } + } + + /* set up dirs and names array if not already done */ + if (!cbd->dirs) + create_dirs_names_array(cbd, repo->pool); + + /* set up useddirs map and the cbd->dids array */ + map_init(&useddirs, data->dirpool.ndirs); + for (i = 0; i < cbd->nfiles; i++) + { + Id did; + if (providedids && MAPTST(providedids, cbd->ids[i])) + { + cbd->dids[i] = 0; /* already included, do not add again */ continue; } - ndone = 0; - FOR_REPODATAS(repo, repodataid, data) + cbd->dids[i] = did = repodata_str2dir(data, cbd->dirs[i], 0); + if (did) + MAPSET(&useddirs, did); + } + repodata_free_dircache(data); /* repodata_str2dir created it */ + + for (p = start; p < end; p++) + { + const unsigned char *dp; + Solvable *s; + if (!MAPTST(cbd->todo, p - repo->start)) + continue; + dp = repodata_lookup_packed_dirstrarray(data, p, SOLVABLE_FILELIST); + if (!dp) + continue; + /* now iterate through the packed array */ + s = repo->pool->solvables + p; + MAPCLR(cbd->todo, p - repo->start); /* this entry is done */ + for (;;) { - if (ndone >= repo->nsolvables) + Id did = 0; + int c; + while ((c = *dp++) & 0x80) + did = (did << 7) ^ c ^ 0x80; + did = (did << 6) | (c & 0x3f); + if ((unsigned int)did < (unsigned int)data->dirpool.ndirs && MAPTST(&useddirs, did)) + { + /* there is at least one entry with that did */ + for (i = 0; i < cbd->nfiles; i++) + if (cbd->dids[i] == did && !strcmp(cbd->names[i], (const char *)dp)) + s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); + } + if (!(c & 0x40)) break; + dp += strlen((const char *)dp) + 1; + } + } + map_free(&useddirs); + prune_todo_range(repo, cbd); +} + +static void +repo_addfileprovides_search_filtered(Repo *repo, struct addfileprovides_cbdata *cbd, int filteredid, Map *postpone) +{ + Repodata *data = repo->repodata + filteredid; + Map *providedids = cbd->providedids; + int rdid; + int start, end, p, i; + Map old_todo; + int old_todo_start, old_todo_end; + + start = cbd->todo_start > data->start ? cbd->todo_start : data->start; + end = cbd->todo_end > data->end ? data->end : cbd->todo_end; - if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) + if (providedids) + { + /* check if all solvables are in the provide range */ + if (start < cbd->provstart || end > cbd->provend) + { + /* unclear, check each solvable */ + for (p = start; p < end; p++) { - map_empty(&cbd->providedids); - for (i = 0; i < fileprovidesq.count; i++) - MAPSET(&cbd->providedids, fileprovidesq.elements[i]); - provstart = data->start; - provend = data->end; - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i])) - break; - if (i == cbd->nfiles) + if (p >= cbd->provstart && p < cbd->provend) + continue; + if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start)) { - /* great! no need to search files */ - for (p = data->start; p < data->end; p++) - if (pool->solvables[p].repo == repo) - { - if (MAPTST(&donemap, p)) - continue; - MAPSET(&donemap, p); - ndone++; - } - continue; + providedids = 0; /* nope, cannot prune with providedids */ + break; } } + } + } - if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) - continue; + /* check if the filtered files are enough */ + for (i = 0; i < cbd->nfiles; i++) + { + if (providedids && MAPTST(providedids, cbd->ids[i])) /* this one is already provided */ + continue; + if (!repodata_filelistfilter_matches(data, pool_id2str(repo->pool, cbd->ids[i]))) + break; + } + if (i < cbd->nfiles) + { + /* nope, need to search the extensions as well. postpone. */ + for (p = start; p < end; p++) + { + if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start)) + { + if (!postpone->size) + map_grow(postpone, repo->nsolvables); + MAPSET(postpone, p - repo->start); + MAPCLR(cbd->todo, p - repo->start); + } + } + prune_todo_range(repo, cbd); + return; + } + + /* now check if there is no data marked withour EXTENSION */ + /* limit todo to the solvables in this repodata */ + old_todo_start = cbd->todo_start; + old_todo_end = cbd->todo_end; + old_todo = *cbd->todo; + map_init(cbd->todo, repo->nsolvables); + for (p = start; p < end; p++) + if (data->incoreoffset[p - data->start] && MAPTST(&old_todo, p - repo->start)) + { + MAPCLR(&old_todo, p - repo->start); + MAPSET(cbd->todo, p - repo->start); + } + prune_todo_range(repo, cbd); - if (data->start < provstart || data->end > provend) + /* do the check */ + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > filteredid ; rdid--, data--) + { + if (data->filelisttype == REPODATA_FILELIST_EXTENSION) + continue; + if (data->start >= cbd->todo_end || data->end <= cbd->todo_start) + continue; + if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) + continue; + if (!repodata_intersects_todo(data, cbd)) + continue; + /* oh no, this filelist data is not tagged with REPODATA_FILELIST_EXTENSION! */ + /* postpone entries that have filelist data */ + start = cbd->todo_start > data->start ? cbd->todo_start : data->start; + end = cbd->todo_end > data->end ? data->end : cbd->todo_end; + for (p = start; p < end; p++) + if (MAPTST(cbd->todo, p - repo->start)) + if (repodata_lookup_type(data, p, SOLVABLE_FILELIST)) { - map_empty(&cbd->providedids); - provstart = provend = 0; + if (!postpone->size) + map_grow(postpone, repo->nsolvables); + MAPSET(postpone, p - repo->start); + MAPCLR(cbd->todo, p - repo->start); } + prune_todo_range(repo, cbd); + if (cbd->todo_start >= cbd->todo_end) + break; + } + + /* do the search over the filtered file list with the remaining entries*/ + if (cbd->todo_start < cbd->todo_end) + repodata_addfileprovides_search(repo->repodata + filteredid, cbd); + + /* restore todo map */ + map_free(cbd->todo); + *cbd->todo = old_todo; + cbd->todo_start = old_todo_start; + cbd->todo_end = old_todo_end; + prune_todo_range(repo, cbd); +} + +static void +repo_addfileprovides_search(Repo *repo, struct addfileprovides_cbdata *cbd, struct searchfiles *sf) +{ + Repodata *data; + int rdid, p, i; + int provstart, provend; + Map todo; + Map providedids; + + if (repo->end <= repo->start || !repo->nsolvables || !sf->nfiles) + return; - /* check if the data is incomplete */ - incomplete = 0; - if (data->state == REPODATA_AVAILABLE) + /* update search data if changed */ + if (cbd->nfiles != sf->nfiles || cbd->ids != sf->ids) + { + free_dirs_names_array(cbd); + cbd->nfiles = sf->nfiles; + cbd->ids = sf->ids; + cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); + } + + /* create todo map and range */ + map_init(&todo, repo->end - repo->start); + for (p = repo->start; p < repo->end; p++) + if (repo->pool->solvables[p].repo == repo) + MAPSET(&todo, p - repo->start); + cbd->todo = &todo; + cbd->todo_start = repo->start; + cbd->todo_end = repo->end; + prune_todo_range(repo, cbd); + + provstart = provend = 0; + map_init(&providedids, 0); + data = repo_lookup_repodata(repo, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES); + if (data) + { + Queue fileprovidesq; + queue_init(&fileprovidesq); + if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) + { + map_grow(&providedids, repo->pool->ss.nstrings); + cbd->providedids = &providedids; + provstart = data->start; + provend = data->end; + for (i = 0; i < fileprovidesq.count; i++) + MAPSET(&providedids, fileprovidesq.elements[i]); + for (i = 0; i < cbd->nfiles; i++) + if (!MAPTST(&providedids, cbd->ids[i])) + break; + if (i == cbd->nfiles) { - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - break; - if (j < data->nkeys) + /* all included, clear entries from todo list */ + if (provstart <= cbd->todo_start && provend >= cbd->todo_end) + cbd->todo_end = cbd->todo_start; /* clear complete range */ + else { -#if 0 - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) - printf("need complete filelist because of %s\n", pool_id2str(pool, cbd->ids[i])); -#endif - for (i = 0; i < cbd->nfiles; i++) - if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) - break; - if (i < cbd->nfiles) - incomplete = 1; + for (p = provstart; p < provend; p++) + MAPCLR(&todo, p - repo->start); + prune_todo_range(repo, cbd); } } - - /* do the search */ - map_init(&cbd->useddirs, 0); - for (p = data->start; p < data->end; p++) - if (pool->solvables[p].repo == repo) - { - if (MAPTST(&donemap, p)) - continue; - repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd); - if (!incomplete) - { - MAPSET(&donemap, p); - ndone++; - } - } - map_free(&cbd->useddirs); } + queue_free(&fileprovidesq); + } - if (repoonly || ++repoid == pool->nrepos) - break; - repo = pool->repos[repoid]; + if (cbd->todo_start >= cbd->todo_end) + { + map_free(&todo); + cbd->todo = 0; + map_free(&providedids); + cbd->providedids = 0; + return; } - map_free(&donemap); - queue_free(&fileprovidesq); - map_free(&cbd->providedids); - if (cbd->dirs) + + /* this is similar to repo_lookup_filelist_repodata in repo.c */ + + for (rdid = 1, data = repo->repodata + rdid; rdid < repo->nrepodata; rdid++, data++) + if (data->filelisttype == REPODATA_FILELIST_FILTERED) + break; + for (; rdid < repo->nrepodata; rdid++, data++) + if (data->filelisttype == REPODATA_FILELIST_EXTENSION) + break; + + if (rdid < repo->nrepodata) { - for (i = 0; i < cbd->nfiles; i++) - solv_free(cbd->dirs[i]); - cbd->dirs = solv_free(cbd->dirs); - cbd->names = solv_free(cbd->names); + /* have at least one repodata with REPODATA_FILELIST_FILTERED followed by REPODATA_FILELIST_EXTENSION */ + Map postpone; + map_init(&postpone, 0); + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) + { + if (data->filelisttype != REPODATA_FILELIST_FILTERED) + continue; + if (!repodata_intersects_todo(data, cbd)) + continue; + if (data->state != REPODATA_AVAILABLE) + { + if (data->state != REPODATA_STUB) + continue; + repodata_load(data); + if (data->state != REPODATA_AVAILABLE || data->filelisttype != REPODATA_FILELIST_FILTERED) + continue; + } + repo_addfileprovides_search_filtered(repo, cbd, rdid, &postpone); + } + if (postpone.size) + { + /* add postponed entries back to todo */ + map_or(&todo, &postpone); + cbd->todo_start = repo->start; + cbd->todo_end = repo->end; + prune_todo_range(repo, cbd); + } + map_free(&postpone); + } + + /* search remaining entries in the standard way */ + if (cbd->todo_start < cbd->todo_end) + { + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) + { + if (data->start >= cbd->todo_end || data->end <= cbd->todo_start) + continue; + if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) + continue; + if (!repodata_intersects_todo(data, cbd)) + continue; + repodata_addfileprovides_search(data, cbd); + if (cbd->todo_start >= cbd->todo_end) + break; + } } + + map_free(&todo); + cbd->todo = 0; + map_free(&providedids); + cbd->providedids = 0; } void @@ -297,6 +560,7 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) installed = pool->installed; now = solv_timems(0); + memset(&cbd, 0, sizeof(cbd)); memset(&sf, 0, sizeof(sf)); map_init(&sf.seen, pool->ss.nstrings + pool->nrels); memset(&isf, 0, sizeof(isf)); @@ -328,23 +592,22 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) if (s->enhances) pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp); } + map_free(&sf.seen); 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 (sf.nfiles) { #if 0 for (i = 0; i < sf.nfiles; i++) 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); + FOR_REPOS(i, repo) + repo_addfileprovides_search(repo, &cbd, &sf); if (idq) - for (i = 0; i < sf.nfiles; i++) - queue_push(idq, sf.ids[i]); + queue_insertn(idq, idq->count, sf.nfiles, sf.ids); if (idqinst) - for (i = 0; i < sf.nfiles; i++) - queue_push(idqinst, sf.ids[i]); + queue_insertn(idqinst, idqinst->count, sf.nfiles, sf.ids); solv_free(sf.ids); } if (isf.nfiles) @@ -354,12 +617,13 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in installed filelist\n", pool_id2str(pool, isf.ids[i])); #endif if (installed) - pool_addfileprovides_search(pool, &cbd, &isf, installed); + repo_addfileprovides_search(installed, &cbd, &isf); if (installed && idqinst) for (i = 0; i < isf.nfiles; i++) queue_pushunique(idqinst, isf.ids[i]); solv_free(isf.ids); } + free_dirs_names_array(&cbd); solv_free(cbd.dids); pool_freewhatprovides(pool); /* as we have added provides */ POOL_DEBUG(SOLV_DEBUG_STATS, "addfileprovides took %d ms\n", solv_timems(now)); diff --git a/src/knownid.h b/src/knownid.h index 64cc6fc..8e53183 100644 --- a/src/knownid.h +++ b/src/knownid.h @@ -76,18 +76,12 @@ KNOWNID(REPOSITORY_EXTERNAL, "repository:external"), KNOWNID(REPOSITORY_KEYS, "repository:keys"), KNOWNID(REPOSITORY_LOCATION, "repository:location"), -/* file provides already added to our solvables */ -KNOWNID(REPOSITORY_ADDEDFILEPROVIDES, "repository:addedfileprovides"), -/* inode of the rpm database for rpm --rebuilddb detection */ -KNOWNID(REPOSITORY_RPMDBCOOKIE, "repository:rpmdbcookie"), - /* the known data types */ KNOWNID(REPOKEY_TYPE_VOID, "repokey:type:void"), KNOWNID(REPOKEY_TYPE_CONSTANT, "repokey:type:constant"), KNOWNID(REPOKEY_TYPE_CONSTANTID, "repokey:type:constantid"), KNOWNID(REPOKEY_TYPE_ID, "repokey:type:id"), KNOWNID(REPOKEY_TYPE_NUM, "repokey:type:num"), -KNOWNID(REPOKEY_TYPE_U32, "repokey:type:num32"), KNOWNID(REPOKEY_TYPE_DIR, "repokey:type:dir"), KNOWNID(REPOKEY_TYPE_STR, "repokey:type:str"), KNOWNID(REPOKEY_TYPE_BINARY, "repokey:type:binary"), @@ -145,6 +139,8 @@ KNOWNID(SOLVABLE_CHANGELOG, "solvable:changelog"), KNOWNID(SOLVABLE_CHANGELOG_AUTHOR, "solvable:changelog:author"), KNOWNID(SOLVABLE_CHANGELOG_TIME, "solvable:changelog:time"), KNOWNID(SOLVABLE_CHANGELOG_TEXT, "solvable:changelog:text"), +KNOWNID(SOLVABLE_INSTALLSTATUS, "solvable:installstatus"), /* debian install status */ +KNOWNID(SOLVABLE_PREREQ_IGNOREINST, "solvable:prereq_ignoreinst"), /* ignore these pre-requires for installed packages */ /* stuff for solvables of type pattern */ KNOWNID(SOLVABLE_CATEGORY, "solvable:category"), @@ -187,6 +183,7 @@ KNOWNID(PRODUCT_URL_TYPE, "product:url:type"), KNOWNID(PRODUCT_FLAGS, "product:flags"), /* e.g. 'update', 'no_you' */ KNOWNID(PRODUCT_PRODUCTLINE, "product:productline"), /* installed product only */ KNOWNID(PRODUCT_REGISTER_TARGET, "product:regtarget"), /* installed and available product */ +KNOWNID(PRODUCT_REGISTER_FLAVOR, "product:regflavor"), /* installed and available product */ KNOWNID(PRODUCT_REGISTER_RELEASE, "product:regrelease"), /* installed product only */ KNOWNID(PRODUCT_UPDATES_REPOID, "product:updates:repoid"), KNOWNID(PRODUCT_UPDATES, "product:updates"), @@ -204,21 +201,18 @@ KNOWNID(SUSETAGS_SHARE_NAME, "susetags:share:name"), KNOWNID(SUSETAGS_SHARE_EVR, "susetags:share:evr"), KNOWNID(SUSETAGS_SHARE_ARCH, "susetags:share:arch"), -/* timestamp then the repository was generated */ -KNOWNID(REPOSITORY_TIMESTAMP, "repository:timestamp"), -/* hint when the metadata could be outdated w/respect to generated timestamp */ -KNOWNID(REPOSITORY_EXPIRE, "repository:expire"), -/* which things does this repo provides updates for, if it does (array) */ -KNOWNID(REPOSITORY_UPDATES, "repository:updates"), /* obsolete? */ -/* which products this repository is supposed to be for (array) */ -KNOWNID(REPOSITORY_DISTROS, "repository:distros"), +KNOWNID(REPOSITORY_ADDEDFILEPROVIDES, "repository:addedfileprovides"), /* file provides already added to our solvables */ +KNOWNID(REPOSITORY_RPMDBCOOKIE, "repository:rpmdbcookie"), /* inode of the rpm database for rpm --rebuilddb detection */ +KNOWNID(REPOSITORY_FILTEREDFILELIST, "repository:filteredfilelist"), /* filelist in repository is filtered */ +KNOWNID(REPOSITORY_TIMESTAMP, "repository:timestamp"), /* timestamp then the repository was generated */ +KNOWNID(REPOSITORY_EXPIRE, "repository:expire"), /* hint when the metadata could be outdated w/respect to generated timestamp */ +KNOWNID(REPOSITORY_UPDATES, "repository:updates"), /* which things does this repo provides updates for, if it does (array) (obsolete?) */ +KNOWNID(REPOSITORY_DISTROS, "repository:distros"), /* which products this repository is supposed to be for (array) */ KNOWNID(REPOSITORY_PRODUCT_LABEL, "repository:product:label"), KNOWNID(REPOSITORY_PRODUCT_CPEID, "repository:product:cpeid"), KNOWNID(REPOSITORY_REPOID, "repository:repoid"), /* obsolete? */ -/* keyword (tags) for this repository */ -KNOWNID(REPOSITORY_KEYWORDS, "repository:keywords"), -/* revision of the repository. arbitrary string */ -KNOWNID(REPOSITORY_REVISION, "repository:revision"), +KNOWNID(REPOSITORY_KEYWORDS, "repository:keywords"), /* keyword (tags) for this repository */ +KNOWNID(REPOSITORY_REVISION, "repository:revision"), /* revision of the repository. arbitrary string */ KNOWNID(REPOSITORY_TOOLVERSION, "repository:toolversion"), KNOWNID(DELTA_PACKAGE_NAME, "delta:pkgname"), @@ -256,12 +250,6 @@ KNOWNID(SIGNATURE_TIME, "signature:time"), KNOWNID(SIGNATURE_EXPIRES, "signature:expires"), KNOWNID(SIGNATURE_DATA, "signature:data"), -KNOWNID(PRODUCT_REGISTER_FLAVOR, "product:regflavor"), /* installed and available product */ - -KNOWNID(SOLVABLE_INSTALLSTATUS, "solvable:installstatus"), /* debian install status */ - -KNOWNID(SOLVABLE_PREREQ_IGNOREINST, "solvable:prereq_ignoreinst"), /* ignore these pre-requires for installed packages */ - KNOWNID(ID_NUM_INTERNAL, 0) #ifdef KNOWNID_INITIALIZE diff --git a/src/libsolv.ver b/src/libsolv.ver index a3fa19a..f0e86ff 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -120,6 +120,7 @@ SOLV_1.0 { pool_trivial_installable_multiversionmap; pool_vendor2mask; pool_whatmatchesdep; + pool_whatmatchessolvable; pool_whatcontainsdep; queue_alloc_one; queue_alloc_one_head; @@ -145,6 +146,7 @@ SOLV_1.0 { repo_addid; repo_addid_dep; repo_create; + repo_create_keyskip; repo_disable_paging; repo_empty; repo_fix_conflicts; @@ -165,7 +167,6 @@ SOLV_1.0 { repo_lookup_str; repo_lookup_type; repo_lookup_void; - repo_matchvalue; repo_reserve_ids; repo_rewrite_suse_deps; repo_search; @@ -203,12 +204,10 @@ SOLV_1.0 { repodata_key2id; repodata_localize_id; repodata_lookup_bin_checksum; - repodata_lookup_bin_checksum_uninternalized; repodata_lookup_binary; - repodata_lookup_dirstrarray_uninternalized; repodata_lookup_id; - repodata_lookup_id_uninternalized; repodata_lookup_idarray; + repodata_lookup_kv_uninternalized; repodata_lookup_num; repodata_lookup_str; repodata_lookup_type; @@ -219,12 +218,16 @@ SOLV_1.0 { repodata_new_handle; repodata_schema2id; repodata_search; + repodata_search_arrayelement; + repodata_search_keyskip; + repodata_search_uninternalized; repodata_set_binary; repodata_set_bin_checksum; repodata_set_checksum; repodata_set_constant; repodata_set_constantid; repodata_set_deltalocation; + repodata_set_filelisttype; repodata_set_id; repodata_set_idarray; repodata_set_location; @@ -238,17 +241,28 @@ SOLV_1.0 { repodata_str2dir; repodata_stringify; repodata_swap_attrs; + repodata_translate_dir_slow; repodata_translate_id; repodata_unset; repodata_unset_uninternalized; repodata_write; repodata_write_filtered; repopagestore_compress_page; + repowriter_create; + repowriter_free; + repowriter_set_flags; + repowriter_set_keyfilter; + repowriter_set_keyqueue; + repowriter_set_repodatarange; + repowriter_set_solvablerange; + repowriter_write; selection_add; selection_filter; selection_make; selection_make_matchdepid; selection_make_matchdeps; + selection_make_matchsolvable; + selection_make_matchsolvablelist; selection_solvables; solv_bin2hex; solv_calloc; diff --git a/src/order.c b/src/order.c index c92c332..c0cc07f 100644 --- a/src/order.c +++ b/src/order.c @@ -23,14 +23,14 @@ #include "repo.h" #include "util.h" -struct _TransactionElement { +struct s_TransactionElement { Id p; /* solvable id */ Id edges; /* pointer into edges data */ Id mark; }; -struct _TransactionOrderdata { - struct _TransactionElement *tes; +struct s_TransactionOrderdata { + struct s_TransactionElement *tes; int ntes; Id *invedgedata; int ninvedgedata; @@ -57,7 +57,7 @@ struct _TransactionOrderdata { void transaction_clone_orderdata(Transaction *trans, Transaction *srctrans) { - struct _TransactionOrderdata *od = srctrans->orderdata; + struct s_TransactionOrderdata *od = srctrans->orderdata; if (!od) return; trans->orderdata = solv_calloc(1, sizeof(*trans->orderdata)); @@ -77,7 +77,7 @@ transaction_free_orderdata(Transaction *trans) { if (trans->orderdata) { - struct _TransactionOrderdata *od = trans->orderdata; + struct s_TransactionOrderdata *od = trans->orderdata; od->tes = solv_free(od->tes); od->invedgedata = solv_free(od->invedgedata); if (od->cycles) @@ -91,7 +91,7 @@ transaction_free_orderdata(Transaction *trans) struct orderdata { Transaction *trans; - struct _TransactionElement *tes; + struct s_TransactionElement *tes; int ntes; Id *edgedata; int nedgedata; @@ -106,7 +106,7 @@ static int addteedge(struct orderdata *od, int from, int to, int type) { int i; - struct _TransactionElement *te; + struct s_TransactionElement *te; if (from == to) return 0; @@ -154,7 +154,7 @@ addedge(struct orderdata *od, Id from, Id to, int type) Transaction *trans = od->trans; Pool *pool = trans->pool; Solvable *s; - struct _TransactionElement *te; + struct s_TransactionElement *te; int i; /* printf("addedge %d %d type %d\n", from, to, type); */ @@ -531,7 +531,7 @@ breakcycle(struct orderdata *od, Id *cycle) Pool *pool = od->trans->pool; Id ddegmin, ddegmax, ddeg; int k, l; - struct _TransactionElement *te; + struct s_TransactionElement *te; l = 0; ddegmin = ddegmax = 0; @@ -604,7 +604,7 @@ dump_tes(struct orderdata *od) Pool *pool = od->trans->pool; int i, j; Queue obsq; - struct _TransactionElement *te, *te2; + struct s_TransactionElement *te, *te2; queue_init(&obsq); for (i = 1, te = od->tes + i; i < od->ntes; i++, te++) @@ -632,7 +632,7 @@ dump_tes(struct orderdata *od) static void reachable(struct orderdata *od, Id i) { - struct _TransactionElement *te = od->tes + i; + struct s_TransactionElement *te = od->tes + i; int j, k; if (te->mark != 0) @@ -660,7 +660,7 @@ addcycleedges(struct orderdata *od, Id *cycle, Queue *todo) Transaction *trans = od->trans; Pool *pool = trans->pool; #endif - struct _TransactionElement *te; + struct s_TransactionElement *te; int i, j, k, tail; int head; @@ -780,7 +780,7 @@ transaction_order(Transaction *trans, int flags) Solvable *s; int i, j, k, numte, numedge; struct orderdata od; - struct _TransactionElement *te; + struct s_TransactionElement *te; Queue todo, obsq, samerepoq, uninstq; int cycstart, cycel; Id *cycle; @@ -795,7 +795,7 @@ transaction_order(Transaction *trans, int flags) /* free old data if present */ if (trans->orderdata) { - struct _TransactionOrderdata *od = trans->orderdata; + struct s_TransactionOrderdata *od = trans->orderdata; od->tes = solv_free(od->tes); od->invedgedata = solv_free(od->invedgedata); trans->orderdata = solv_free(trans->orderdata); @@ -1069,7 +1069,7 @@ printf("do %s [%d]\n", pool_solvid2str(pool, te->p), temedianr[i]); s = pool->solvables + te->p; for (j = te->edges; od.invedgedata[j]; j++) { - struct _TransactionElement *te2 = od.tes + od.invedgedata[j]; + struct s_TransactionElement *te2 = od.tes + od.invedgedata[j]; assert(te2->mark > 0); if (--te2->mark == 0) { @@ -1103,7 +1103,7 @@ printf("free %s [%d]\n", pool_solvid2str(pool, te2->p), temedianr[od.invedgedata if ((flags & (SOLVER_TRANSACTION_KEEP_ORDERDATA | SOLVER_TRANSACTION_KEEP_ORDERCYCLES)) != 0) { - struct _TransactionOrderdata *tod; + struct s_TransactionOrderdata *tod; trans->orderdata = tod = solv_calloc(1, sizeof(*trans->orderdata)); if ((flags & SOLVER_TRANSACTION_KEEP_ORDERCYCLES) != 0) { @@ -1137,8 +1137,8 @@ int transaction_order_add_choices(Transaction *trans, Id chosen, Queue *choices) { int i, j; - struct _TransactionOrderdata *od = trans->orderdata; - struct _TransactionElement *te; + struct s_TransactionOrderdata *od = trans->orderdata; + struct s_TransactionElement *te; if (!od) return choices->count; @@ -1349,7 +1349,7 @@ transaction_check_order(Transaction *trans) void transaction_order_get_cycleids(Transaction *trans, Queue *q, int minseverity) { - struct _TransactionOrderdata *od = trans->orderdata; + struct s_TransactionOrderdata *od = trans->orderdata; Queue *cq; int i, cid, ncycles; @@ -1377,7 +1377,7 @@ transaction_order_get_cycleids(Transaction *trans, Queue *q, int minseverity) int transaction_order_get_cycle(Transaction *trans, Id cid, Queue *q) { - struct _TransactionOrderdata *od = trans->orderdata; + struct s_TransactionOrderdata *od = trans->orderdata; Queue *cq; int cmin, cmax, severity; int ncycles; diff --git a/src/policy.c b/src/policy.c index e1682f2..191327a 100644 --- a/src/policy.c +++ b/src/policy.c @@ -866,8 +866,6 @@ move_installed_to_front(Pool *pool, Queue *plist) Solvable *s; Id p, pp; - if (!pool->installed) - return; for (i = j = 0; i < plist->count; i++) { s = pool->solvables + plist->elements[i]; @@ -926,9 +924,9 @@ prune_to_best_version(Pool *pool, Queue *plist) { s = pool->solvables + plist->elements[i]; - POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s [%d]%s\n", - pool_solvable2str(pool, s), plist->elements[i], - (pool->installed && s->repo == pool->installed) ? "I" : ""); + POOL_DEBUG(SOLV_DEBUG_POLICY, "- %s[%s]\n", + pool_solvable2str(pool, s), + (pool->installed && s->repo == pool->installed) ? "installed" : "not installed"); if (!best) /* if no best yet, the current is best */ { @@ -963,6 +961,8 @@ prune_to_best_version(Pool *pool, Queue *plist) else prune_obsoleted(pool, plist); } + if (plist->count > 1 && pool->installed) + move_installed_to_front(pool, plist); } @@ -1343,7 +1343,6 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode) #endif dislike_old_versions(pool, plist); sort_by_common_dep(pool, plist); - move_installed_to_front(pool, plist); if (solv->urpmreorder) urpm_reorder(solv, plist); prefer_suggested(solv, plist); @@ -1365,7 +1364,6 @@ pool_best_solvables(Pool *pool, Queue *plist, int flags) { dislike_old_versions(pool, plist); sort_by_common_dep(pool, plist); - move_installed_to_front(pool, plist); } } @@ -927,7 +927,7 @@ pool_addstdproviders(Pool *pool, Id d) return 1; } queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); - dataiterator_init(&di, pool, 0, 0, SOLVABLE_FILELIST, str, SEARCH_STRING|SEARCH_FILES|SEARCH_COMPLETE_FILELIST); + dataiterator_init(&di, pool, 0, 0, SOLVABLE_FILELIST, str, SEARCH_STRING|SEARCH_FILES); for (; dataiterator_step(&di); dataiterator_skip_solvable(&di)) { Solvable *s = pool->solvables + di.solvid; @@ -1485,6 +1485,37 @@ pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker) queue_free(&qq); } +/* intersect dependencies in keyname with all provides of solvable solvid, + * return list of matching packages */ +/* this currently only works for installable packages */ +void +pool_whatmatchessolvable(Pool *pool, Id keyname, Id solvid, Queue *q, int marker) +{ + Id p; + Queue qq; + Map missc; /* cache for misses */ + int reloff; + + queue_empty(q); + queue_init(&qq); + reloff = pool->ss.nstrings; + map_init(&missc, reloff + pool->nrels); + FOR_POOL_SOLVABLES(p) + { + Solvable *s = pool->solvables + p; + if (p == solvid) + continue; /* filter out self-matches */ + if (s->repo->disabled) + continue; + if (s->repo != pool->installed && !pool_installable(pool, s)) + continue; + if (solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff)) + queue_push(q, p); + } + map_free(&missc); + queue_free(&qq); +} + /*************************************************************************/ void @@ -1505,7 +1536,6 @@ pool_debug(Pool *pool, int type, const char *format, ...) vprintf(format, args); else vfprintf(stderr, format, args); - va_end(args); return; } vsnprintf(buf, sizeof(buf), format, args); @@ -1567,12 +1597,12 @@ pool_setdebuglevel(Pool *pool, int level) if (level > 2) mask |= SOLV_DEBUG_PROPAGATE; if (level > 3) - mask |= SOLV_DEBUG_RULE_CREATION | SOLV_DEBUG_WATCHES; + mask |= SOLV_DEBUG_RULE_CREATION; mask |= pool->debugmask & SOLV_DEBUG_TO_STDERR; /* keep bit */ pool->debugmask = mask; } -void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct _Pool *, void *data, int type, const char *str), void *debugcallbackdata) +void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct s_Pool *, void *data, int type, const char *str), void *debugcallbackdata) { pool->debugcallback = debugcallback; pool->debugcallbackdata = debugcallbackdata; @@ -1583,20 +1613,20 @@ void pool_setdebugmask(Pool *pool, int mask) pool->debugmask = mask; } -void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata) +void pool_setloadcallback(Pool *pool, int (*cb)(struct s_Pool *, struct s_Repodata *, void *), void *loadcbdata) { pool->loadcallback = cb; pool->loadcallbackdata = loadcbdata; } -void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, Id), void *nscbdata) +void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct s_Pool *, void *, Id, Id), void *nscbdata) { pool->nscallback = cb; pool->nscallbackdata = nscbdata; } void -pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata) +pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct s_Repodata *data, struct s_Repokey *key, struct s_KeyValue *kv), void *cbdata) { if (p) { @@ -36,13 +36,13 @@ extern "C" { /*----------------------------------------------- */ -struct _Repo; -struct _Repodata; -struct _Repokey; -struct _KeyValue; +struct s_Repo; +struct s_Repodata; +struct s_Repokey; +struct s_KeyValue; -typedef struct _Datapos { - struct _Repo *repo; +typedef struct s_Datapos { + struct s_Repo *repo; Id solvid; Id repodataid; Id schema; @@ -55,7 +55,7 @@ typedef struct _Datapos { /* how many strings to maintain (round robin) */ #define POOL_TMPSPACEBUF 16 -struct _Pool_tmpspace { +struct s_Pool_tmpspace { char *buf[POOL_TMPSPACEBUF]; int len[POOL_TMPSPACEBUF]; int n; @@ -63,19 +63,19 @@ struct _Pool_tmpspace { #endif -struct _Pool { +struct s_Pool { void *appdata; /* application private pointer */ - struct _Stringpool ss; + struct s_Stringpool ss; Reldep *rels; /* table of rels: Id -> Reldep */ int nrels; /* number of unique rels */ - struct _Repo **repos; + struct s_Repo **repos; int nrepos; /* repos allocated */ int urepos; /* repos in use */ - struct _Repo *installed; /* packages considered installed */ + struct s_Repo *installed; /* packages considered installed */ Solvable *solvables; int nsolvables; /* solvables allocated */ @@ -109,16 +109,16 @@ struct _Pool { Map *considered; /* callback for REL_NAMESPACE dependencies handled by the application */ - Id (*nscallback)(struct _Pool *, void *data, Id name, Id evr); + Id (*nscallback)(struct s_Pool *, void *data, Id name, Id evr); void *nscallbackdata; /* debug mask and callback */ int debugmask; - void (*debugcallback)(struct _Pool *, void *data, int type, const char *str); + void (*debugcallback)(struct s_Pool *, void *data, int type, const char *str); void *debugcallbackdata; /* load callback */ - int (*loadcallback)(struct _Pool *, struct _Repodata *, void *); + int (*loadcallback)(struct s_Pool *, struct s_Repodata *, void *); void *loadcallbackdata; /* search position */ @@ -148,14 +148,14 @@ struct _Pool { int languagecacheother; /* our tmp space string space */ - struct _Pool_tmpspace tmpspace; + struct s_Pool_tmpspace tmpspace; char *errstr; /* last error string */ int errstra; /* allocated space for errstr */ char *rootdir; - int (*custom_vendorcheck)(struct _Pool *, Solvable *, Solvable *); + int (*custom_vendorcheck)(struct s_Pool *, Solvable *, Solvable *); int addfileprovidesfiltered; /* 1: only use filtered file list for addfileprovides */ int addedfileprovides; /* true: application called addfileprovides */ @@ -188,7 +188,6 @@ struct _Pool { #define SOLV_DEBUG_JOB (1<<11) #define SOLV_DEBUG_SOLVER (1<<12) #define SOLV_DEBUG_TRANSACTION (1<<13) -#define SOLV_DEBUG_WATCHES (1<<14) #define SOLV_DEBUG_TO_STDERR (1<<30) @@ -247,13 +246,13 @@ extern int pool_set_flag(Pool *pool, int flag, int value); extern int pool_get_flag(Pool *pool, int flag); extern void pool_debug(Pool *pool, int type, const char *format, ...) __attribute__((format(printf, 3, 4))); -extern void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct _Pool *, void *data, int type, const char *str), void *debugcallbackdata); +extern void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct s_Pool *, void *data, int type, const char *str), void *debugcallbackdata); extern void pool_setdebugmask(Pool *pool, int mask); -extern void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata); -extern void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, Id), void *nscbdata); +extern void pool_setloadcallback(Pool *pool, int (*cb)(struct s_Pool *, struct s_Repodata *, void *), void *loadcbdata); +extern void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct s_Pool *, void *, Id, Id), void *nscbdata); extern void pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr); -extern void pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(struct _Pool *, Solvable *, Solvable *)); +extern void pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(struct s_Pool *, Solvable *, Solvable *)); extern char *pool_alloctmpspace(Pool *pool, int len); @@ -262,7 +261,7 @@ extern char *pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const extern char *pool_tmpappend(Pool *pool, const char *str1, const char *str2, const char *str3); extern const char *pool_bin2hex(Pool *pool, const unsigned char *buf, int len); -extern void pool_set_installed(Pool *pool, struct _Repo *repo); +extern void pool_set_installed(Pool *pool, struct s_Repo *repo); extern int pool_error(Pool *pool, int ret, const char *format, ...) __attribute__((format(printf, 3, 4))); extern char *pool_errstr(Pool *pool); @@ -349,6 +348,7 @@ static inline Id *pool_whatprovides_ptr(Pool *pool, Id d) void pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker); void pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker); +void pool_whatmatchessolvable(Pool *pool, Id keyname, Id solvid, Queue *q, int marker); void pool_set_whatprovides(Pool *pool, Id id, Id providers); @@ -357,7 +357,7 @@ void pool_set_whatprovides(Pool *pool, Id id, Id providers); * key - search only this key * match - key must match this string */ -void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata); +void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct s_Repodata *data, struct s_Repokey *key, struct s_KeyValue *kv), void *cbdata); void pool_clear_pos(Pool *pool); @@ -374,17 +374,17 @@ const char *pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *median #define DUCHANGES_ONLYADD 1 -typedef struct _DUChanges { +typedef struct s_DUChanges { const char *path; - int kbytes; - int files; + long long kbytes; + long long files; int flags; } DUChanges; void pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap); void pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps); -int pool_calc_installsizechange(Pool *pool, Map *installedmap); +long long pool_calc_installsizechange(Pool *pool, Map *installedmap); void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts); diff --git a/src/poolarch.c b/src/poolarch.c index 4a1fa50..6727760 100644 --- a/src/poolarch.c +++ b/src/poolarch.c @@ -33,6 +33,10 @@ static const char *archpolicies[] = { "ppc64", "ppc64:ppc", "ppc64p7", "ppc64p7:ppc64:ppc", "ia64", "ia64:i686:i586:i486:i386", + "armv8hcnl", "armv8hcnl:armv8hnl:armv8hl:armv7hnl:armv7hl:armv6hl", + "armv8hnl", "armv8hnl:armv8hl:armv7hnl:armv7hl:armv6hl", + "armv8hl", "armv8hl:armv7hl:armv6hl", + "armv8l", "armv8l:armv7l:armv6l:armv5tejl:armv5tel:armv5tl:armv5l:armv4tl:armv4l:armv3l", "armv7hnl", "armv7hnl:armv7hl:armv6hl", "armv7hl", "armv7hl:armv6hl", "armv7l", "armv7l:armv6l:armv5tejl:armv5tel:armv5tl:armv5l:armv4tl:armv4l:armv3l", diff --git a/src/poolid.h b/src/poolid.h index 79a3ccd..f832ff4 100644 --- a/src/poolid.h +++ b/src/poolid.h @@ -24,7 +24,7 @@ extern "C" { * Ids with relation */ -typedef struct _Reldep { +typedef struct s_Reldep { Id name; /* "package" */ Id evr; /* "0:42-3" */ int flags; /* operation/relation, see REL_x in pool.h */ diff --git a/src/pooltypes.h b/src/pooltypes.h index 64a3b87..e1f77b0 100644 --- a/src/pooltypes.h +++ b/src/pooltypes.h @@ -27,11 +27,11 @@ #define SOLV_FLAG_PREFIX_POOL 4 #define SOLV_FLAG_SIZE_BYTES 8 -struct _Stringpool; -typedef struct _Stringpool Stringpool; +struct s_Stringpool; +typedef struct s_Stringpool Stringpool; -struct _Pool; -typedef struct _Pool Pool; +struct s_Pool; +typedef struct s_Pool Pool; /* identifier for string values */ typedef int Id; /* must be signed!, since negative Id is used in solver rules to denote negation */ diff --git a/src/problems.c b/src/problems.c index 2b5cefd..df751c4 100644 --- a/src/problems.c +++ b/src/problems.c @@ -247,23 +247,8 @@ solver_autouninstall(Solver *solv, int start) if (v >= solv->updaterules && v < solv->updaterules_end) { Rule *r; - Id p = solv->installed->start + (v - solv->updaterules); if (m && !MAPTST(m, v - solv->updaterules)) continue; - if (pool->considered && !MAPTST(pool->considered, p)) - continue; /* do not uninstalled disabled packages */ - if (solv->bestrules_pkg && solv->bestrules_end > solv->bestrules) - { - int j; - for (j = start + 1; j < solv->problems.count - 1; j++) - { - Id vv = solv->problems.elements[j]; - if (vv >= solv->bestrules && vv < solv->bestrules_end && solv->bestrules_pkg[vv - solv->bestrules] == p) - break; - } - if (j < solv->problems.count - 1) - continue; /* best rule involved, do not uninstall */ - } /* check if identical to feature rule, we don't like that (except for orphans) */ r = solv->rules + solv->featurerules + (v - solv->updaterules); if (!r->p) @@ -275,7 +260,7 @@ solver_autouninstall(Solver *solv, int start) if (solv->keep_orphans) { r = solv->rules + v; - if (!r->d && !r->w2 && r->p == p) + if (!r->d && !r->w2 && r->p == (solv->installed->start + (v - solv->updaterules))) { lastfeature = v; lastupdate = 0; diff --git a/src/problems.h b/src/problems.h index 63319d6..37021e1 100644 --- a/src/problems.h +++ b/src/problems.h @@ -20,7 +20,7 @@ extern "C" { #endif -struct _Solver; +struct s_Solver; #define SOLVER_SOLUTION_JOB (0) #define SOLVER_SOLUTION_DISTUPGRADE (-1) @@ -28,31 +28,31 @@ struct _Solver; #define SOLVER_SOLUTION_BEST (-3) #define SOLVER_SOLUTION_POOLJOB (-4) -void solver_recordproblem(struct _Solver *solv, Id rid); -void solver_fixproblem(struct _Solver *solv, Id rid); -Id solver_autouninstall(struct _Solver *solv, int start); -void solver_disableproblemset(struct _Solver *solv, int start); +void solver_recordproblem(struct s_Solver *solv, Id rid); +void solver_fixproblem(struct s_Solver *solv, Id rid); +Id solver_autouninstall(struct s_Solver *solv, int start); +void solver_disableproblemset(struct s_Solver *solv, int start); -int solver_prepare_solutions(struct _Solver *solv); +int solver_prepare_solutions(struct s_Solver *solv); -unsigned int solver_problem_count(struct _Solver *solv); -Id solver_next_problem(struct _Solver *solv, Id problem); -unsigned int solver_solution_count(struct _Solver *solv, Id problem); -Id solver_next_solution(struct _Solver *solv, Id problem, Id solution); -unsigned int solver_solutionelement_count(struct _Solver *solv, Id problem, Id solution); -Id solver_solutionelement_internalid(struct _Solver *solv, Id problem, Id solution); -Id solver_solutionelement_extrajobflags(struct _Solver *solv, Id problem, Id solution); -Id solver_next_solutionelement(struct _Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp); +unsigned int solver_problem_count(struct s_Solver *solv); +Id solver_next_problem(struct s_Solver *solv, Id problem); +unsigned int solver_solution_count(struct s_Solver *solv, Id problem); +Id solver_next_solution(struct s_Solver *solv, Id problem, Id solution); +unsigned int solver_solutionelement_count(struct s_Solver *solv, Id problem, Id solution); +Id solver_solutionelement_internalid(struct s_Solver *solv, Id problem, Id solution); +Id solver_solutionelement_extrajobflags(struct s_Solver *solv, Id problem, Id solution); +Id solver_next_solutionelement(struct s_Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp); -void solver_take_solutionelement(struct _Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job); -void solver_take_solution(struct _Solver *solv, Id problem, Id solution, Queue *job); +void solver_take_solutionelement(struct s_Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job); +void solver_take_solution(struct s_Solver *solv, Id problem, Id solution, Queue *job); -Id solver_findproblemrule(struct _Solver *solv, Id problem); -void solver_findallproblemrules(struct _Solver *solv, Id problem, Queue *rules); +Id solver_findproblemrule(struct s_Solver *solv, Id problem); +void solver_findallproblemrules(struct s_Solver *solv, Id problem, Queue *rules); -extern const char *solver_problemruleinfo2str(struct _Solver *solv, SolverRuleinfo type, Id source, Id target, Id dep); -extern const char *solver_problem2str(struct _Solver *solv, Id problem); -extern const char *solver_solutionelement2str(struct _Solver *solv, Id p, Id rp); +extern const char *solver_problemruleinfo2str(struct s_Solver *solv, SolverRuleinfo type, Id source, Id target, Id dep); +extern const char *solver_problem2str(struct s_Solver *solv, Id problem); +extern const char *solver_solutionelement2str(struct s_Solver *solv, Id p, Id rp); #ifdef __cplusplus } diff --git a/src/queue.h b/src/queue.h index 7e56035..8b1ef08 100644 --- a/src/queue.h +++ b/src/queue.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef struct _Queue { +typedef struct s_Queue { Id *elements; /* pointer to elements */ int count; /* current number of elements in queue */ Id *alloc; /* this is whats actually allocated, elements > alloc if shifted */ @@ -672,11 +672,12 @@ struct matchdata int flags; Datamatcher matcher; int stop; + Id *keyskip; int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv); void *callback_data; }; -int +static int repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) { struct matchdata *md = cbdata; @@ -692,6 +693,12 @@ repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValu if (!datamatcher_match(&md->matcher, str)) return 0; } + else + { + /* stringify filelist if requested */ + if (key->name == SOLVABLE_FILELIST && key->type == REPOKEY_TYPE_DIRSTRARRAY && (md->matcher.flags & SEARCH_FILES) != 0) + repodata_stringify(md->pool, data, key, kv, md->flags); + } md->stop = md->callback(md->callback_data, s, data, key, kv); return md->stop; } @@ -736,8 +743,9 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md) KeyValue kv; Pool *pool = repo->pool; Repodata *data; - int i, j, flags; + int i, flags; Solvable *s; + Id *keyskip; kv.parent = 0; md->stop = 0; @@ -752,12 +760,10 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md) } return; } - else if (p < 0) - /* The callback only supports solvables, so we can't iterate over the - extra things. */ - return; + if (p < 0 && p != SOLVID_META) + return; /* SOLVID_POS not supported yet */ flags = md->flags; - if (!(flags & SEARCH_NO_STORAGE_SOLVABLE)) + if (p > 0 && !(flags & SEARCH_NO_STORAGE_SOLVABLE)) { s = pool->solvables + p; switch(keyname) @@ -850,42 +856,23 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md) } } + if (keyname) + { + if (keyname == SOLVABLE_FILELIST) + data = repo_lookup_filelist_repodata(repo, p, &md->matcher); + else + data = repo_lookup_repodata_opt(repo, p, keyname); + if (data) + repodata_search(data, p, keyname, md->flags, repo_matchvalue, md); + return; + } + + keyskip = repo_create_keyskip(repo, p, &md->keyskip); FOR_REPODATAS(repo, i, data) { - if (p < data->start || p >= data->end) - continue; - if (keyname && !repodata_precheck_keyname(data, keyname)) + if (p != SOLVID_META && (p < data->start || p >= data->end)) continue; - if (keyname == SOLVABLE_FILELIST && !(md->flags & SEARCH_COMPLETE_FILELIST)) - { - /* do not search filelist extensions */ - if (data->state != REPODATA_AVAILABLE) - continue; - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - break; - if (j == data->nkeys) - continue; - } - if (data->state == REPODATA_STUB) - { - if (keyname) - { - for (j = 1; j < data->nkeys; j++) - if (keyname == data->keys[j].name) - break; - if (j == data->nkeys) - continue; - } - /* load it */ - if (data->loadcallback) - data->loadcallback(data); - else - data->state = REPODATA_ERROR; - } - if (data->state == REPODATA_ERROR) - continue; - repodata_search(data, p, keyname, md->flags, repo_matchvalue, md); + repodata_search_keyskip(data, p, keyname, md->flags, keyskip, repo_matchvalue, md); if (md->stop > SEARCH_NEXT_KEY) break; } @@ -908,18 +895,181 @@ repo_search(Repo *repo, Id p, Id keyname, const char *match, int flags, int (*ca repo_search_md(repo, p, keyname, &md); if (match) datamatcher_free(&md.matcher); + solv_free(md.keyskip); +} + +Repodata * +repo_lookup_repodata(Repo *repo, Id entry, Id keyname) +{ + Repodata *data; + int rdid; + Id type; + + if (entry == SOLVID_POS) + { + Pool *pool = repo->pool; + return pool->pos.repo == repo && pool->pos.repodataid ? pool->pos.repo->repodata + pool->pos.repodataid : 0; + } + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) + { + if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) + continue; + if (!repodata_precheck_keyname(data, keyname)) + continue; + if ((type = repodata_lookup_type(data, entry, keyname)) != 0) + return type == REPOKEY_TYPE_DELETED ? 0 : data; + } + return 0; +} + +/* like repo_lookup_repodata, but may return a repodata that contains no match instead of NULL */ +Repodata * +repo_lookup_repodata_opt(Repo *repo, Id entry, Id keyname) +{ + Repodata *data, *found = 0; + int rdid; + Id type; + + if (entry == SOLVID_POS) + { + Pool *pool = repo->pool; + return pool->pos.repo == repo && pool->pos.repodataid ? pool->pos.repo->repodata + pool->pos.repodataid : 0; + } + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) + { + if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) + continue; + if (!repodata_precheck_keyname(data, keyname)) + continue; + if (found && (type = repodata_lookup_type(found, entry, keyname)) != 0) + return type == REPOKEY_TYPE_DELETED ? 0 : found; + found = data; + } + return found; +} + +Repodata * +repo_lookup_filelist_repodata(Repo *repo, Id entry, Datamatcher *matcher) +{ + Repodata *data; + int haveextension; + int rdid; + Id type; + + if (entry <= 0 || !matcher || !matcher->match || ((matcher->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING + && (matcher->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)) + return repo_lookup_repodata_opt(repo, entry, SOLVABLE_FILELIST); /* cannot use filtered filelist */ + + haveextension = 0; + for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--) + { + if (entry < data->start || entry >= data->end) + continue; + if (data->filelisttype == REPODATA_FILELIST_FILTERED) + { + if (data->state != REPODATA_AVAILABLE) + { + if (data->state != REPODATA_STUB) + continue; + repodata_load(data); + if (data->state != REPODATA_AVAILABLE || entry < data->start || entry >= data->end) + continue; + } + /* does this contain any data about the solvable we're looking for? */ + if (!data->incoreoffset[entry - data->start]) + continue; /* no, ignore */ + if (haveextension && repodata_filelistfilter_matches(data, matcher->match)) + return data; + break; /* fall back to normal code */ + } + if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) + continue; + if (data->filelisttype == REPODATA_FILELIST_EXTENSION) + { + haveextension++; + continue; + } + if ((type = repodata_lookup_type(data, entry, SOLVABLE_FILELIST)) != 0) + { + if (haveextension) + break; /* need to look in extension */ + return type == REPOKEY_TYPE_DELETED ? 0 : data; + } + } + /* cannot use filtered filelist */ + return repo_lookup_repodata_opt(repo, entry, SOLVABLE_FILELIST); +} + + +/* the keyskip array has the following format: + * 0: keyname area size + * 1: repoid base + * 2: repoid end + * 3: entry for keyname 0 + * 4: entry for keyname 1 + * ... + */ +Id * +repo_create_keyskip(Repo *repo, Id entry, Id **oldkeyskip) +{ + Repodata *data, *last = 0; + Id *keyskip; + int rdid, cnt = 0; + + if (repo->nrepodata <= 2) + return 0; /* just one repodata, nothing to filter */ + keyskip = oldkeyskip ? *oldkeyskip : 0; + if (keyskip) + { + if (keyskip[1] >= 0x10000000) + keyskip = solv_free(keyskip); + else + keyskip[1] = keyskip[2]; + } + FOR_REPODATAS(repo, rdid, data) + { + if (entry != SOLVID_META) + { + if (data->state != REPODATA_AVAILABLE && data->state != REPODATA_LOADING) + { + if (data->state != REPODATA_STUB) + continue; + repodata_load(data); + if (data->state != REPODATA_AVAILABLE) + continue; + } + if ((entry < data->start || entry >= data->end)) + continue; + if (!data->incoreoffset[entry - data->start]) + continue; + } + if (last) + keyskip = repodata_fill_keyskip(last, entry, keyskip); + last = data; + cnt++; + } + if (cnt <= 1) + { + if (oldkeyskip) + *oldkeyskip = keyskip; + return 0; + } + keyskip = repodata_fill_keyskip(last, entry, keyskip); + if (keyskip) + keyskip[2] = keyskip[1] + repo->nrepodata; + if (oldkeyskip) + *oldkeyskip = keyskip; + return keyskip; } const char * repo_lookup_str(Repo *repo, Id entry, Id keyname) { - Pool *pool = repo->pool; Repodata *data; - int i; - const char *str; if (entry >= 0) { + Pool *pool = repo->pool; switch (keyname) { case SOLVABLE_NAME: @@ -932,31 +1082,15 @@ repo_lookup_str(Repo *repo, Id entry, Id keyname) return pool_id2str(pool, pool->solvables[entry].vendor); } } - else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname); - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - str = repodata_lookup_str(data, entry, keyname); - if (str) - return str; - if (repodata_lookup_type(data, entry, keyname)) - return 0; - } - return 0; + data = repo_lookup_repodata_opt(repo, entry, keyname); + return data ? repodata_lookup_str(data, entry, keyname) : 0; } unsigned long long repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned long long notfound) { - Pool *pool = repo->pool; Repodata *data; - int i; - unsigned long long value; if (entry >= 0) { @@ -967,28 +1101,14 @@ repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned long long notfound) return notfound; } } - else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, &value) ? value : notfound; - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - if (repodata_lookup_num(data, entry, keyname, &value)) - return value; - if (repodata_lookup_type(data, entry, keyname)) - return notfound; - } - return notfound; + data = repo_lookup_repodata_opt(repo, entry, keyname); + return data ? repodata_lookup_num(data, entry, keyname, notfound) : notfound; } Id repo_lookup_id(Repo *repo, Id entry, Id keyname) { - Pool *pool = repo->pool; Repodata *data; - int i; Id id; if (entry >= 0) @@ -1005,24 +1125,9 @@ repo_lookup_id(Repo *repo, Id entry, Id keyname) return repo->pool->solvables[entry].vendor; } } - else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - { - Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid; - Id id = repodata_lookup_id(data, entry, keyname); - return data->localpool ? repodata_globalize_id(data, id, 1) : id; - } - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - id = repodata_lookup_id(data, entry, keyname); - if (id) - return data->localpool ? repodata_globalize_id(data, id, 1) : id; - if (repodata_lookup_type(data, entry, keyname)) - return 0; - } + data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data && (id = repodata_lookup_id(data, entry, keyname)) != 0) + return data->localpool ? repodata_globalize_id(data, id, 1) : id; return 0; } @@ -1041,7 +1146,6 @@ lookup_idarray_solvable(Repo *repo, Offset off, Queue *q) int repo_lookup_idarray(Repo *repo, Id entry, Id keyname, Queue *q) { - Pool *pool = repo->pool; Repodata *data; int i; if (entry >= 0) @@ -1066,36 +1170,15 @@ repo_lookup_idarray(Repo *repo, Id entry, Id keyname, Queue *q) return lookup_idarray_solvable(repo, repo->pool->solvables[entry].enhances, q); } } - else if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - { - Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid; - if (repodata_lookup_idarray(data, entry, keyname, q)) - { - if (data->localpool) - { - for (i = 0; i < q->count; i++) - q->elements[i] = repodata_globalize_id(data, q->elements[i], 1); - } - return 1; - } - } - FOR_REPODATAS(repo, i, data) + data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data && repodata_lookup_idarray(data, entry, keyname, q)) { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - if (repodata_lookup_idarray(data, entry, keyname, q)) + if (data->localpool) { - if (data->localpool) - { - for (i = 0; i < q->count; i++) - q->elements[i] = repodata_globalize_id(data, q->elements[i], 1); - } - return 1; + for (i = 0; i < q->count; i++) + q->elements[i] = repodata_globalize_id(data, q->elements[i], 1); } - if (repodata_lookup_type(data, entry, keyname)) - break; + return 1; } queue_empty(q); return 0; @@ -1139,25 +1222,10 @@ repo_lookup_deparray(Repo *repo, Id entry, Id keyname, Queue *q, Id marker) const unsigned char * repo_lookup_bin_checksum(Repo *repo, Id entry, Id keyname, Id *typep) { - Pool *pool = repo->pool; - Repodata *data; - int i; const unsigned char *chk; - - if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, typep); - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - chk = repodata_lookup_bin_checksum(data, entry, keyname, typep); - if (chk) - return chk; - if (repodata_lookup_type(data, entry, keyname)) - return 0; - } + Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data && (chk = repodata_lookup_bin_checksum(data, entry, keyname, typep)) != 0) + return chk; *typep = 0; return 0; } @@ -1172,69 +1240,29 @@ repo_lookup_checksum(Repo *repo, Id entry, Id keyname, Id *typep) int repo_lookup_void(Repo *repo, Id entry, Id keyname) { - Pool *pool = repo->pool; - Repodata *data; - int i; - Id type; - - if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname); - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - type = repodata_lookup_type(data, entry, keyname); - if (type) - return type == REPOKEY_TYPE_VOID; - } + Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data) + return repodata_lookup_void(data, entry, keyname); return 0; } Id repo_lookup_type(Repo *repo, Id entry, Id keyname) { - Pool *pool = repo->pool; - Repodata *data; - int i; Id type; - - if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_type(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname); - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - type = repodata_lookup_type(data, entry, keyname); - if (type) - return type == REPOKEY_TYPE_DELETED ? 0 : type; - } + Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data && (type = repodata_lookup_type(data, entry, keyname)) != 0 && type != REPOKEY_TYPE_DELETED) + return type; return 0; } const void * repo_lookup_binary(Repo *repo, Id entry, Id keyname, int *lenp) { - Pool *pool = repo->pool; - Repodata *data; - int i; const void *bin; - - if (entry == SOLVID_POS && pool->pos.repo == repo && pool->pos.repodataid) - return repodata_lookup_binary(pool->pos.repo->repodata + pool->pos.repodataid, entry, keyname, lenp); - FOR_REPODATAS(repo, i, data) - { - if (entry != SOLVID_META && (entry < data->start || entry >= data->end)) - continue; - if (!repodata_precheck_keyname(data, keyname)) - continue; - bin = repodata_lookup_binary(data, entry, keyname, lenp); - if (bin) - return bin; - } + Repodata *data = repo_lookup_repodata_opt(repo, entry, keyname); + if (data && (bin = repodata_lookup_binary(data, entry, keyname, lenp)) != 0) + return bin; *lenp = 0; return 0; } @@ -24,7 +24,7 @@ extern "C" { #endif -typedef struct _Repo { +typedef struct s_Repo { const char *name; /* name pointer */ Id repoid; /* our id */ void *appdata; /* application private pointer */ @@ -146,6 +146,11 @@ Repodata *repo_last_repodata(Repo *repo); void repo_search(Repo *repo, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata); +/* returns the last repodata that contains the key */ +Repodata *repo_lookup_repodata(Repo *repo, Id entry, Id keyname); +Repodata *repo_lookup_repodata_opt(Repo *repo, Id entry, Id keyname); +Repodata *repo_lookup_filelist_repodata(Repo *repo, Id entry, Datamatcher *matcher); + /* returns the string value of the attribute, or NULL if not found */ Id repo_lookup_type(Repo *repo, Id entry, Id keyname); const char *repo_lookup_str(Repo *repo, Id entry, Id keyname); @@ -173,6 +178,8 @@ void repo_unset(Repo *repo, Id p, Id keyname); void repo_internalize(Repo *repo); void repo_disable_paging(Repo *repo); +Id *repo_create_keyskip(Repo *repo, Id entry, Id **oldkeyskip); + /* iterator macros */ #define FOR_REPO_SOLVABLES(r, p, s) \ diff --git a/src/repo_solv.c b/src/repo_solv.c index 5858d4f..be33967 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -478,7 +478,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) int oldnstrings = pool->ss.nstrings; int oldnrels = pool->nrels; - struct _Stringpool *spool; + struct s_Stringpool *spool; Repodata *parent = 0; Repodata data; @@ -859,7 +859,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) type = idmap[type]; else if ((flags & REPO_LOCALPOOL) != 0) type = pool_str2id(pool, stringpool_id2str(spool, type), 1); - if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_FLEXARRAY) + if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_DELETED) { data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported data type '%s'", pool_id2str(pool, type)); type = REPOKEY_TYPE_VOID; @@ -879,6 +879,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "main solvable data must use incore storage %d", keys[i].storage); keys[i].storage = KEY_STORAGE_SOLVABLE; } + if ((type == REPOKEY_TYPE_FIXARRAY || type == REPOKEY_TYPE_FLEXARRAY) && keys[i].storage != KEY_STORAGE_INCORE) + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "flex/fixarrays must use incore storage\n"); /* cannot handle rel idarrays in incore/vertical */ if (type == REPOKEY_TYPE_REL_IDARRAY && keys[i].storage != KEY_STORAGE_SOLVABLE) data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "type REL_IDARRAY is only supported for STORAGE_SOLVABLE"); @@ -1216,12 +1218,9 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key } /* FALLTHROUGH */ default: - if (id == RPM_RPMDBID && s && (keys[key].type == REPOKEY_TYPE_U32 || keys[key].type == REPOKEY_TYPE_NUM)) + if (id == RPM_RPMDBID && s && keys[key].type == REPOKEY_TYPE_NUM) { - if (keys[key].type == REPOKEY_TYPE_U32) - dp = data_read_u32(dp, (unsigned int *)&id); - else - dp = data_read_id_max(dp, &id, 0, 0, &data); + dp = data_read_id_max(dp, &id, 0, 0, &data); if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); repo->rpmdbid[(s - pool->solvables) - repo->start] = id; @@ -1270,7 +1269,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key keys[i].type = REPOKEY_TYPE_IDARRAY; for (i = 1; i < numkeys; i++) - if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) + if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET && keys[i].size) break; if (i < numkeys && !data.error) { @@ -1310,6 +1309,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key /* overwrite stub repodata */ repodata_freedata(parent); data.repodataid = parent->repodataid; + data.loadcallback = parent->loadcallback; *parent = data; } else @@ -1326,6 +1326,17 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key repo->repodata[repo->nrepodata++] = data; } + if ((flags & REPO_EXTEND_SOLVABLES) != 0) + { + if (repodata_has_keyname(&data, SOLVABLE_FILELIST)) + repodata_set_filelisttype(repo->repodata + data.repodataid, REPODATA_FILELIST_EXTENSION); + } + else + { + if (repodata_lookup_type(&data, SOLVID_META, REPOSITORY_FILTEREDFILELIST)) + repodata_set_filelisttype(repo->repodata + data.repodataid, REPODATA_FILELIST_FILTERED); + } + /* create stub repodata entries for all external */ if (!(flags & SOLV_ADD_NO_STUBS) && !parent) { @@ -1333,7 +1344,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key if (data.keys[key].name == REPOSITORY_EXTERNAL && data.keys[key].type == REPOKEY_TYPE_FLEXARRAY) break; if (key < data.nkeys) - repodata_create_stubs(repo->repodata + (repo->nrepodata - 1)); + repodata_create_stubs(repo->repodata + data.repodataid); } POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_solv took %d ms\n", solv_timems(now)); diff --git a/src/repo_write.c b/src/repo_write.c index 7e78af5..a975cec 100644 --- a/src/repo_write.c +++ b/src/repo_write.c @@ -38,7 +38,7 @@ typedef struct needid { } NeedId; -#define RELOFF(id) (needid[0].map + GETRELID(id)) +#define NEEDIDOFF(id) (ISRELDEP(id) ? (needid[0].map + GETRELID(id)) : id) /* * increment need Id @@ -49,44 +49,22 @@ typedef struct needid { * */ -static void -incneedid(Pool *pool, Id id, NeedId *needid) +static inline void +incneedid(Id id, NeedId *needid) { - while (ISRELDEP(id)) - { - Reldep *rd = GETRELDEP(pool, id); - needid[RELOFF(id)].need++; - if (ISRELDEP(rd->evr)) - incneedid(pool, rd->evr, needid); - else - needid[rd->evr].need++; - id = rd->name; - } - needid[id].need++; + needid[NEEDIDOFF(id)].need++; } static int -incneedidarray(Pool *pool, Id *idarray, NeedId *needid) +incneedidarray(Id *idarray, NeedId *needid) { Id id; int n = 0; - if (!idarray) - return 0; while ((id = *idarray++) != 0) { n++; - while (ISRELDEP(id)) - { - Reldep *rd = GETRELDEP(pool, id); - needid[RELOFF(id)].need++; - if (ISRELDEP(rd->evr)) - incneedid(pool, rd->evr, needid); - else - needid[rd->evr].need++; - id = rd->name; - } - needid[id].need++; + needid[NEEDIDOFF(id)].need++; } return n + 1; } @@ -248,7 +226,7 @@ write_idarray(Repodata *data, Pool *pool, NeedId *needid, Id *ids) { id = *ids++; if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + id = needid[NEEDIDOFF(id)].need; if (id >= 64) id = (id & 63) | ((id & ~63) << 1); if (!*ids) @@ -266,23 +244,21 @@ struct extdata { }; struct cbdata { + Pool *pool; Repo *repo; Repodata *target; Stringpool *ownspool; Dirpool *owndirpool; + int clonepool; /* are the pool ids cloned into ownspool? */ - Id *keymap; - int nkeymap; - Id *keymapstart; + Id *keymap; /* keymap for this repodata */ NeedId *needid; Id *schema; /* schema construction space */ Id *sp; /* pointer in above */ - Id *oldschema, *oldsp; - Id *solvschemata; Id *subschemata; int nsubschemata; int current_sub; @@ -291,18 +267,20 @@ struct cbdata { Id *dirused; - Id vstart; + Id vstart; /* offset of key in vertical data */ Id maxdata; Id lastlen; int doingsolvables; /* working on solvables data */ int filelistmode; + + Id lastdirid; /* last dir id seen in this repodata */ + Id lastdirid_own; /* last dir id put in own pool */ }; -#define NEEDED_BLOCK 1023 +#define NEEDID_BLOCK 1023 #define SCHEMATA_BLOCK 31 -#define SCHEMATADATA_BLOCK 255 #define EXTDATA_BLOCK 4095 static inline void @@ -411,7 +389,7 @@ data_adddepids(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marke { Id id = ids[len]; if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + id = needid[NEEDIDOFF(id)].need; lids[len] = id; } if (ids[len]) @@ -424,7 +402,7 @@ data_adddepids(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marke { Id id = ids[len]; if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + id = needid[NEEDIDOFF(id)].need; sids[len] = id; } } @@ -493,7 +471,7 @@ data_adddepids(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marke while ((id = *ids++) != 0) { if (needid) - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + id = needid[NEEDIDOFF(id)].need; data_addideof(xd, id, *ids ? 0 : 1); } } @@ -508,73 +486,53 @@ data_addblob(struct extdata *xd, unsigned char *blob, int len) xd->len += len; } -static inline void -data_addu32(struct extdata *xd, unsigned int num) +/* grow needid array so that it contains the specified id */ +static void +grow_needid(struct cbdata *cbdata, Id id) { - unsigned char d[4]; - d[0] = num >> 24; - d[1] = num >> 16; - d[2] = num >> 8; - d[3] = num; - data_addblob(xd, d, 4); + int oldoff = cbdata->needid[0].map; + int newoff = (id + 1 + NEEDID_BLOCK) & ~NEEDID_BLOCK; + int nrels = cbdata->pool->nrels; + cbdata->needid = solv_realloc2(cbdata->needid, newoff + nrels, sizeof(NeedId)); + if (nrels) + memmove(cbdata->needid + newoff, cbdata->needid + oldoff, nrels * sizeof(NeedId)); + memset(cbdata->needid + oldoff, 0, (newoff - oldoff) * sizeof(NeedId)); + cbdata->needid[0].map = newoff; } static Id -putinownpool(struct cbdata *cbdata, Stringpool *ss, Id id) +putinownpool(struct cbdata *cbdata, Repodata *data, Id id) { + Stringpool *ss = data->localpool ? &data->spool : &cbdata->pool->ss; const char *str = stringpool_id2str(ss, id); id = stringpool_str2id(cbdata->ownspool, str, 1); if (id >= cbdata->needid[0].map) - { - int oldoff = cbdata->needid[0].map; - int newoff = (id + 1 + NEEDED_BLOCK) & ~NEEDED_BLOCK; - int nrels = cbdata->repo->pool->nrels; - cbdata->needid = solv_realloc2(cbdata->needid, newoff + nrels, sizeof(NeedId)); - if (nrels) - memmove(cbdata->needid + newoff, cbdata->needid + oldoff, nrels * sizeof(NeedId)); - memset(cbdata->needid + oldoff, 0, (newoff - oldoff) * sizeof(NeedId)); - cbdata->needid[0].map = newoff; - } + grow_needid(cbdata, id); return id; } static Id -putinowndirpool(struct cbdata *cbdata, Repodata *data, Dirpool *dp, Id dir) +putinowndirpool_slow(struct cbdata *cbdata, Repodata *data, Dirpool *dp, Id dir) { Id compid, parent; parent = dirpool_parent(dp, dir); if (parent) - parent = putinowndirpool(cbdata, data, dp, parent); - compid = dp->dirs[dir]; - if (cbdata->ownspool && compid > 1) - compid = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, compid); + parent = putinowndirpool_slow(cbdata, data, dp, parent); + compid = dirpool_compid(dp, dir); + if (cbdata->ownspool && compid > 1 && (!cbdata->clonepool || data->localpool)) + compid = putinownpool(cbdata, data, compid); return dirpool_add_dir(cbdata->owndirpool, parent, compid, 1); } -/* - * collect usage information about the dirs - * 1: dir used, no child of dir used - * 2: dir used as parent of another used dir - */ -static inline void -setdirused(struct cbdata *cbdata, Dirpool *dp, Id dir) +static inline Id +putinowndirpool(struct cbdata *cbdata, Repodata *data, Id dir) { - if (cbdata->dirused[dir]) - return; - cbdata->dirused[dir] = 1; - while ((dir = dirpool_parent(dp, dir)) != 0) - { - if (cbdata->dirused[dir] == 2) - return; - if (cbdata->dirused[dir]) - { - cbdata->dirused[dir] = 2; - return; - } - cbdata->dirused[dir] = 2; - } - cbdata->dirused[0] = 2; + if (dir && dir == cbdata->lastdirid) + return cbdata->lastdirid_own; + cbdata->lastdirid = dir; + cbdata->lastdirid_own = putinowndirpool_slow(cbdata, data, &data->dirpool, dir); + return cbdata->lastdirid_own; } /* @@ -582,26 +540,24 @@ setdirused(struct cbdata *cbdata, Dirpool *dp, Id dir) * collect key/id/dirid usage information, create needed schemas */ static int -repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Repokey *key, KeyValue *kv) +collect_needed_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) { + struct cbdata *cbdata = vcbdata; Id id; int rm; +#if 0 + fprintf(stderr, "solvable %d (%s): key (%d)%s %d\n", s ? (int)(s - cbdata->pool->solvables) : 0, s ? pool_id2str(cbdata->pool, s->name) : "", key->name, pool_id2str(cbdata->pool, key->name), key->type); +#endif if (key->name == REPOSITORY_SOLVABLES) return SEARCH_NEXT_KEY; /* we do not want this one */ - /* hack: ignore some keys, see BUGS */ - if (data->repodataid != data->repo->nrepodata - 1) - if (key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_LOCATION || key->name == REPOSITORY_KEYS || key->name == REPOSITORY_TOOLVERSION) - return SEARCH_NEXT_KEY; - - rm = cbdata->keymap[cbdata->keymapstart[data->repodataid] + (key - data->keys)]; + rm = cbdata->keymap[key - data->keys]; if (!rm) return SEARCH_NEXT_KEY; /* we do not want this one */ /* record key in schema */ - if ((key->type != REPOKEY_TYPE_FIXARRAY || kv->eof == 0) - && (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm)) + if (cbdata->sp[-1] != rm) *cbdata->sp++ = rm; switch(key->type) @@ -609,51 +565,20 @@ repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Rep case REPOKEY_TYPE_ID: case REPOKEY_TYPE_IDARRAY: id = kv->id; - if (!ISRELDEP(id) && cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &repo->pool->ss, id); - incneedid(repo->pool, id, cbdata->needid); + if (!ISRELDEP(id) && cbdata->ownspool && id > 1 && (!cbdata->clonepool || data->localpool)) + id = putinownpool(cbdata, data, id); + incneedid(id, cbdata->needid); break; case REPOKEY_TYPE_DIR: case REPOKEY_TYPE_DIRNUMNUMARRAY: case REPOKEY_TYPE_DIRSTRARRAY: id = kv->id; if (cbdata->owndirpool) - putinowndirpool(cbdata, data, &data->dirpool, id); + putinowndirpool(cbdata, data, id); else - setdirused(cbdata, &data->dirpool, id); + cbdata->dirused[id] = 1; break; case REPOKEY_TYPE_FIXARRAY: - if (kv->eof == 0) - { - if (cbdata->oldschema) - { - cbdata->target->error = pool_error(cbdata->repo->pool, -1, "nested fixarray structs not yet implemented"); - return SEARCH_NEXT_KEY; - } - cbdata->oldschema = cbdata->schema; - cbdata->oldsp = cbdata->sp; - cbdata->schema = solv_calloc(cbdata->target->nkeys, sizeof(Id)); - cbdata->sp = cbdata->schema; - } - else if (kv->eof == 1) - { - cbdata->current_sub++; - *cbdata->sp = 0; - cbdata->subschemata = solv_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - cbdata->subschemata[cbdata->nsubschemata++] = repodata_schema2id(cbdata->target, cbdata->schema, 1); -#if 0 - fprintf(stderr, "Have schema %d\n", cbdata->subschemata[cbdata->nsubschemata-1]); -#endif - cbdata->sp = cbdata->schema; - } - else - { - solv_free(cbdata->schema); - cbdata->schema = cbdata->oldschema; - cbdata->sp = cbdata->oldsp; - cbdata->oldsp = cbdata->oldschema = 0; - } - break; case REPOKEY_TYPE_FLEXARRAY: if (kv->entry == 0) { @@ -662,13 +587,16 @@ repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Rep } else { - /* just finished a schema, rewind */ + /* just finished a schema, rewind to start */ Id *sp = cbdata->sp - 1; *sp = 0; while (sp[-1]) sp--; - cbdata->subschemata = solv_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK); - cbdata->subschemata[cbdata->nsubschemata++] = repodata_schema2id(cbdata->target, sp, 1); + if (kv->entry == 1 || key->type == REPOKEY_TYPE_FLEXARRAY) + { + cbdata->subschemata = solv_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK); + cbdata->subschemata[cbdata->nsubschemata++] = repodata_schema2id(cbdata->target, sp, 1); + } cbdata->sp = kv->eof == 2 ? sp - 1: sp; } break; @@ -678,17 +606,82 @@ repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Rep return 0; } -static int -repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +static void +collect_needed_solvable(struct cbdata *cbdata, Solvable *s, Id *keymap) { - struct cbdata *cbdata = vcbdata; - Repo *repo = data->repo; - -#if 0 - if (s) - fprintf(stderr, "solvable %d (%s): key (%d)%s %d\n", s ? s - repo->pool->solvables : 0, s ? pool_id2str(repo->pool, s->name) : "", key->name, pool_id2str(repo->pool, key->name), key->type); -#endif - return repo_write_collect_needed(cbdata, repo, data, key, kv); + /* set schema info, keep in sync with collect_data_solvable */ + Repo *repo = s->repo; + Id *sp = cbdata->sp; + NeedId *needid = cbdata->needid; + Repodata *target = cbdata->target; + Id *idarraydata = repo->idarraydata; + + if (keymap[SOLVABLE_NAME]) + { + *sp++ = keymap[SOLVABLE_NAME]; + needid[s->name].need++; + } + if (keymap[SOLVABLE_ARCH]) + { + *sp++ = keymap[SOLVABLE_ARCH]; + needid[s->arch].need++; + } + if (keymap[SOLVABLE_EVR]) + { + *sp++ = keymap[SOLVABLE_EVR]; + needid[s->evr].need++; + } + if (s->vendor && keymap[SOLVABLE_VENDOR]) + { + *sp++ = keymap[SOLVABLE_VENDOR]; + needid[s->vendor].need++; + } + if (s->provides && keymap[SOLVABLE_PROVIDES]) + { + *sp++ = keymap[SOLVABLE_PROVIDES]; + target->keys[keymap[SOLVABLE_PROVIDES]].size += incneedidarray(idarraydata + s->provides, needid); + } + if (s->obsoletes && keymap[SOLVABLE_OBSOLETES]) + { + *sp++ = keymap[SOLVABLE_OBSOLETES]; + target->keys[keymap[SOLVABLE_OBSOLETES]].size += incneedidarray(idarraydata + s->obsoletes, needid); + } + if (s->conflicts && keymap[SOLVABLE_CONFLICTS]) + { + *sp++ = keymap[SOLVABLE_CONFLICTS]; + target->keys[keymap[SOLVABLE_CONFLICTS]].size += incneedidarray(idarraydata + s->conflicts, needid); + } + if (s->requires && keymap[SOLVABLE_REQUIRES]) + { + *sp++ = keymap[SOLVABLE_REQUIRES]; + target->keys[keymap[SOLVABLE_REQUIRES]].size += incneedidarray(idarraydata + s->requires, needid); + } + if (s->recommends && keymap[SOLVABLE_RECOMMENDS]) + { + *sp++ = keymap[SOLVABLE_RECOMMENDS]; + target->keys[keymap[SOLVABLE_RECOMMENDS]].size += incneedidarray(idarraydata + s->recommends, needid); + } + if (s->suggests && keymap[SOLVABLE_SUGGESTS]) + { + *sp++ = keymap[SOLVABLE_SUGGESTS]; + target->keys[keymap[SOLVABLE_SUGGESTS]].size += incneedidarray(idarraydata + s->suggests, needid); + } + if (s->supplements && keymap[SOLVABLE_SUPPLEMENTS]) + { + *sp++ = keymap[SOLVABLE_SUPPLEMENTS]; + target->keys[keymap[SOLVABLE_SUPPLEMENTS]].size += incneedidarray(idarraydata + s->supplements, needid); + } + if (s->enhances && keymap[SOLVABLE_ENHANCES]) + { + *sp++ = keymap[SOLVABLE_ENHANCES]; + target->keys[keymap[SOLVABLE_ENHANCES]].size += incneedidarray(idarraydata + s->enhances, needid); + } + if (repo->rpmdbid && keymap[RPM_RPMDBID]) + { + *sp++ = keymap[RPM_RPMDBID]; + target->keys[keymap[RPM_RPMDBID]].size++; + } + cbdata->sp = sp; } @@ -696,57 +689,51 @@ repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, K * pass 2 callback: * encode all of the data into the correct buffers */ - static int -repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue *kv) +collect_data_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) { + struct cbdata *cbdata = vcbdata; int rm; - Id id; - unsigned int u32; - unsigned char v[4]; + Id id, storage; struct extdata *xd; NeedId *needid; if (key->name == REPOSITORY_SOLVABLES) return SEARCH_NEXT_KEY; - /* hack: ignore some keys, see BUGS */ - if (data->repodataid != data->repo->nrepodata - 1) - if (key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_LOCATION || key->name == REPOSITORY_KEYS || key->name == REPOSITORY_TOOLVERSION) - return SEARCH_NEXT_KEY; - - rm = cbdata->keymap[cbdata->keymapstart[data->repodataid] + (key - data->keys)]; + rm = cbdata->keymap[key - data->keys]; if (!rm) return SEARCH_NEXT_KEY; /* we do not want this one */ + storage = cbdata->target->keys[rm].storage; - if (cbdata->target->keys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET) + xd = cbdata->extdata + 0; /* incore buffer */ + if (storage == KEY_STORAGE_VERTICAL_OFFSET) { - xd = cbdata->extdata + rm; /* vertical buffer */ + xd += rm; /* vertical buffer */ if (cbdata->vstart == -1) cbdata->vstart = xd->len; } - else - xd = cbdata->extdata + 0; /* incore buffer */ switch(key->type) { + case REPOKEY_TYPE_DELETED: case REPOKEY_TYPE_VOID: case REPOKEY_TYPE_CONSTANT: case REPOKEY_TYPE_CONSTANTID: break; case REPOKEY_TYPE_ID: id = kv->id; - if (!ISRELDEP(id) && cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); - needid = cbdata->needid; - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + if (!ISRELDEP(id) && cbdata->ownspool && id > 1 && (!cbdata->clonepool || data->localpool)) + id = putinownpool(cbdata, data, id); + needid = cbdata->needid; + id = needid[NEEDIDOFF(id)].need; data_addid(xd, id); break; case REPOKEY_TYPE_IDARRAY: id = kv->id; - if (!ISRELDEP(id) && cbdata->ownspool && id > 1) - id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); - needid = cbdata->needid; - id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + if (!ISRELDEP(id) && cbdata->ownspool && id > 1 && (!cbdata->clonepool || data->localpool)) + id = putinownpool(cbdata, data, id); + needid = cbdata->needid; + id = needid[NEEDIDOFF(id)].need; data_addideof(xd, id, kv->eof); break; case REPOKEY_TYPE_STR: @@ -770,13 +757,6 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue case REPOKEY_TYPE_SHA512: data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA512); break; - case REPOKEY_TYPE_U32: - u32 = kv->num; - v[0] = u32 >> 24; - v[1] = u32 >> 16; - v[2] = u32 >> 8; - v[3] = u32; - data_addblob(xd, v, 4); break; case REPOKEY_TYPE_NUM: data_addid64(xd, kv->num, kv->num2); @@ -784,7 +764,7 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue case REPOKEY_TYPE_DIR: id = kv->id; if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); + id = putinowndirpool(cbdata, data, id); id = cbdata->dirused[id]; data_addid(xd, id); break; @@ -796,7 +776,7 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue case REPOKEY_TYPE_DIRNUMNUMARRAY: id = kv->id; if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); + id = putinowndirpool(cbdata, data, id); id = cbdata->dirused[id]; data_addid(xd, id); data_addid(xd, kv->num); @@ -805,39 +785,22 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue case REPOKEY_TYPE_DIRSTRARRAY: id = kv->id; if (cbdata->owndirpool) - id = putinowndirpool(cbdata, data, &data->dirpool, id); + id = putinowndirpool(cbdata, data, id); id = cbdata->dirused[id]; - if (cbdata->filelistmode > 0) + if (rm == cbdata->filelistmode) { + /* postpone adding to xd, just update len to get the correct offsets into the incore data*/ xd->len += data_addideof_len(id) + strlen(kv->str) + 1; break; } data_addideof(xd, id, kv->eof); data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1); - if (cbdata->filelistmode < 0) - return 0; break; case REPOKEY_TYPE_FIXARRAY: - if (kv->eof == 0) - { - if (kv->num) - { - data_addid(xd, kv->num); - data_addid(xd, cbdata->subschemata[cbdata->current_sub]); -#if 0 - fprintf(stderr, "writing %d %d\n", kv->num, cbdata->subschemata[cbdata->current_sub]); -#endif - } - } - else if (kv->eof == 1) - { - cbdata->current_sub++; - } - break; case REPOKEY_TYPE_FLEXARRAY: if (!kv->entry) data_addid(xd, kv->num); - if (kv->eof != 2) + if (kv->eof != 2 && (!kv->entry || key->type == REPOKEY_TYPE_FLEXARRAY)) data_addid(xd, cbdata->subschemata[cbdata->current_sub++]); if (xd == cbdata->extdata + 0 && !kv->parent && !cbdata->doingsolvables) { @@ -847,10 +810,10 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue } break; default: - cbdata->target->error = pool_error(cbdata->repo->pool, -1, "unknown type for %d: %d\n", key->name, key->type); + cbdata->target->error = pool_error(cbdata->pool, -1, "unknown type for %d: %d\n", key->name, key->type); break; } - if (cbdata->target->keys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET && kv->eof) + if (storage == KEY_STORAGE_VERTICAL_OFFSET && kv->eof) { /* we can re-use old data in the blob here! */ data_addid(cbdata->extdata + 0, cbdata->vstart); /* add offset into incore data */ @@ -860,11 +823,63 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue return 0; } +/* special version of collect_data_cb that collects just one single REPOKEY_TYPE_DIRSTRARRAY vertical data */ static int -repo_write_cb_adddata(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +collect_filelist_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) { struct cbdata *cbdata = vcbdata; - return repo_write_adddata(cbdata, data, key, kv); + int rm; + Id id; + struct extdata *xd; + + rm = cbdata->keymap[key - data->keys]; + if (rm != cbdata->filelistmode) + return SEARCH_NEXT_KEY; /* we do not want this one */ + id = kv->id; + if (cbdata->owndirpool) + id = putinowndirpool(cbdata, data, id); + id = cbdata->dirused[id]; + xd = cbdata->extdata + rm; /* vertical buffer */ + data_addideof(xd, id, kv->eof); + data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1); + return 0; +} + +static void +collect_data_solvable(struct cbdata *cbdata, Solvable *s, Id *keymap) +{ + Repo *repo = s->repo; + Pool *pool = repo->pool; + struct extdata *xd = cbdata->extdata; + NeedId *needid = cbdata->needid; + Id *idarraydata = repo->idarraydata; + + if (keymap[SOLVABLE_NAME]) + data_addid(xd, needid[s->name].need); + if (keymap[SOLVABLE_ARCH]) + data_addid(xd, needid[s->arch].need); + if (keymap[SOLVABLE_EVR]) + data_addid(xd, needid[s->evr].need); + if (s->vendor && keymap[SOLVABLE_VENDOR]) + data_addid(xd, needid[s->vendor].need); + if (s->provides && keymap[SOLVABLE_PROVIDES]) + data_adddepids(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); + if (s->obsoletes && keymap[SOLVABLE_OBSOLETES]) + data_adddepids(xd, pool, needid, idarraydata + s->obsoletes, 0); + if (s->conflicts && keymap[SOLVABLE_CONFLICTS]) + data_adddepids(xd, pool, needid, idarraydata + s->conflicts, 0); + if (s->requires && keymap[SOLVABLE_REQUIRES]) + data_adddepids(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); + if (s->recommends && keymap[SOLVABLE_RECOMMENDS]) + data_adddepids(xd, pool, needid, idarraydata + s->recommends, 0); + if (s->suggests && keymap[SOLVABLE_SUGGESTS]) + data_adddepids(xd, pool, needid, idarraydata + s->suggests, 0); + if (s->supplements && keymap[SOLVABLE_SUPPLEMENTS]) + data_adddepids(xd, pool, needid, idarraydata + s->supplements, 0); + if (s->enhances && keymap[SOLVABLE_ENHANCES]) + data_adddepids(xd, pool, needid, idarraydata + s->enhances, 0); + if (repo->rpmdbid && keymap[RPM_RPMDBID]) + data_addid(xd, repo->rpmdbid[(s - pool->solvables) - repo->start]); } /* traverse through directory with first child "dir" */ @@ -972,24 +987,6 @@ repo_write_stdkeyfilter(Repo *repo, Repokey *key, void *kfdata) return KEY_STORAGE_INCORE; } -/* - * return true if the repodata contains the filelist (and just - * the filelist). The same code is used in the dataiterator. The way - * it is used is completely wrong, of course, as having the filelist - * key does not mean it is used for a specific solvable. Nevertheless - * it is better to have it than to write broken solv files. - */ -static inline int -is_filelist_extension(Repodata *data) -{ - int j; - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - return 0; - return 1; -} - - static int write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vpage, int lpage) { @@ -1013,10 +1010,109 @@ write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vp return lpage; } + +static Id * +create_keyskip(Repo *repo, Id entry, unsigned char *repodataused, Id **oldkeyskip) +{ + Repodata *data, *last = 0; + Id *keyskip; + int rdid, cnt = 0; + + if (repo->nrepodata <= 2) + return 0; + keyskip = *oldkeyskip; + if (keyskip) + { + if (keyskip[1] >= 0x10000000) + keyskip = solv_free(keyskip); + else + keyskip[1] = keyskip[2]; + } + FOR_REPODATAS(repo, rdid, data) + { + if (!repodataused[rdid]) + continue; + if (entry != SOLVID_META) + { + if (entry < data->start || entry >= data->end) + continue; + /* if repodataused is set we know that the state is AVAILABLE */ + if (!data->incoreoffset[entry - data->start]) + continue; + } + if (last) + keyskip = repodata_fill_keyskip(last, entry, keyskip); + last = data; + cnt++; + } + if (cnt <= 1) /* just one repodata means we don't need a keyskip */ + { + *oldkeyskip = keyskip; + return 0; + } + keyskip = repodata_fill_keyskip(last, entry, keyskip); + if (keyskip) + keyskip[2] = keyskip[1] + repo->nrepodata; + *oldkeyskip = keyskip; + return keyskip; +} + /* * Repo */ +Repowriter * +repowriter_create(Repo *repo) +{ + Repowriter *writer = solv_calloc(1, sizeof(*writer)); + writer->repo = repo; + writer->keyfilter = repo_write_stdkeyfilter; + writer->repodatastart = 1; + writer->repodataend = repo->nrepodata; + writer->solvablestart = repo->start; + writer->solvableend = repo->end; + return writer; +} + +Repowriter * +repowriter_free(Repowriter *writer) +{ + return solv_free(writer); +} + +void +repowriter_set_flags(Repowriter *writer, int flags) +{ + writer->flags = flags; +} + +void +repowriter_set_keyfilter(Repowriter *writer, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata) +{ + writer->keyfilter = keyfilter; + writer->kfdata = kfdata; +} + +void +repowriter_set_keyqueue(Repowriter *writer, Queue *keyq) +{ + writer->keyq = keyq; +} + +void +repowriter_set_repodatarange(Repowriter *writer, int repodatastart, int repodataend) +{ + writer->repodatastart = repodatastart; + writer->repodataend = repodataend; +} + +void +repowriter_set_solvablerange(Repowriter *writer, int solvablestart, int solvableend) +{ + writer->solvablestart = solvablestart; + writer->solvableend = solvableend; +} + /* * the code works the following way: * @@ -1029,31 +1125,43 @@ write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vp * 5) write everything to disk */ int -repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq) +repowriter_write(Repowriter *writer, FILE *fp) { + Repo *repo = writer->repo; Pool *pool = repo->pool; - int i, j, n, lastfilelistn; + int i, j, n; Solvable *s; - NeedId *needid; + NeedId *needid, *needidp; int nstrings, nrels; unsigned int sizeid; unsigned int solv_flags; - Reldep *ran; - Id *idarraydata; + Id *oldkeyskip = 0; + Id *keyskip = 0; + int searchflags = 0; Id id, *sp; + Id *keymap; /* maps repo key to my key, 0 -> not used */ + int nkeymap; + int *keymapstart; /* maps repo number to keymap offset */ + Id *dirmap; int ndirmap; Id *keyused; + unsigned char *repodataused; int anyrepodataused = 0; + + int solvablestart, solvableend; + Id *solvschemata; int anysolvableused = 0; + int nsolvables; struct cbdata cbdata; + int clonepool; Repokey *key; - int poolusage, dirpoolusage, idused, dirused; + int poolusage, dirpoolusage; int reloff; Repodata *data, *dirpooldata; @@ -1063,14 +1171,15 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * Stringpool *spool; Dirpool *dirpool; - Id mainschema; + Id mainschema, *mainschemakeys; struct extdata *xd; - Id type_constantid = REPOKEY_TYPE_CONSTANTID; + Id type_constantid = 0; memset(&cbdata, 0, sizeof(cbdata)); + cbdata.pool = pool; cbdata.repo = repo; cbdata.target = ⌖ @@ -1078,48 +1187,50 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * /* go through all repodata and find the keys we need */ /* also unify keys */ - /* keymapstart - maps repo number to keymap offset */ - /* keymap - maps repo key to my key, 0 -> not used */ /* start with all KEY_STORAGE_SOLVABLE ids */ n = ID_NUM_INTERNAL; FOR_REPODATAS(repo, i, data) n += data->nkeys; - cbdata.keymap = solv_calloc(n, sizeof(Id)); - cbdata.keymapstart = solv_calloc(repo->nrepodata, sizeof(Id)); + nkeymap = n; + keymap = solv_calloc(nkeymap, sizeof(Id)); + keymapstart = solv_calloc(repo->nrepodata, sizeof(Id)); repodataused = solv_calloc(repo->nrepodata, 1); clonepool = 0; poolusage = 0; - /* add keys for STORAGE_SOLVABLE */ - for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++) + if (!(writer->flags & REPOWRITER_NO_STORAGE_SOLVABLE)) { - Repokey keyd; - keyd.name = i; - if (i < SOLVABLE_PROVIDES) - keyd.type = REPOKEY_TYPE_ID; - else if (i < RPM_RPMDBID) + /* add keys for STORAGE_SOLVABLE */ + for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++) + { + Repokey keyd; + keyd.name = i; + if (i < SOLVABLE_PROVIDES) + keyd.type = REPOKEY_TYPE_ID; + else if (i < RPM_RPMDBID) #ifdef USE_REL_IDARRAY - keyd.type = REPOKEY_TYPE_REL_IDARRAY; + keyd.type = REPOKEY_TYPE_REL_IDARRAY; #else - keyd.type = REPOKEY_TYPE_IDARRAY; + keyd.type = REPOKEY_TYPE_IDARRAY; #endif - else - keyd.type = REPOKEY_TYPE_NUM; - keyd.size = 0; - keyd.storage = KEY_STORAGE_SOLVABLE; - if (keyfilter) - { - keyd.storage = keyfilter(repo, &keyd, kfdata); - if (keyd.storage == KEY_STORAGE_DROPPED) - continue; + else + keyd.type = REPOKEY_TYPE_NUM; + keyd.size = 0; keyd.storage = KEY_STORAGE_SOLVABLE; + if (writer->keyfilter) + { + keyd.storage = writer->keyfilter(repo, &keyd, writer->kfdata); + if (keyd.storage == KEY_STORAGE_DROPPED) + continue; + keyd.storage = KEY_STORAGE_SOLVABLE; + } + poolusage = 1; + clonepool = 1; + keymap[keyd.name] = repodata_key2id(&target, &keyd, 1); } - poolusage = 1; - clonepool = 1; - cbdata.keymap[keyd.name] = repodata_key2id(&target, &keyd, 1); } if (repo->nsolvables) @@ -1129,7 +1240,7 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * keyd.type = REPOKEY_TYPE_FLEXARRAY; keyd.size = 0; keyd.storage = KEY_STORAGE_INCORE; - cbdata.keymap[keyd.name] = repodata_key2id(&target, &keyd, 1); + keymap[keyd.name] = repodata_key2id(&target, &keyd, 1); } dirpoolusage = 0; @@ -1138,35 +1249,37 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * dirpool = 0; dirpooldata = 0; n = ID_NUM_INTERNAL; - lastfilelistn = 0; FOR_REPODATAS(repo, i, data) { - cbdata.keymapstart[i] = n; - cbdata.keymap[n++] = 0; /* key 0 */ - idused = 0; - dirused = 0; - if (keyfilter) + int idused, dirused; + if (i < writer->repodatastart || i >= writer->repodataend) + continue; + if (writer->keyfilter && (writer->flags & REPOWRITER_LEGACY) != 0) { + /* ask keyfilter if we want this repodata */ Repokey keyd; /* check if we want this repodata */ memset(&keyd, 0, sizeof(keyd)); keyd.name = 1; keyd.type = 1; keyd.size = i; - if (keyfilter(repo, &keyd, kfdata) == -1) + if (writer->keyfilter(repo, &keyd, writer->kfdata) == -1) continue; } + keymapstart[i] = n; + keymap[n++] = 0; /* key 0 */ + idused = dirused = 0; for (j = 1; j < data->nkeys; j++, n++) { key = data->keys + j; if (key->name == REPOSITORY_SOLVABLES && key->type == REPOKEY_TYPE_FLEXARRAY) { - cbdata.keymap[n] = cbdata.keymap[key->name]; + keymap[n] = keymap[key->name]; continue; } - if (key->type == REPOKEY_TYPE_DELETED) + if (key->type == REPOKEY_TYPE_DELETED && (writer->flags & REPOWRITER_KEEP_TYPE_DELETED) == 0) { - cbdata.keymap[n] = 0; + keymap[n] = 0; continue; } if (key->type == REPOKEY_TYPE_CONSTANTID && data->localpool) @@ -1179,43 +1292,48 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * id = repodata_key2id(&target, key, 0); if (!id) { + /* a new key. ask keyfilter if we want it before creating it */ Repokey keyd = *key; keyd.storage = KEY_STORAGE_INCORE; if (keyd.type == REPOKEY_TYPE_CONSTANTID) keyd.size = repodata_globalize_id(data, key->size, 1); else if (keyd.type != REPOKEY_TYPE_CONSTANT) keyd.size = 0; - if (keyfilter) + if (writer->keyfilter) { - keyd.storage = keyfilter(repo, &keyd, kfdata); + keyd.storage = writer->keyfilter(repo, &keyd, writer->kfdata); if (keyd.storage == KEY_STORAGE_DROPPED) { - cbdata.keymap[n] = 0; + keymap[n] = 0; continue; } } - id = repodata_key2id(&target, &keyd, 1); + if (data->state != REPODATA_STUB) + id = repodata_key2id(&target, &keyd, 1); } - cbdata.keymap[n] = id; + keymap[n] = id; /* load repodata if not already loaded */ if (data->state == REPODATA_STUB) { - if (data->loadcallback) - data->loadcallback(data); - else - data->state = REPODATA_ERROR; - if (data->state != REPODATA_ERROR) + int oldnkeys = data->nkeys; + repodata_load(data); + if (oldnkeys != data->nkeys) + { + nkeymap += data->nkeys - oldnkeys; /* grow/shrink keymap */ + keymap = solv_realloc2(keymap, nkeymap, sizeof(Id)); + } + if (data->state == REPODATA_AVAILABLE) { /* redo this repodata! */ j = 0; - n = cbdata.keymapstart[i]; + n = keymapstart[i]; continue; } } - if (data->state == REPODATA_ERROR) + if (data->state != REPODATA_AVAILABLE && data->state != REPODATA_LOADING) { /* too bad! */ - cbdata.keymap[n] = 0; + keymap[n] = 0; continue; } @@ -1229,20 +1347,6 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * idused = 1; /* dirs also use ids */ dirused = 1; } - if (key->type == REPOKEY_TYPE_DIRSTRARRAY && key->name == SOLVABLE_FILELIST) - { - /* is this a file list extension */ - if (is_filelist_extension(data)) - { - /* hmm, we have a file list extension. Kill filelist of other repodata. - * XXX: this is wrong, as the extension does not need to cover all - * solvables of the other repodata */ - if (lastfilelistn) - cbdata.keymap[lastfilelistn] = 0; - } - else - lastfilelistn = n; - } } if (idused) { @@ -1276,20 +1380,24 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * } } } - cbdata.nkeymap = n; + nkeymap = n; /* update */ /* 0: no pool needed at all */ /* 1: use global pool */ /* 2: use repodata local pool */ /* 3: need own pool */ + if (poolusage != 3) + clonepool = 0; if (poolusage == 3) { spool = &target.spool; + target.localpool = 1; /* so we can use repodata_translate */ /* hack: reuse global pool data so we don't have to map pool ids */ if (clonepool) { stringpool_free(spool); stringpool_clone(spool, &pool->ss); + cbdata.clonepool = 1; } cbdata.ownspool = spool; } @@ -1301,6 +1409,10 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * if (dirpoolusage == 3) { + /* dirpoolusage == 3 means that at least two repodata + * areas have dir keys. This means that two areas have + * idused set to 1, which results in poolusage being + * either 1 (global pool) or 3 (own pool) */ dirpool = &target.dirpool; dirpooldata = 0; cbdata.owndirpool = dirpool; @@ -1313,196 +1425,110 @@ repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey * #if 0 fprintf(stderr, "poolusage: %d\n", poolusage); fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage); +fprintf(stderr, "clonepool: %d\n", clonepool); fprintf(stderr, "nkeys: %d\n", target.nkeys); for (i = 1; i < target.nkeys; i++) fprintf(stderr, " %2d: %s[%d] %d %d %d\n", i, pool_id2str(pool, target.keys[i].name), target.keys[i].name, target.keys[i].type, target.keys[i].size, target.keys[i].storage); #endif - /* copy keys if requested */ - if (keyq) - { - queue_empty(keyq); - for (i = 1; i < target.nkeys; i++) - queue_push2(keyq, target.keys[i].name, target.keys[i].type); - } - - if (poolusage > 1) - { - /* put all the keys we need in our string pool */ - /* put mapped ids right into target.keys */ - for (i = 1, key = target.keys + i; i < target.nkeys; i++, key++) - { - key->name = stringpool_str2id(spool, pool_id2str(pool, key->name), 1); - if (key->type == REPOKEY_TYPE_CONSTANTID) - { - key->type = stringpool_str2id(spool, pool_id2str(pool, key->type), 1); - type_constantid = key->type; - key->size = stringpool_str2id(spool, pool_id2str(pool, key->size), 1); - } - else - key->type = stringpool_str2id(spool, pool_id2str(pool, key->type), 1); - } - if (poolusage == 2) - stringpool_freehash(spool); /* free some mem */ - } - - /********************************************************************/ + searchflags = SEARCH_SUB|SEARCH_ARRAYSENTINEL; + if ((writer->flags & REPOWRITER_KEEP_TYPE_DELETED) != 0) + searchflags |= SEARCH_KEEP_TYPE_DELETED; + /* set needed count of all strings and rels, * find which keys are used in the solvables * put all strings in own spool */ reloff = spool->nstrings; - if (poolusage == 3) - reloff = (reloff + NEEDED_BLOCK) & ~NEEDED_BLOCK; + if (cbdata.ownspool) + reloff = (reloff + NEEDID_BLOCK) & ~NEEDID_BLOCK; + else if (poolusage == 2) + { + /* we'll need to put the key data into the spool, + * so leave some room. 3 * nkeys is an upper bound */ + reloff += 3 * target.nkeys; + } needid = calloc(reloff + pool->nrels, sizeof(*needid)); - needid[0].map = reloff; + needid[0].map = reloff; /* remember size in case we need to grow */ cbdata.needid = needid; - cbdata.schema = solv_calloc(target.nkeys, sizeof(Id)); - cbdata.sp = cbdata.schema; - cbdata.solvschemata = solv_calloc(repo->nsolvables, sizeof(Id)); + cbdata.schema = solv_calloc(target.nkeys + 2, sizeof(Id)); /* create main schema */ - cbdata.sp = cbdata.schema; - /* collect all other data from all repodatas */ + cbdata.sp = cbdata.schema + 1; + + /* collect meta data from all repodatas */ /* XXX: merge arrays of equal keys? */ + keyskip = create_keyskip(repo, SOLVID_META, repodataused, &oldkeyskip); FOR_REPODATAS(repo, j, data) { if (!repodataused[j]) continue; - repodata_search(data, SOLVID_META, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_needed, &cbdata); + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; /* clear dir mapping cache */ + repodata_search_keyskip(data, SOLVID_META, 0, searchflags, keyskip, collect_needed_cb, &cbdata); } + needid = cbdata.needid; /* maybe relocated */ sp = cbdata.sp; /* add solvables if needed (may revert later) */ if (repo->nsolvables) { - *sp++ = cbdata.keymap[REPOSITORY_SOLVABLES]; - target.keys[cbdata.keymap[REPOSITORY_SOLVABLES]].size++; + *sp++ = keymap[REPOSITORY_SOLVABLES]; + target.keys[keymap[REPOSITORY_SOLVABLES]].size++; } *sp = 0; - mainschema = repodata_schema2id(cbdata.target, cbdata.schema, 1); - - idarraydata = repo->idarraydata; + /* stash away main schema (including terminating zero) */ + mainschemakeys = solv_memdup2(cbdata.schema + 1, sp - cbdata.schema, sizeof(Id)); + /* collect data for all solvables */ + solvschemata = solv_calloc(repo->nsolvables, sizeof(Id)); /* allocate upper bound */ + solvablestart = writer->solvablestart < repo->start ? repo->start : writer->solvablestart; + solvableend = writer->solvableend > repo->end ? repo->end : writer->solvableend; anysolvableused = 0; + nsolvables = 0; /* solvables we are going to write, will be <= repo->nsolvables */ cbdata.doingsolvables = 1; - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) + for (i = solvablestart, s = pool->solvables + i; i < solvableend; i++, s++) { if (s->repo != repo) continue; - /* set schema info, keep in sync with further down */ - sp = cbdata.schema; - if (cbdata.keymap[SOLVABLE_NAME]) - { - *sp++ = cbdata.keymap[SOLVABLE_NAME]; - needid[s->name].need++; - } - if (cbdata.keymap[SOLVABLE_ARCH]) - { - *sp++ = cbdata.keymap[SOLVABLE_ARCH]; - needid[s->arch].need++; - } - if (cbdata.keymap[SOLVABLE_EVR]) - { - *sp++ = cbdata.keymap[SOLVABLE_EVR]; - needid[s->evr].need++; - } - if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) - { - *sp++ = cbdata.keymap[SOLVABLE_VENDOR]; - needid[s->vendor].need++; - } - if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - { - *sp++ = cbdata.keymap[SOLVABLE_PROVIDES]; - target.keys[cbdata.keymap[SOLVABLE_PROVIDES]].size += incneedidarray(pool, idarraydata + s->provides, needid); - } - if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - { - *sp++ = cbdata.keymap[SOLVABLE_OBSOLETES]; - target.keys[cbdata.keymap[SOLVABLE_OBSOLETES]].size += incneedidarray(pool, idarraydata + s->obsoletes, needid); - } - if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - { - *sp++ = cbdata.keymap[SOLVABLE_CONFLICTS]; - target.keys[cbdata.keymap[SOLVABLE_CONFLICTS]].size += incneedidarray(pool, idarraydata + s->conflicts, needid); - } - if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - { - *sp++ = cbdata.keymap[SOLVABLE_REQUIRES]; - target.keys[cbdata.keymap[SOLVABLE_REQUIRES]].size += incneedidarray(pool, idarraydata + s->requires, needid); - } - if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - { - *sp++ = cbdata.keymap[SOLVABLE_RECOMMENDS]; - target.keys[cbdata.keymap[SOLVABLE_RECOMMENDS]].size += incneedidarray(pool, idarraydata + s->recommends, needid); - } - if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - { - *sp++ = cbdata.keymap[SOLVABLE_SUGGESTS]; - target.keys[cbdata.keymap[SOLVABLE_SUGGESTS]].size += incneedidarray(pool, idarraydata + s->suggests, needid); - } - if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - { - *sp++ = cbdata.keymap[SOLVABLE_SUPPLEMENTS]; - target.keys[cbdata.keymap[SOLVABLE_SUPPLEMENTS]].size += incneedidarray(pool, idarraydata + s->supplements, needid); - } - if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - { - *sp++ = cbdata.keymap[SOLVABLE_ENHANCES]; - target.keys[cbdata.keymap[SOLVABLE_ENHANCES]].size += incneedidarray(pool, idarraydata + s->enhances, needid); - } - if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) - { - *sp++ = cbdata.keymap[RPM_RPMDBID]; - target.keys[cbdata.keymap[RPM_RPMDBID]].size++; - } - cbdata.sp = sp; + cbdata.sp = cbdata.schema + 1; + collect_needed_solvable(&cbdata, s, keymap); if (anyrepodataused) { + keyskip = create_keyskip(repo, i, repodataused, &oldkeyskip); FOR_REPODATAS(repo, j, data) { - if (!repodataused[j]) - continue; - if (i < data->start || i >= data->end) + if (!repodataused[j] || i < data->start || i >= data->end) continue; - repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_needed, &cbdata); - needid = cbdata.needid; + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; + repodata_search_keyskip(data, i, 0, searchflags, keyskip, collect_needed_cb, &cbdata); } + needid = cbdata.needid; /* maybe relocated */ } *cbdata.sp = 0; - cbdata.solvschemata[n] = repodata_schema2id(cbdata.target, cbdata.schema, 1); - if (cbdata.solvschemata[n]) + solvschemata[nsolvables] = repodata_schema2id(cbdata.target, cbdata.schema + 1, 1); + if (solvschemata[nsolvables]) anysolvableused = 1; - n++; + nsolvables++; } cbdata.doingsolvables = 0; - assert(n == repo->nsolvables); if (repo->nsolvables && !anysolvableused) { - /* strip off solvable from the main schema */ - target.keys[cbdata.keymap[REPOSITORY_SOLVABLES]].size = 0; - sp = cbdata.schema; - for (i = 0; target.schemadata[target.schemata[mainschema] + i]; i++) - { - *sp = target.schemadata[target.schemata[mainschema] + i]; - if (*sp != cbdata.keymap[REPOSITORY_SOLVABLES]) - sp++; - } - assert(target.schemadatalen == target.schemata[mainschema] + i + 1); - *sp = 0; - target.schemadatalen = target.schemata[mainschema]; - target.nschemata--; - repodata_free_schemahash(&target); - mainschema = repodata_schema2id(cbdata.target, cbdata.schema, 1); + /* strip off REPOSITORY_SOLVABLES from the main schema */ + for (sp = mainschemakeys; *sp; sp++) + ; + sp[-1] = 0; /* strip last entry */ } + mainschema = repodata_schema2id(cbdata.target, mainschemakeys, 1); + mainschemakeys = solv_free(mainschemakeys); /********************************************************************/ @@ -1515,32 +1541,78 @@ for (i = 1; i < target.nkeys; i++) { if (!keyused[i]) continue; - keyused[i] = n; if (i != n) - { - target.keys[n] = target.keys[i]; - if (keyq) - { - keyq->elements[2 * n - 2] = keyq->elements[2 * i - 2]; - keyq->elements[2 * n - 1] = keyq->elements[2 * i - 1]; - } - } - n++; + target.keys[n] = target.keys[i]; + keyused[i] = n++; } target.nkeys = n; - if (keyq) - queue_truncate(keyq, 2 * n - 2); /* update schema data to the new key ids */ for (i = 1; i < (int)target.schemadatalen; i++) target.schemadata[i] = keyused[target.schemadata[i]]; /* update keymap to the new key ids */ - for (i = 0; i < cbdata.nkeymap; i++) - cbdata.keymap[i] = keyused[cbdata.keymap[i]]; + for (i = 0; i < nkeymap; i++) + keymap[i] = keyused[keymap[i]]; keyused = solv_free(keyused); - /* increment needid of the used keys, they are already mapped to - * the correct string pool */ + /* copy keys if requested */ + if (writer->keyq) + { + queue_empty(writer->keyq); + for (i = 1; i < target.nkeys; i++) + queue_push2(writer->keyq, target.keys[i].name, target.keys[i].type); + } + +/********************************************************************/ + + /* check if we can do the special filelist memory optimization + * we do the check before the keys are mapped. + * The optimization is done if there is just one vertical key and + * it is of type REPOKEY_TYPE_DIRSTRARRAY */ + if (anysolvableused && anyrepodataused) + { + for (i = 1; i < target.nkeys; i++) + { + if (target.keys[i].storage != KEY_STORAGE_VERTICAL_OFFSET) + continue; + if (target.keys[i].type != REPOKEY_TYPE_DIRSTRARRAY || cbdata.filelistmode != 0) + { + cbdata.filelistmode = 0; + break; + } + cbdata.filelistmode = i; + } + } + +/********************************************************************/ + + if (poolusage > 1) + { + /* put all the keys in our string pool */ + /* put mapped ids right into target.keys */ + for (i = 1, key = target.keys + i; i < target.nkeys; i++, key++) + { + key->name = stringpool_str2id(spool, pool_id2str(pool, key->name), 1); + id = stringpool_str2id(spool, pool_id2str(pool, key->type), 1); + if (key->type == REPOKEY_TYPE_CONSTANTID) + { + type_constantid = id; + key->size = stringpool_str2id(spool, pool_id2str(pool, key->size), 1); + } + key->type = id; + } + if (poolusage == 2) + stringpool_freehash(spool); /* free some mem */ + if (cbdata.ownspool && spool->nstrings > needid[0].map) + { + grow_needid(&cbdata, spool->nstrings - 1); + needid = cbdata.needid; /* we relocated */ + } + } + else + type_constantid = REPOKEY_TYPE_CONSTANTID; + + /* increment needid of the keys */ for (i = 1; i < target.nkeys; i++) { if (target.keys[i].type == type_constantid) @@ -1551,41 +1623,116 @@ for (i = 1; i < target.nkeys; i++) /********************************************************************/ - if (dirpool && cbdata.dirused && !cbdata.dirused[0]) + /* increment need id of all relations + * if we refer to another relation, make sure that the + * need value is it is bigger than our value so that + * ordering works. + */ + reloff = needid[0].map; + for (i = pool->nrels - 1, needidp = needid + (reloff + i); i > 0; i--, needidp--) + if (needidp->need) + break; + if (i) { - /* no dirs used at all */ - cbdata.dirused = solv_free(cbdata.dirused); - dirpool = 0; - } + /* we have some relations with a non-zero need */ + Reldep *rd; + + for (rd = pool->rels + i; i > 1; i--, rd--) + { + int need = needid[reloff + i].need; + if (!need) + continue; + id = rd->name; + if (ISRELDEP(id)) + { + id = GETRELID(id); + if (needid[reloff + id].need < need + 1) + needid[reloff + id].need = need + 1; + } + else + { + if (cbdata.ownspool && id > 1 && !cbdata.clonepool) + { + id = stringpool_str2id(cbdata.ownspool, pool_id2str(pool, id), 1); + if (id >= cbdata.needid[0].map) + { + grow_needid(&cbdata, id); + needid = cbdata.needid; /* we relocated */ + reloff = needid[0].map; /* we have a new offset */ + } + } + needid[id].need++; + } + + id = rd->evr; + if (ISRELDEP(id)) + { + id = GETRELID(id); + if (needid[reloff + id].need < need + 1) + needid[reloff + id].need = need + 1; + } + else + { + if (cbdata.ownspool && id > 1 && !cbdata.clonepool) + { + id = stringpool_str2id(cbdata.ownspool, pool_id2str(pool, id), 1); + if (id >= cbdata.needid[0].map) + { + grow_needid(&cbdata, id); + needid = cbdata.needid; /* we relocated */ + reloff = needid[0].map; /* we have a new offset */ + } + } + needid[id].need++; + } + } + } + +/********************************************************************/ /* increment need id for used dir components */ - if (dirpool) + if (cbdata.owndirpool) { /* if we have own dirpool, all entries in it are used. also, all comp ids are already mapped by putinowndirpool(), so we can simply increment needid. (owndirpool != 0, dirused == 0, dirpooldata == 0) */ + for (i = 1; i < dirpool->ndirs; i++) + { + id = dirpool->dirs[i]; + if (id <= 0) + continue; + needid[id].need++; + } + } + else if (dirpool) + { + Id parent; /* else we re-use a dirpool of repodata "dirpooldata". dirused tells us which of the ids are used. we need to map comp ids if we generate a new pool. (owndirpool == 0, dirused != 0, dirpooldata != 0) */ - for (i = 1; i < dirpool->ndirs; i++) + for (i = dirpool->ndirs - 1; i > 0; i--) { -#if 0 -fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); -#endif - if (cbdata.dirused && !cbdata.dirused[i]) + if (!cbdata.dirused[i]) continue; + parent = dirpool_parent(dirpool, i); /* always < i */ + cbdata.dirused[parent] = 2; /* 2: used as parent */ id = dirpool->dirs[i]; if (id <= 0) continue; - if (dirpooldata && cbdata.ownspool && id > 1) + if (cbdata.ownspool && id > 1 && (!cbdata.clonepool || dirpooldata->localpool)) { - id = putinownpool(&cbdata, dirpooldata->localpool ? &dirpooldata->spool : &pool->ss, id); + id = putinownpool(&cbdata, dirpooldata, id); needid = cbdata.needid; } needid[id].need++; } + if (!cbdata.dirused[0]) + { + cbdata.dirused = solv_free(cbdata.dirused); + dirpool = 0; + } } @@ -1606,13 +1753,9 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); for (i = 1; i < reloff + pool->nrels; i++) needid[i].map = i; -#if 0 - solv_sort(needid + 1, spool->nstrings - 1, sizeof(*needid), needid_cmp_need_s, spool); -#else /* make first entry '' */ needid[1].need = 1; solv_sort(needid + 2, spool->nstrings - 2, sizeof(*needid), needid_cmp_need_s, spool); -#endif solv_sort(needid + reloff, pool->nrels, sizeof(*needid), needid_cmp_need, 0); /* now needid is in new order, needid[newid].map -> oldid */ @@ -1652,7 +1795,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); ndirmap = 0; dirmap = 0; - if (dirpool) + if (dirpool && dirpool->ndirs) { /* create our new target directory structure by traversing through all * used dirs. This will concatenate blocks with the same parent @@ -1661,7 +1804,10 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); * we will change this in the second step below */ /* (dirpooldata and dirused are 0 if we have our own dirpool) */ if (cbdata.dirused && !cbdata.dirused[1]) - cbdata.dirused[1] = 1; /* always want / entry */ + { + cbdata.dirused[1] = 1; /* always want / entry */ + cbdata.dirused[0] = 2; /* always want / entry */ + } dirmap = solv_calloc(dirpool->ndirs, sizeof(Id)); dirmap[0] = 0; ndirmap = traverse_dirs(dirpool, dirmap, 1, dirpool_child(dirpool, 0), cbdata.dirused); @@ -1678,7 +1824,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); cbdata.dirused[dirmap[i]] = i; id = dirpool->dirs[dirmap[i]]; if (dirpooldata && cbdata.ownspool && id > 1) - id = putinownpool(&cbdata, dirpooldata->localpool ? &dirpooldata->spool : &pool->ss, id); + id = putinownpool(&cbdata, dirpooldata, id); dirmap[i] = needid[id].need; } /* now the new target directory structure is complete (dirmap), and we have @@ -1689,6 +1835,8 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); /* collect all data * we use extdata[0] for incore data and extdata[keyid] for vertical data + * + * this must match the code above that creates the schema data! */ cbdata.extdata = solv_calloc(target.nkeys, sizeof(struct extdata)); @@ -1699,77 +1847,41 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); cbdata.lastlen = 0; data_addid(xd, mainschema); -#if 1 + keyskip = create_keyskip(repo, SOLVID_META, repodataused, &oldkeyskip); FOR_REPODATAS(repo, j, data) { if (!repodataused[j]) continue; - repodata_search(data, SOLVID_META, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata); + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; + repodata_search_keyskip(data, SOLVID_META, 0, searchflags, keyskip, collect_data_cb, &cbdata); } -#endif - if (xd->len - cbdata.lastlen > cbdata.maxdata) cbdata.maxdata = xd->len - cbdata.lastlen; cbdata.lastlen = xd->len; if (anysolvableused) { - data_addid(xd, repo->nsolvables); /* FLEXARRAY nentries */ + data_addid(xd, nsolvables); /* FLEXARRAY nentries */ cbdata.doingsolvables = 1; - /* check if we can do the special filelist memory optimization */ - if (anyrepodataused) - { - for (i = 1; i < target.nkeys; i++) - if (target.keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) - cbdata.filelistmode |= cbdata.filelistmode == 0 && target.keys[i].type == REPOKEY_TYPE_DIRSTRARRAY ? 1 : 2; - else if (target.keys[i].type == REPOKEY_TYPE_DIRSTRARRAY) - cbdata.filelistmode = 2; - if (cbdata.filelistmode != 1) - cbdata.filelistmode = 0; - } - - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) + for (i = solvablestart, s = pool->solvables + i, n = 0; i < solvableend; i++, s++) { if (s->repo != repo) continue; - data_addid(xd, cbdata.solvschemata[n]); - if (cbdata.keymap[SOLVABLE_NAME]) - data_addid(xd, needid[s->name].need); - if (cbdata.keymap[SOLVABLE_ARCH]) - data_addid(xd, needid[s->arch].need); - if (cbdata.keymap[SOLVABLE_EVR]) - data_addid(xd, needid[s->evr].need); - if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) - data_addid(xd, needid[s->vendor].need); - if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - data_adddepids(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); - if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - data_adddepids(xd, pool, needid, idarraydata + s->obsoletes, 0); - if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - data_adddepids(xd, pool, needid, idarraydata + s->conflicts, 0); - if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - data_adddepids(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); - if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - data_adddepids(xd, pool, needid, idarraydata + s->recommends, 0); - if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - data_adddepids(xd, pool, needid, idarraydata + s->suggests, 0); - if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - data_adddepids(xd, pool, needid, idarraydata + s->supplements, 0); - if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - data_adddepids(xd, pool, needid, idarraydata + s->enhances, 0); - if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) - data_addid(xd, repo->rpmdbid[i - repo->start]); + data_addid(xd, solvschemata[n]); + collect_data_solvable(&cbdata, s, keymap); if (anyrepodataused) { + keyskip = create_keyskip(repo, i, repodataused, &oldkeyskip); cbdata.vstart = -1; FOR_REPODATAS(repo, j, data) { - if (!repodataused[j]) - continue; - if (i < data->start || i >= data->end) + if (!repodataused[j] || i < data->start || i >= data->end) continue; - repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata); + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; + repodata_search_keyskip(data, i, 0, searchflags, keyskip, collect_data_cb, &cbdata); } } if (xd->len - cbdata.lastlen > cbdata.maxdata) @@ -1781,11 +1893,8 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); } assert(cbdata.current_sub == cbdata.nsubschemata); - if (cbdata.subschemata) - { - cbdata.subschemata = solv_free(cbdata.subschemata); - cbdata.nsubschemata = 0; - } + cbdata.subschemata = solv_free(cbdata.subschemata); + cbdata.nsubschemata = 0; /********************************************************************/ @@ -1802,7 +1911,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); write_u32(&target, nstrings); write_u32(&target, nrels); write_u32(&target, ndirmap); - write_u32(&target, anysolvableused ? repo->nsolvables : 0); + write_u32(&target, anysolvableused ? nsolvables : 0); write_u32(&target, target.nkeys); write_u32(&target, target.nschemata); solv_flags = 0; @@ -1857,9 +1966,9 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); */ for (i = 0; i < nrels; i++) { - ran = pool->rels + (needid[reloff + i].map - reloff); - write_id(&target, needid[ISRELDEP(ran->name) ? RELOFF(ran->name) : ran->name].need); - write_id(&target, needid[ISRELDEP(ran->evr) ? RELOFF(ran->evr) : ran->evr].need); + Reldep *ran = pool->rels + (needid[reloff + i].map - reloff); + write_id(&target, needid[NEEDIDOFF(ran->name)].need); + write_id(&target, needid[NEEDIDOFF(ran->evr)].need); write_u8(&target, ran->flags); } @@ -1901,52 +2010,60 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); for (i = 1; i < target.nschemata; i++) write_idarray(&target, pool, 0, repodata_id2schema(&target, i)); -/********************************************************************/ - + /* + * write incore data + */ write_id(&target, cbdata.maxdata); write_id(&target, cbdata.extdata[0].len); if (cbdata.extdata[0].len) write_blob(&target, cbdata.extdata[0].buf, cbdata.extdata[0].len); solv_free(cbdata.extdata[0].buf); - /* do we have vertical data? */ + /* + * write vertical data if we have any + */ for (i = 1; i < target.nkeys; i++) if (cbdata.extdata[i].len) break; if (i < target.nkeys) { - /* yes, write it in pages */ + /* have vertical data, write it in pages */ unsigned char vpage[REPOPAGE_BLOBSIZE]; int lpage = 0; write_u32(&target, REPOPAGE_BLOBSIZE); - for (i = 1; i < target.nkeys; i++) - if (cbdata.extdata[i].len) - { - if (cbdata.filelistmode) - break; - lpage = write_compressed_extdata(&target, cbdata.extdata + i, vpage, lpage); - } - if (cbdata.filelistmode && i < target.nkeys) + if (!cbdata.filelistmode) { - /* ok, just this single extdata, which is a filelist */ + for (i = 1; i < target.nkeys; i++) + if (cbdata.extdata[i].len) + lpage = write_compressed_extdata(&target, cbdata.extdata + i, vpage, lpage); + } + else + { + /* ok, just one single extdata which is of type REPOKEY_TYPE_DIRSTRARRAY */ xd = cbdata.extdata + i; xd->len = 0; - cbdata.filelistmode = -1; - for (j = 0; j < cbdata.nkeymap; j++) - if (cbdata.keymap[j] != i) - cbdata.keymap[j] = 0; - for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++) + keyskip = create_keyskip(repo, SOLVID_META, repodataused, &oldkeyskip); + FOR_REPODATAS(repo, j, data) + { + if (!repodataused[j]) + continue; + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; + repodata_search_keyskip(data, SOLVID_META, 0, searchflags, keyskip, collect_filelist_cb, &cbdata); + } + for (i = solvablestart, s = pool->solvables + i; i < solvableend; i++, s++) { if (s->repo != repo) continue; + keyskip = create_keyskip(repo, i, repodataused, &oldkeyskip); FOR_REPODATAS(repo, j, data) { - if (!repodataused[j]) + if (!repodataused[j] || i < data->start || i >= data->end) continue; - if (i < data->start || i >= data->end) - continue; - repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata); + cbdata.keymap = keymap + keymapstart[j]; + cbdata.lastdirid = 0; + repodata_search_keyskip(data, i, 0, searchflags, keyskip, collect_filelist_cb, &cbdata); } if (xd->len > 1024 * 1024) { @@ -1969,56 +2086,64 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); repodata_freedata(&target); solv_free(needid); - solv_free(cbdata.solvschemata); + solv_free(solvschemata); solv_free(cbdata.schema); - solv_free(cbdata.keymap); - solv_free(cbdata.keymapstart); + solv_free(keymap); + solv_free(keymapstart); solv_free(cbdata.dirused); solv_free(repodataused); + solv_free(oldkeyskip); return target.error; } -struct repodata_write_data { - int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata); - void *kfdata; - int repodataid; -}; - -static int -repodata_write_keyfilter(Repo *repo, Repokey *key, void *kfdata) +int +repo_write(Repo *repo, FILE *fp) { - struct repodata_write_data *wd = kfdata; - - /* XXX: special repodata selection hack */ - if (key->name == 1 && key->size != wd->repodataid) - return -1; - if (key->storage == KEY_STORAGE_SOLVABLE) - return KEY_STORAGE_DROPPED; /* not part of this repodata */ - if (wd->keyfilter) - return (*wd->keyfilter)(repo, key, wd->kfdata); - return key->storage; + int res; + Repowriter *writer = repowriter_create(repo); + res = repowriter_write(writer, fp); + repowriter_free(writer); + return res; } int -repodata_write_filtered(Repodata *data, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq) +repodata_write(Repodata *data, FILE *fp) { - struct repodata_write_data wd; - - wd.keyfilter = keyfilter; - wd.kfdata = kfdata; - wd.repodataid = data->repodataid; - return repo_write_filtered(data->repo, fp, repodata_write_keyfilter, &wd, keyq); + int res; + Repowriter *writer = repowriter_create(data->repo); + repowriter_set_repodatarange(writer, data->repodataid, data->repodataid + 1); + repowriter_set_flags(writer, REPOWRITER_NO_STORAGE_SOLVABLE); + res = repowriter_write(writer, fp); + repowriter_free(writer); + return res; } +/* deprecated functions, do not use in new code! */ int -repodata_write(Repodata *data, FILE *fp) +repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq) { - return repodata_write_filtered(data, fp, repo_write_stdkeyfilter, 0, 0); + int res; + Repowriter *writer = repowriter_create(repo); + repowriter_set_flags(writer, REPOWRITER_LEGACY); + repowriter_set_keyfilter(writer, keyfilter, kfdata); + repowriter_set_keyqueue(writer, keyq); + res = repowriter_write(writer, fp); + repowriter_free(writer); + return res; } int -repo_write(Repo *repo, FILE *fp) +repodata_write_filtered(Repodata *data, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq) { - return repo_write_filtered(repo, fp, repo_write_stdkeyfilter, 0, 0); + int res; + Repowriter *writer = repowriter_create(data->repo); + repowriter_set_repodatarange(writer, data->repodataid, data->repodataid + 1); + repowriter_set_flags(writer, REPOWRITER_NO_STORAGE_SOLVABLE | REPOWRITER_LEGACY); + repowriter_set_keyfilter(writer, keyfilter, kfdata); + repowriter_set_keyqueue(writer, keyq); + res = repowriter_write(writer, fp); + repowriter_free(writer); + return res; } + diff --git a/src/repo_write.h b/src/repo_write.h index 763147e..3471670 100644 --- a/src/repo_write.h +++ b/src/repo_write.h @@ -22,14 +22,42 @@ extern "C" { #endif -extern int repo_write(Repo *repo, FILE *fp); -extern int repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq); +typedef struct s_Repowriter { + Repo *repo; + int flags; + int repodatastart; + int repodataend; + int solvablestart; + int solvableend; + int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata); + void *kfdata; + Queue *keyq; +} Repowriter; + +/* repowriter flags */ +#define REPOWRITER_NO_STORAGE_SOLVABLE (1 << 0) +#define REPOWRITER_KEEP_TYPE_DELETED (1 << 1) +#define REPOWRITER_LEGACY (1 << 30) +Repowriter *repowriter_create(Repo *repo); +Repowriter *repowriter_free(Repowriter *writer); +void repowriter_set_flags(Repowriter *writer, int flags); +void repowriter_set_keyfilter(Repowriter *writer, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata); +void repowriter_set_keyqueue(Repowriter *writer, Queue *keyq); +void repowriter_set_repodatarange(Repowriter *writer, int repodatastart, int repodataend); +void repowriter_set_solvablerange(Repowriter *writer, int solvablestart, int solvableend); +int repowriter_write(Repowriter *writer, FILE *fp); + +/* convenience functions */ +extern int repo_write(Repo *repo, FILE *fp); extern int repodata_write(Repodata *data , FILE *fp); -extern int repodata_write_filtered(Repodata *data , FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq); extern int repo_write_stdkeyfilter(Repo *repo, Repokey *key, void *kfdata); +/* deprecated functions, do not use in new code! */ +extern int repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq); +extern int repodata_write_filtered(Repodata *data , FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq); + #ifdef __cplusplus } #endif diff --git a/src/repodata.c b/src/repodata.c index 4ab5d18..71e8175 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Novell Inc. + * Copyright (c) 2018, SUSE LLC. * * This program is licensed under the BSD license, read LICENSE.BSD * for further information @@ -94,6 +94,8 @@ repodata_freedata(Repodata *data) solv_free(data->attrnum64data); solv_free(data->dircache); + + repodata_free_filelistfilter(data); } void @@ -518,17 +520,36 @@ get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance) return 0; } -static int -load_repodata(Repodata *data) +void +repodata_load(Repodata *data) { + if (data->state != REPODATA_STUB) + return; if (data->loadcallback) + data->loadcallback(data); + else + data->state = REPODATA_ERROR; +} + +static int +maybe_load_repodata_stub(Repodata *data, Id keyname) +{ + if (data->state != REPODATA_STUB) { - data->loadcallback(data); - if (data->state == REPODATA_AVAILABLE) - return 1; + data->state = REPODATA_ERROR; + return 0; } - data->state = REPODATA_ERROR; - return 0; + if (keyname) + { + int i; + for (i = 1; i < data->nkeys; i++) + if (keyname == data->keys[i].name) + break; + if (i == data->nkeys) + return 0; + } + repodata_load(data); + return data->state == REPODATA_AVAILABLE ? 1 : 0; } static inline int @@ -536,28 +557,11 @@ maybe_load_repodata(Repodata *data, Id keyname) { if (keyname && !repodata_precheck_keyname(data, keyname)) return 0; /* do not bother... */ - switch(data->state) - { - case REPODATA_STUB: - if (keyname) - { - int i; - for (i = 1; i < data->nkeys; i++) - if (keyname == data->keys[i].name) - break; - if (i == data->nkeys) - return 0; - } - return load_repodata(data); - case REPODATA_ERROR: - return 0; - case REPODATA_AVAILABLE: - case REPODATA_LOADING: - return 1; - default: - data->state = REPODATA_ERROR; - return 0; - } + if (data->state == REPODATA_AVAILABLE || data->state == REPODATA_LOADING) + return 1; + if (data->state == REPODATA_ERROR) + return 0; + return maybe_load_repodata_stub(data, keyname); } static inline unsigned char * @@ -626,6 +630,53 @@ find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp) return get_data(data, key, &dp, 0); } +static const Id * +repodata_lookup_schemakeys(Repodata *data, Id solvid) +{ + Id schema; + if (!maybe_load_repodata(data, 0)) + return 0; + if (!solvid2data(data, solvid, &schema)) + return 0; + return data->schemadata + data->schemata[schema]; +} + +static Id * +alloc_keyskip() +{ + Id *keyskip = solv_calloc(3 + 256, sizeof(Id)); + keyskip[0] = 256; + keyskip[1] = keyskip[2] = 1; + return keyskip; +} + +Id * +repodata_fill_keyskip(Repodata *data, Id solvid, Id *keyskip) +{ + const Id *keyp; + Id maxkeyname, value; + keyp = repodata_lookup_schemakeys(data, solvid); + if (!keyp) + return keyskip; /* no keys for this solvid */ + if (!keyskip) + keyskip = alloc_keyskip(); + maxkeyname = keyskip[0]; + value = keyskip[1] + data->repodataid; + for (; *keyp; keyp++) + { + Id keyname = data->keys[*keyp].name; + if (keyname >= maxkeyname) + { + int newmax = (keyname | 255) + 1; + keyskip = solv_realloc2(keyskip, 3 + newmax, sizeof(Id)); + memset(keyskip + (3 + maxkeyname), 0, (newmax - maxkeyname) * sizeof(Id)); + keyskip[0] = maxkeyname = newmax; + } + keyskip[3 + keyname] = value; + } + return keyskip; +} + Id repodata_lookup_type(Repodata *data, Id solvid, Id keyname) { @@ -682,52 +733,32 @@ repodata_lookup_str(Repodata *data, Id solvid, Id keyname) return pool_id2str(data->repo->pool, id); } -int -repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long *value) +unsigned long long +repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long notfound) { unsigned char *dp; Repokey *key; unsigned int high, low; - *value = 0; dp = find_key_data(data, solvid, keyname, &key); if (!dp) - return 0; + return notfound; switch (key->type) { case REPOKEY_TYPE_NUM: data_read_num64(dp, &low, &high); - *value = (unsigned long long)high << 32 | low; - return 1; - case REPOKEY_TYPE_U32: - data_read_u32(dp, &low); - *value = low; - return 1; + return (unsigned long long)high << 32 | low; case REPOKEY_TYPE_CONSTANT: - *value = key->size; - return 1; + return key->size; default: - return 0; + return notfound; } } int repodata_lookup_void(Repodata *data, Id solvid, Id keyname) { - Id schema; - Id *keyp; - unsigned char *dp; - - if (!maybe_load_repodata(data, keyname)) - return 0; - dp = solvid2data(data, solvid, &schema); - if (!dp) - return 0; - /* can't use find_key_data as we need to test the type */ - for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++) - if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID) - return 1; - return 0; + return repodata_lookup_type(data, solvid, keyname) == REPOKEY_TYPE_VOID ? 1 : 0; } const unsigned char * @@ -760,9 +791,7 @@ repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q) queue_empty(q); dp = find_key_data(data, solvid, keyname, &key); - if (!dp) - return 0; - if (key->type != REPOKEY_TYPE_IDARRAY) + if (!dp || key->type != REPOKEY_TYPE_IDARRAY) return 0; for (;;) { @@ -792,6 +821,48 @@ repodata_lookup_binary(Repodata *data, Id solvid, Id keyname, int *lenp) return dp; } +/* highly specialized function to speed up fileprovides adding. + * - repodata must be available + * - solvid must be >= data->start and < data->end + * - returns NULL is not found, a "" entry if wrong type + * - also returns wrong type for REPOKEY_TYPE_DELETED + */ +const unsigned char * +repodata_lookup_packed_dirstrarray(Repodata *data, Id solvid, Id keyname) +{ + static unsigned char wrongtype[2] = { 0x00 /* dir id 0 */, 0 /* "" */ }; + unsigned char *dp; + Id schema, *keyp, *kp; + Repokey *key; + + if (!data->incoredata || !data->incoreoffset[solvid - data->start]) + return 0; + dp = data->incoredata + data->incoreoffset[solvid - data->start]; + dp = data_read_id(dp, &schema); + keyp = data->schemadata + data->schemata[schema]; + for (kp = keyp; *kp; kp++) + if (data->keys[*kp].name == keyname) + break; + if (!*kp) + return 0; + key = data->keys + *kp; + if (key->type != REPOKEY_TYPE_DIRSTRARRAY) + return wrongtype; + dp = forward_to_key(data, *kp, keyp, dp); + if (key->storage == KEY_STORAGE_INCORE) + return dp; + if (key->storage == KEY_STORAGE_VERTICAL_OFFSET && dp) + { + Id off, len; + dp = data_read_id(dp, &off); + data_read_id(dp, &len); + return get_vertical_data(data, key, off, len); + } + return 0; +} + +/* id translation functions */ + Id repodata_globalize_id(Repodata *data, Id id, int create) { @@ -811,97 +882,172 @@ repodata_localize_id(Repodata *data, Id id, int create) Id repodata_translate_id(Repodata *data, Repodata *fromdata, Id id, int create) { + const char *s; if (!id || !data || !fromdata) return id; - if (!data->localpool || !fromdata->localpool) - { - if (fromdata->localpool) - id = repodata_globalize_id(fromdata, id, create); - if (data->localpool) - id = repodata_localize_id(data, id, create); - return id; - } - /* localpool is set in both data and fromdata */ - return stringpool_str2id(&data->spool, stringpool_id2str(&fromdata->spool, id), create); + if (data == fromdata || (!data->localpool && !fromdata->localpool)) + return id; + if (fromdata->localpool) + s = stringpool_id2str(&fromdata->spool, id); + else + s = pool_id2str(data->repo->pool, id); + if (data->localpool) + return stringpool_str2id(&data->spool, s, create); + else + return pool_str2id(data->repo->pool, s, create); } Id -repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid) +repodata_translate_dir_slow(Repodata *data, Repodata *fromdata, Id dir, int create, Id *cache) { - Id *ap; - if (!data->attrs) - return 0; - ap = data->attrs[solvid - data->start]; - if (!ap) - return 0; - for (; *ap; ap += 2) + Id parent, compid; + if (!dir) { - if (data->keys[*ap].name != keyname) - continue; - if (data->keys[*ap].type == REPOKEY_TYPE_VOID) - return voidid; - if (data->keys[*ap].type == REPOKEY_TYPE_ID) - return ap[1]; + /* make sure that the dirpool has an entry */ + if (create && !data->dirpool.ndirs) + dirpool_add_dir(&data->dirpool, 0, 0, create); return 0; } - return 0; + parent = dirpool_parent(&fromdata->dirpool, dir); + if (parent) + { + if (!(parent = repodata_translate_dir(data, fromdata, parent, create, cache))) + return 0; + } + compid = dirpool_compid(&fromdata->dirpool, dir); + if (compid > 1 && (data->localpool || fromdata->localpool)) + { + if (!(compid = repodata_translate_id(data, fromdata, compid, create))) + return 0; + } + if (!(compid = dirpool_add_dir(&data->dirpool, parent, compid, create))) + return 0; + if (cache) + { + cache[(dir & 255) * 2] = dir; + cache[(dir & 255) * 2 + 1] = compid; + } + return compid; } -const char * -repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp) +/************************************************************************ + * uninternalized lookup / search + */ + +static void +data_fetch_uninternalized(Repodata *data, Repokey *key, Id value, KeyValue *kv) { - Id *ap, did; - Id iter = *iterp; - if (iter == 0) /* find key data */ + Id *array; + kv->eof = 1; + switch (key->type) { - if (!data->attrs) - return 0; - ap = data->attrs[solvid - data->start]; - if (!ap) - return 0; - for (; *ap; ap += 2) - if (data->keys[*ap].name == keyname && data->keys[*ap].type == REPOKEY_TYPE_DIRSTRARRAY) - break; - if (!*ap) - return 0; - iter = ap[1]; + case REPOKEY_TYPE_STR: + kv->str = (const char *)data->attrdata + value; + return; + case REPOKEY_TYPE_CONSTANT: + kv->num2 = 0; + kv->num = key->size; + return; + case REPOKEY_TYPE_CONSTANTID: + kv->id = key->size; + return; + case REPOKEY_TYPE_NUM: + kv->num2 = 0; + kv->num = value; + if (value & 0x80000000) + { + kv->num = (unsigned int)data->attrnum64data[value ^ 0x80000000]; + kv->num2 = (unsigned int)(data->attrnum64data[value ^ 0x80000000] >> 32); + } + return; + case_CHKSUM_TYPES: + kv->num = 0; /* not stringified */ + kv->str = (const char *)data->attrdata + value; + return; + case REPOKEY_TYPE_BINARY: + kv->str = (const char *)data_read_id(data->attrdata + value, (Id *)&kv->num); + return; + case REPOKEY_TYPE_IDARRAY: + array = data->attriddata + (value + kv->entry); + kv->id = array[0]; + kv->eof = array[1] ? 0 : 1; + return; + case REPOKEY_TYPE_DIRSTRARRAY: + kv->num = 0; /* not stringified */ + array = data->attriddata + (value + kv->entry * 2); + kv->id = array[0]; + kv->str = (const char *)data->attrdata + array[1]; + kv->eof = array[2] ? 0 : 1; + return; + case REPOKEY_TYPE_DIRNUMNUMARRAY: + array = data->attriddata + (value + kv->entry * 3); + kv->id = array[0]; + kv->num = array[1]; + kv->num2 = array[2]; + kv->eof = array[3] ? 0 : 1; + return; + case REPOKEY_TYPE_FIXARRAY: + case REPOKEY_TYPE_FLEXARRAY: + array = data->attriddata + (value + kv->entry); + kv->id = array[0]; /* the handle */ + kv->eof = array[1] ? 0 : 1; + return; + default: + kv->id = value; + return; } - did = *didp; - for (ap = data->attriddata + iter; *ap; ap += 2) +} + +Repokey * +repodata_lookup_kv_uninternalized(Repodata *data, Id solvid, Id keyname, KeyValue *kv) +{ + Id *ap; + if (!data->attrs || solvid < data->start || solvid >= data->end) + return 0; + ap = data->attrs[solvid - data->start]; + if (!ap) + return 0; + for (; *ap; ap += 2) { - if (did && ap[0] != did) + Repokey *key = data->keys + *ap; + if (key->name != keyname) continue; - *didp = ap[0]; - *iterp = ap - data->attriddata + 2; - return (const char *)data->attrdata + ap[1]; + data_fetch_uninternalized(data, key, ap[1], kv); + return key; } - *iterp = 0; return 0; } -const unsigned char * -repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep) +void +repodata_search_uninternalized(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) { Id *ap; - if (!data->attrs) - return 0; + int stop; + Solvable *s; + KeyValue kv; + + if (!data->attrs || solvid < data->start || solvid >= data->end) + return; ap = data->attrs[solvid - data->start]; if (!ap) - return 0; + return; for (; *ap; ap += 2) { - if (data->keys[*ap].name != keyname) + Repokey *key = data->keys + *ap; + if (keyname && key->name != keyname) continue; - switch (data->keys[*ap].type) + s = solvid > 0 ? data->repo->pool->solvables + solvid : 0; + kv.entry = 0; + do { - case_CHKSUM_TYPES: - *typep = data->keys[*ap].type; - return (const unsigned char *)data->attrdata + ap[1]; - default: - break; + data_fetch_uninternalized(data, key, ap[1], &kv); + stop = callback(cbdata, s, data, key, &kv); + kv.entry++; } + while (!kv.eof && !stop); + if (keyname || stop > SEARCH_NEXT_KEY) + return; } - return 0; } /************************************************************************ @@ -921,7 +1067,7 @@ repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int f kv->str = stringpool_id2str(&data->spool, kv->id); else kv->str = pool_id2str(pool, kv->id); - if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE) + if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE && (key->name == SOLVABLE_NAME || key->type == REPOKEY_TYPE_IDARRAY)) { const char *s; for (s = kv->str; *s >= 'a' && *s <= 'z'; s++) @@ -955,15 +1101,59 @@ repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int f } +/* this is an internal hack to pass the parent kv to repodata_search_keyskip */ struct subschema_data { - Solvable *s; void *cbdata; + Id solvid; KeyValue *parent; }; +void +repodata_search_arrayelement(Repodata *data, Id solvid, Id keyname, int flags, KeyValue *kv, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) +{ + repodata_search_keyskip(data, solvid, keyname, flags | SEARCH_SUBSCHEMA, (Id *)kv, callback, cbdata); +} + +static int +repodata_search_array(Repodata *data, Id solvid, Id keyname, int flags, Repokey *key, KeyValue *kv, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) +{ + Solvable *s = solvid > 0 ? data->repo->pool->solvables + solvid : 0; + unsigned char *dp = (unsigned char *)kv->str; + int stop; + Id schema = 0; + + if (!dp || kv->entry != -1) + return 0; + while (++kv->entry < kv->num) + { + if (kv->entry) + dp = data_skip_schema(data, dp, schema); + if (kv->entry == 0 || key->type == REPOKEY_TYPE_FLEXARRAY) + dp = data_read_id(dp, &schema); + kv->id = schema; + kv->str = (const char *)dp; + kv->eof = kv->entry == kv->num - 1 ? 1 : 0; + stop = callback(cbdata, s, data, key, kv); + if (stop && stop != SEARCH_ENTERSUB) + return stop; + if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB) + repodata_search_keyskip(data, solvid, keyname, flags | SEARCH_SUBSCHEMA, (Id *)kv, callback, cbdata); + } + if ((flags & SEARCH_ARRAYSENTINEL) != 0) + { + if (kv->entry) + dp = data_skip_schema(data, dp, schema); + kv->id = 0; + kv->str = (const char *)dp; + kv->eof = 2; + return callback(cbdata, s, data, key, kv); + } + return 0; +} + /* search a specific repodata */ void -repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) +repodata_search_keyskip(Repodata *data, Id solvid, Id keyname, int flags, Id *keyskip, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) { Id schema; Repokey *key; @@ -976,14 +1166,13 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback if (!maybe_load_repodata(data, keyname)) return; - if (solvid == SOLVID_SUBSCHEMA) + if ((flags & SEARCH_SUBSCHEMA) != 0) { - struct subschema_data *subd = cbdata; - cbdata = subd->cbdata; - s = subd->s; - schema = subd->parent->id; - dp = (unsigned char *)subd->parent->str; - kv.parent = subd->parent; + flags ^= SEARCH_SUBSCHEMA; + kv.parent = (KeyValue *)keyskip; + keyskip = 0; + schema = kv.parent->id; + dp = (unsigned char *)kv.parent->str; } else { @@ -991,9 +1180,9 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback dp = solvid2data(data, solvid, &schema); if (!dp) return; - s = data->repo->pool->solvables + solvid; kv.parent = 0; } + s = solvid > 0 ? data->repo->pool->solvables + solvid : 0; keyp = data->schemadata + data->schemata[schema]; if (keyname) { @@ -1013,58 +1202,30 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback { stop = 0; key = data->keys + keyid; - ddp = get_data(data, key, &dp, *keyp ? 1 : 0); + ddp = get_data(data, key, &dp, *keyp && !onekey ? 1 : 0); - if (key->type == REPOKEY_TYPE_DELETED) + if (keyskip && (key->name >= keyskip[0] || keyskip[3 + key->name] != keyskip[1] + data->repodataid)) { if (onekey) return; continue; } - if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY) + if (key->type == REPOKEY_TYPE_DELETED && !(flags & SEARCH_KEEP_TYPE_DELETED)) { - struct subschema_data subd; - int nentries; - Id schema = 0; - - subd.cbdata = cbdata; - subd.s = s; - subd.parent = &kv; - ddp = data_read_id(ddp, &nentries); - kv.num = nentries; - kv.entry = 0; - kv.eof = 0; - while (ddp && nentries > 0) - { - if (!--nentries) - kv.eof = 1; - if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry) - ddp = data_read_id(ddp, &schema); - kv.id = schema; - kv.str = (char *)ddp; - stop = callback(cbdata, s, data, key, &kv); - if (stop > SEARCH_NEXT_KEY) - return; - if (stop && stop != SEARCH_ENTERSUB) - break; - if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB) - repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd); - ddp = data_skip_schema(data, ddp, schema); - kv.entry++; - } - if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0) - { - /* sentinel */ - kv.eof = 2; - kv.str = (char *)ddp; - stop = callback(cbdata, s, data, key, &kv); - if (stop > SEARCH_NEXT_KEY) - return; - } if (onekey) return; continue; } + if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY) + { + kv.entry = -1; + ddp = data_read_id(ddp, (Id *)&kv.num); + kv.str = (const char *)ddp; + stop = repodata_search_array(data, solvid, 0, flags, key, &kv, callback, cbdata); + if (onekey || stop > SEARCH_NEXT_KEY) + return; + continue; + } kv.entry = 0; do { @@ -1081,6 +1242,12 @@ repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback } void +repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) +{ + repodata_search_keyskip(data, solvid, keyname, flags, 0, callback, cbdata); +} + +void repodata_setpos_kv(Repodata *data, KeyValue *kv) { Pool *pool = data->repo->pool; @@ -1271,21 +1438,6 @@ datamatcher_checkbasename(Datamatcher *ma, const char *basename) return !strcmp(match, basename); } -int -repodata_filelistfilter_matches(Repodata *data, const char *str) -{ - /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */ - /* for now hardcoded */ - if (strstr(str, "bin/")) - return 1; - if (!strncmp(str, "/etc/", 5)) - return 1; - if (!strcmp(str, "/usr/lib/sendmail")) - return 1; - return 0; -} - - enum { di_bye, @@ -1364,6 +1516,10 @@ dataiterator_init_clone(Dataiterator *di, Dataiterator *from) di->parents[i].kv.parent = &di->parents[i - 1].kv; di->kv.parent = &di->parents[di->nparents - 1].kv; } + if (di->oldkeyskip) + di->oldkeyskip = solv_memdup2(di->oldkeyskip, 3 + di->oldkeyskip[0], sizeof(Id)); + if (di->keyskip) + di->keyskip = di->oldkeyskip; } int @@ -1439,6 +1595,8 @@ dataiterator_free(Dataiterator *di) datamatcher_free(&di->matcher); if (di->dupstr) solv_free(di->dupstr); + if (di->oldkeyskip) + solv_free(di->oldkeyskip); } static unsigned char * @@ -1465,88 +1623,21 @@ dataiterator_find_keyname(Dataiterator *di, Id keyname) return dp; } -static inline int -is_filelist_extension(Repodata *data) -{ - int j; - if (!repodata_precheck_keyname(data, SOLVABLE_FILELIST)) - return 0; - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name == SOLVABLE_FILELIST) - break; - if (j == data->nkeys) - return 0; - if (data->state != REPODATA_AVAILABLE) - return 1; - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - return 0; - return 1; -} - -static int -dataiterator_filelistcheck(Dataiterator *di) -{ - int j; - int needcomplete = 0; - Repodata *data = di->data; - - if ((di->flags & SEARCH_COMPLETE_FILELIST) != 0) - if (!di->matcher.match - || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING - && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB) - || !repodata_filelistfilter_matches(data, di->matcher.match)) - needcomplete = 1; - if (data->state != REPODATA_AVAILABLE) - return needcomplete ? 1 : 0; - if (!needcomplete) - { - /* we don't need the complete filelist, so ignore all stubs */ - if (data->repo->nrepodata == 2) - return 1; - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - return 1; - return 0; - } - else - { - /* we need the complete filelist. check if we habe a filtered filelist and there's - * a extension with the complete filelist later on */ - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name == SOLVABLE_FILELIST) - break; - if (j == data->nkeys) - return 0; /* does not have filelist */ - for (j = 1; j < data->nkeys; j++) - if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) - break; - if (j == data->nkeys) - return 1; /* this is the externsion */ - while (data - data->repo->repodata + 1 < data->repo->nrepodata) - { - data++; - if (is_filelist_extension(data)) - return 0; - } - return 1; - } -} - int dataiterator_step(Dataiterator *di) { Id schema; - if (di->state == di_nextattr && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET && di->vert_ddp && di->vert_storestate != di->data->storestate) { - unsigned int ddpoff = di->ddp - di->vert_ddp; - di->vert_off += ddpoff; - di->vert_len -= ddpoff; - di->ddp = di->vert_ddp = get_vertical_data(di->data, di->key, di->vert_off, di->vert_len); - di->vert_storestate = di->data->storestate; - if (!di->ddp) - di->state = di_nextkey; - } + if (di->state == di_nextattr && di->key->storage == KEY_STORAGE_VERTICAL_OFFSET && di->vert_ddp && di->vert_storestate != di->data->storestate) + { + unsigned int ddpoff = di->ddp - di->vert_ddp; + di->vert_off += ddpoff; + di->vert_len -= ddpoff; + di->ddp = di->vert_ddp = get_vertical_data(di->data, di->key, di->vert_off, di->vert_len); + di->vert_storestate = di->data->storestate; + if (!di->ddp) + di->state = di_nextkey; + } for (;;) { switch (di->state) @@ -1562,18 +1653,28 @@ dataiterator_step(Dataiterator *di) /* FALLTHROUGH */ case di_entersolvable: di_entersolvable: - if (di->repodataid) + if (!di->repodataid) + goto di_enterrepodata; /* POS case, repodata is set */ + if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames) { - di->repodataid = 1; /* reset repodata iterator */ - if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames) - { - extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1]; + extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1]; + di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0); + di->data = 0; + goto di_entersolvablekey; + } - di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0); - di->data = 0; - goto di_entersolvablekey; - } + if (di->keyname) + { + di->data = di->keyname == SOLVABLE_FILELIST ? repo_lookup_filelist_repodata(di->repo, di->solvid, &di->matcher) : repo_lookup_repodata_opt(di->repo, di->solvid, di->keyname); + if (!di->data) + goto di_nextsolvable; + di->repodataid = di->data - di->repo->repodata; + di->keyskip = 0; + goto di_enterrepodata; } + di_leavesolvablekey: + di->repodataid = 1; /* reset repodata iterator */ + di->keyskip = repo_create_keyskip(di->repo, di->solvid, &di->oldkeyskip); /* FALLTHROUGH */ case di_enterrepodata: di_enterrepodata: @@ -1583,8 +1684,6 @@ dataiterator_step(Dataiterator *di) goto di_nextsolvable; di->data = di->repo->repodata + di->repodataid; } - if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di)) - goto di_nextrepodata; if (!maybe_load_repodata(di->data, di->keyname)) goto di_nextrepodata; di->dp = solvid2data(di->data, di->solvid, &schema); @@ -1625,15 +1724,17 @@ dataiterator_step(Dataiterator *di) } else if (di->key->storage == KEY_STORAGE_INCORE) { - di->ddp = di->dp; + di->ddp = di->dp; /* start of data */ if (di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0)) - di->dp = data_skip_key(di->data, di->dp, di->key); + di->dp = data_skip_key(di->data, di->dp, di->key); /* advance to next key */ } else di->ddp = 0; if (!di->ddp) goto di_nextkey; - if (di->key->type == REPOKEY_TYPE_DELETED) + if (di->keyskip && (di->key->name >= di->keyskip[0] || di->keyskip[3 + di->key->name] != di->keyskip[1] + di->data->repodataid)) + goto di_nextkey; + if (di->key->type == REPOKEY_TYPE_DELETED && !(di->flags & SEARCH_KEEP_TYPE_DELETED)) goto di_nextkey; if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY) goto di_enterarray; @@ -1644,10 +1745,7 @@ dataiterator_step(Dataiterator *di) case di_nextattr: di->kv.entry++; di->ddp = data_fetch(di->ddp, &di->kv, di->key); - if (di->kv.eof) - di->state = di_nextkey; - else - di->state = di_nextattr; + di->state = di->kv.eof ? di_nextkey : di_nextattr; break; case di_nextkey: di_nextkey: @@ -1658,7 +1756,7 @@ dataiterator_step(Dataiterator *di) /* FALLTHROUGH */ case di_nextrepodata: di_nextrepodata: - if (di->repodataid && ++di->repodataid < di->repo->nrepodata) + if (!di->keyname && di->repodataid && ++di->repodataid < di->repo->nrepodata) goto di_enterrepodata; /* FALLTHROUGH */ @@ -1759,8 +1857,10 @@ dataiterator_step(Dataiterator *di) /* special solvable attr handling follows */ case di_nextsolvablekey: di_nextsolvablekey: - if (di->keyname || di->key->name == RPM_RPMDBID) - goto di_enterrepodata; + if (di->keyname) + goto di_nextsolvable; + if (di->key->name == RPM_RPMDBID) /* reached end of list? */ + goto di_leavesolvablekey; di->key++; /* FALLTHROUGH */ @@ -1794,6 +1894,7 @@ dataiterator_step(Dataiterator *di) } + /* we have a potential match */ if (di->matcher.match) { const char *str; @@ -1801,6 +1902,7 @@ dataiterator_step(Dataiterator *di) if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->matcher.flags & SEARCH_FILES) != 0) if (!datamatcher_checkbasename(&di->matcher, di->kv.str)) continue; + /* now stringify so that we can do the matching */ if (!(str = repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))) { if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)) @@ -1812,6 +1914,7 @@ dataiterator_step(Dataiterator *di) } else { + /* stringify filelist if requested */ if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->flags & SEARCH_FILES) != 0) repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags); } @@ -2792,18 +2895,18 @@ repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname, } void -repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle) +repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id handle) { repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1); - data->attriddata[data->attriddatalen++] = ghandle; + data->attriddata[data->attriddatalen++] = handle; data->attriddata[data->attriddatalen++] = 0; } void -repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle) +repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id handle) { repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1); - data->attriddata[data->attriddatalen++] = ghandle; + data->attriddata[data->attriddatalen++] = handle; data->attriddata[data->attriddatalen++] = 0; } @@ -2873,7 +2976,6 @@ repodata_unset_uninternalized(Repodata *data, Id solvid, Id keyname) *pp = 0; } -/* XXX: does not work correctly, needs fix in iterators! */ void repodata_unset(Repodata *data, Id solvid, Id keyname) { @@ -3583,13 +3685,14 @@ repodata_disable_paging(Repodata *data) } } +/* call the pool's loadcallback to load a stub repodata */ static void -repodata_load_stub(Repodata *data) +repodata_stub_loader(Repodata *data) { Repo *repo = data->repo; Pool *pool = repo->pool; int r, i; - struct _Pool_tmpspace oldtmpspace; + struct s_Pool_tmpspace oldtmpspace; Datapos oldpos; if (!pool->loadcallback) @@ -3640,7 +3743,7 @@ repodata_add_stub(Repodata **datap) if (data->end > data->start) repodata_extend_block(sdata, data->start, data->end - data->start); sdata->state = REPODATA_STUB; - sdata->loadcallback = repodata_load_stub; + sdata->loadcallback = repodata_stub_loader; *datap = data; return sdata; } @@ -3694,6 +3797,8 @@ repodata_create_stubs(Repodata *data) else { repodata_add_stubkey(sdata, xkeyname, di.kv.id); + if (xkeyname == SOLVABLE_FILELIST) + repodata_set_filelisttype(sdata, REPODATA_FILELIST_EXTENSION); xkeyname = 0; } } @@ -3705,6 +3810,12 @@ repodata_create_stubs(Repodata *data) return data; } +void +repodata_set_filelisttype(Repodata *data, int type) +{ + data->filelisttype = type; +} + unsigned int repodata_memused(Repodata *data) { diff --git a/src/repodata.h b/src/repodata.h index 7208e95..f204e34 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -34,10 +34,10 @@ extern "C" { #define SIZEOF_SHA384 48 #define SIZEOF_SHA512 64 -struct _Repo; -struct _KeyValue; +struct s_Repo; +struct s_KeyValue; -typedef struct _Repokey { +typedef struct s_Repokey { Id name; Id type; /* REPOKEY_TYPE_xxx */ unsigned int size; @@ -53,19 +53,26 @@ typedef struct _Repokey { struct dircache; #endif -typedef struct _Repodata { - Id repodataid; /* our id */ - struct _Repo *repo; /* back pointer to repo */ - +/* repodata states */ #define REPODATA_AVAILABLE 0 #define REPODATA_STUB 1 #define REPODATA_ERROR 2 #define REPODATA_STORE 3 #define REPODATA_LOADING 4 +/* repodata filelist types */ +/* note that FILELIST_FILTERED means that the data contains a filtered + * filelist *AND* that it is authoritative for all included solvables. */ +#define REPODATA_FILELIST_FILTERED 1 +#define REPODATA_FILELIST_EXTENSION 2 + +typedef struct s_Repodata { + Id repodataid; /* our id */ + struct s_Repo *repo; /* back pointer to repo */ + int state; /* available, stub or error */ - void (*loadcallback)(struct _Repodata *); + void (*loadcallback)(struct s_Repodata *); int start; /* start of solvables this repodata is valid for */ int end; /* last solvable + 1 of this repodata */ @@ -87,6 +94,10 @@ typedef struct _Repodata { FILE *fp; /* file pointer of solv file */ int error; /* corrupt solv file */ + int filelisttype; /* type of filelist */ + Id *filelistfilter; /* filelist filter used */ + char *filelistfilterdata; /* filelist filter string space */ + unsigned int schemadatalen; /* schema storage size */ Id *schematahash; /* unification helper */ @@ -132,18 +143,18 @@ typedef struct _Repodata { #define SOLVID_META -1 #define SOLVID_POS -2 -#define SOLVID_SUBSCHEMA -3 /* internal! */ /*----- * management functions */ -void repodata_initdata(Repodata *data, struct _Repo *repo, int localpool); +void repodata_initdata(Repodata *data, struct s_Repo *repo, int localpool); void repodata_freedata(Repodata *data); void repodata_free(Repodata *data); void repodata_empty(Repodata *data, int localpool); +void repodata_load(Repodata *data); /* * key management functions @@ -196,25 +207,34 @@ repodata_has_keyname(Repodata *data, Id keyname) /* search key <keyname> (all keys, if keyname == 0) for Id <solvid> * Call <callback> for each match */ -void repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct _KeyValue *kv), void *cbdata); +void repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct s_KeyValue *kv), void *cbdata); +void repodata_search_keyskip(Repodata *data, Id solvid, Id keyname, int flags, Id *keyskip, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct s_KeyValue *kv), void *cbdata); +void repodata_search_arrayelement(Repodata *data, Id solvid, Id keyname, int flags, struct s_KeyValue *kv, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct s_KeyValue *kv), void *cbdata); /* Make sure the found KeyValue has the "str" field set. Return "str" * if valid, NULL if not possible */ -const char *repodata_stringify(Pool *pool, Repodata *data, Repokey *key, struct _KeyValue *kv, int flags); +const char *repodata_stringify(Pool *pool, Repodata *data, Repokey *key, struct s_KeyValue *kv, int flags); +/* filelist filter support */ +void repodata_set_filelisttype(Repodata *data, int filelisttype); int repodata_filelistfilter_matches(Repodata *data, const char *str); - +void repodata_free_filelistfilter(Repodata *data); /* lookup functions */ Id repodata_lookup_type(Repodata *data, Id solvid, Id keyname); Id repodata_lookup_id(Repodata *data, Id solvid, Id keyname); const char *repodata_lookup_str(Repodata *data, Id solvid, Id keyname); -int repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long *value); +unsigned long long repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long notfound); int repodata_lookup_void(Repodata *data, Id solvid, Id keyname); const unsigned char *repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep); int repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q); const void *repodata_lookup_binary(Repodata *data, Id solvid, Id keyname, int *lenp); +/* internal, used in fileprovides code */ +const unsigned char *repodata_lookup_packed_dirstrarray(Repodata *data, Id solvid, Id keyname); + +/* internal, fill keyskip array with data */ +Id *repodata_fill_keyskip(Repodata *data, Id solvid, Id *keyskip); /*----- * data assignment functions @@ -264,14 +284,14 @@ void repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const ch void repodata_free_dircache(Repodata *data); -/* Arrays */ +/* arrays */ void repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id); void repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname, const char *str); void repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle); void repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle); /* generic */ -void repodata_set_kv(Repodata *data, Id solvid, Id keyname, Id keytype, struct _KeyValue *kv); +void repodata_set_kv(Repodata *data, Id solvid, Id keyname, Id keytype, struct s_KeyValue *kv); void repodata_unset(Repodata *data, Id solvid, Id keyname); void repodata_unset_uninternalized(Repodata *data, Id solvid, Id keyname); @@ -294,6 +314,7 @@ void repodata_disable_paging(Repodata *data); Id repodata_globalize_id(Repodata *data, Id id, int create); Id repodata_localize_id(Repodata *data, Id id, int create); Id repodata_translate_id(Repodata *data, Repodata *fromdata, Id id, int create); +Id repodata_translate_dir_slow(Repodata *data, Repodata *fromdata, Id dir, int create, Id *cache); Id repodata_str2dir(Repodata *data, const char *dir, int create); const char *repodata_dir2str(Repodata *data, Id did, const char *suf); @@ -302,14 +323,34 @@ void repodata_set_location(Repodata *data, Id solvid, int medianr, const char *d void repodata_set_deltalocation(Repodata *data, Id handle, int medianr, const char *dir, const char *file); void repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg); -/* uninternalized data lookup */ -Id repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid); -const char *repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp); -const unsigned char *repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep); +/* uninternalized data lookup / search */ +Repokey *repodata_lookup_kv_uninternalized(Repodata *data, Id solvid, Id keyname, struct s_KeyValue *kv); +void repodata_search_uninternalized(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct s_KeyValue *kv), void *cbdata); /* stats */ unsigned int repodata_memused(Repodata *data); +static inline Id +repodata_translate_dir(Repodata *data, Repodata *fromdata, Id dir, int create, Id *cache) +{ + if (cache && dir && cache[(dir & 255) * 2] == dir) + return cache[(dir & 255) * 2 + 1]; + return repodata_translate_dir_slow(data, fromdata, dir, create, cache); +} + +static inline Id * +repodata_create_dirtranscache(Repodata *data) +{ + return (Id *)solv_calloc(256, sizeof(Id) * 2); +} + +static inline Id * +repodata_free_dirtranscache(Id *cache) +{ + return (Id *)solv_free(cache); +} + + #ifdef __cplusplus } #endif diff --git a/src/repopack.h b/src/repopack.h index 3079239..e63366d 100644 --- a/src/repopack.h +++ b/src/repopack.h @@ -129,13 +129,6 @@ data_read_ideof(unsigned char *dp, Id *idp, int *eof) } static inline unsigned char * -data_read_u32(unsigned char *dp, unsigned int *nump) -{ - *nump = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3]; - return dp + 4; -} - -static inline unsigned char * data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) { kv->eof = 1; @@ -144,6 +137,7 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) switch (key->type) { case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_DELETED: return dp; case REPOKEY_TYPE_CONSTANT: kv->num2 = 0; @@ -160,9 +154,6 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) return data_read_id(dp, &kv->id); case REPOKEY_TYPE_NUM: return data_read_num64(dp, &kv->num, &kv->num2); - case REPOKEY_TYPE_U32: - kv->num2 = 0; - return data_read_u32(dp, &kv->num); case REPOKEY_TYPE_MD5: kv->num = 0; /* not stringified yet */ kv->str = (const char *)dp; @@ -203,10 +194,17 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) dp = data_read_id(dp, (Id *)&kv->num); return data_read_ideof(dp, (Id *)&kv->num2, &kv->eof); case REPOKEY_TYPE_FIXARRAY: - dp = data_read_id(dp, (Id *)&kv->num); - return data_read_id(dp, &kv->id); case REPOKEY_TYPE_FLEXARRAY: - return data_read_id(dp, (Id *)&kv->num); + if (!kv->entry) + { + dp = data_read_id(dp, (Id *)&kv->num); /* number of elements */ + if (!kv->num) + return 0; /* illegal */ + } + if (!kv->entry || key->type == REPOKEY_TYPE_FLEXARRAY) + dp = data_read_id(dp, &kv->id); /* schema */ + kv->str = (const char *)dp; + return dp; default: return 0; } @@ -229,8 +227,6 @@ data_skip(unsigned char *dp, int type) while ((*dp & 0x80) != 0) dp++; return dp + 1; - case REPOKEY_TYPE_U32: - return dp + 4; case REPOKEY_TYPE_MD5: return dp + SIZEOF_MD5; case REPOKEY_TYPE_SHA1: @@ -290,96 +286,4 @@ data_skip(unsigned char *dp, int type) } } -static inline unsigned char * -data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir) -{ - Id id; - int eof; - - switch (type) - { - case REPOKEY_TYPE_VOID: - case REPOKEY_TYPE_CONSTANT: - case REPOKEY_TYPE_CONSTANTID: - case REPOKEY_TYPE_DELETED: - return dp; - case REPOKEY_TYPE_NUM: - while ((*dp & 0x80) != 0) - dp++; - return dp + 1; - case REPOKEY_TYPE_U32: - return dp + 4; - case REPOKEY_TYPE_MD5: - return dp + SIZEOF_MD5; - case REPOKEY_TYPE_SHA1: - return dp + SIZEOF_SHA1; - case REPOKEY_TYPE_SHA224: - return dp + SIZEOF_SHA224; - case REPOKEY_TYPE_SHA256: - return dp + SIZEOF_SHA256; - case REPOKEY_TYPE_SHA384: - return dp + SIZEOF_SHA384; - case REPOKEY_TYPE_SHA512: - return dp + SIZEOF_SHA512; - case REPOKEY_TYPE_ID: - dp = data_read_id(dp, &id); - if (id >= maxid) - return 0; - return dp; - case REPOKEY_TYPE_DIR: - dp = data_read_id(dp, &id); - if (id >= maxdir) - return 0; - return dp; - case REPOKEY_TYPE_IDARRAY: - for (;;) - { - dp = data_read_ideof(dp, &id, &eof); - if (id >= maxid) - return 0; - if (eof) - return dp; - } - case REPOKEY_TYPE_STR: - while ((*dp) != 0) - dp++; - return dp + 1; - case REPOKEY_TYPE_BINARY: - { - unsigned int len; - dp = data_read_id(dp, (Id *)&len); - return dp + len; - } - case REPOKEY_TYPE_DIRSTRARRAY: - for (;;) - { - dp = data_read_ideof(dp, &id, &eof); - if (id >= maxdir) - return 0; - while ((*dp) != 0) - dp++; - dp++; - if (eof) - return dp; - } - case REPOKEY_TYPE_DIRNUMNUMARRAY: - for (;;) - { - dp = data_read_id(dp, &id); - if (id >= maxdir) - return 0; - while ((*dp & 0x80) != 0) - dp++; - dp++; - while ((*dp & 0x80) != 0) - dp++; - if (!(*dp & 0x40)) - return dp + 1; - dp++; - } - default: - return 0; - } -} - #endif /* LIBSOLV_REPOPACK */ diff --git a/src/repopage.h b/src/repopage.h index 739345e..b5f2eee 100644 --- a/src/repopage.h +++ b/src/repopage.h @@ -11,7 +11,7 @@ #define REPOPAGE_BLOBBITS 15 #define REPOPAGE_BLOBSIZE (1 << REPOPAGE_BLOBBITS) -typedef struct _Attrblobpage +typedef struct s_Attrblobpage { /* page_size == 0 means the page is not backed by some file storage. Otherwise it is L*2+(compressed ? 1 : 0), with L being the data @@ -20,7 +20,7 @@ typedef struct _Attrblobpage unsigned int page_size; } Attrblobpage; -typedef struct _Repopagestore { +typedef struct s_Repopagestore { int pagefd; /* file descriptor we're paging from */ long file_offset; /* pages in file start here */ diff --git a/src/rules.c b/src/rules.c index 5901145..df32341 100644 --- a/src/rules.c +++ b/src/rules.c @@ -1328,31 +1328,6 @@ solver_addfeaturerule(Solver *solv, Solvable *s) } } -/* check if multiversion solvable s2 has an obsoletes for installed solvable s */ -static int -is_multiversion_obsoleteed(Pool *pool, Solvable *s, Solvable *s2) -{ - Id *wp, obs, *obsp; - - if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2)) - return 0; - obsp = s2->repo->idarraydata + s2->obsoletes; - if (!pool->obsoleteusesprovides) - { - while ((obs = *obsp++) != 0) - if (pool_match_nevr(pool, s, obs)) - return 1; - } - else - { - while ((obs = *obsp++) != 0) - for (wp = pool_whatprovides_ptr(pool, obs); *wp; wp++) - if (pool->solvables + *wp == s) - return 1; - } - return 0; -} - /*------------------------------------------------------------------- * * add rule for update @@ -1414,8 +1389,9 @@ solver_addupdaterule(Solver *solv, Solvable *s) if (MAPTST(&solv->multiversion, qs.elements[i])) { Solvable *ps = pool->solvables + qs.elements[i]; - /* check if there is an explicit obsoletes */ - if (solv->keepexplicitobsoletes && ps->obsoletes && is_multiversion_obsoleteed(pool, s, ps)) + /* if keepexplicitobsoletes is set and the name is different, + * we assume that there is an obsoletes. XXX: not 100% correct */ + if (solv->keepexplicitobsoletes && ps->name != s->name) { qs.elements[j++] = qs.elements[i]; continue; @@ -2199,7 +2175,7 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) if (pool->solvables[p].repo == installed) return; if (solv->multiversion.size && MAPTST(&solv->multiversion, p) && !solv->keepexplicitobsoletes) - return; /* will not obsolete anything, so just return */ + return; } omap.size = 0; qstart = q->count; diff --git a/src/rules.h b/src/rules.h index db52199..a3c0135 100644 --- a/src/rules.h +++ b/src/rules.h @@ -35,7 +35,7 @@ extern "C" { * possible. Do not add new members unless there is no other way. */ -typedef struct _Rule { +typedef struct s_Rule { Id p; /* first literal in rule */ Id d; /* Id offset into 'list of providers terminated by 0' as used by whatprovides; pool->whatprovides + d */ /* in case of binary rules, d == 0, w1 == p, w2 == other literal */ @@ -76,14 +76,14 @@ typedef enum { #define SOLVER_RULE_TYPEMASK 0xff00 -struct _Solver; +struct s_Solver; /*------------------------------------------------------------------- * disable rule */ static inline void -solver_disablerule(struct _Solver *solv, Rule *r) +solver_disablerule(struct s_Solver *solv, Rule *r) { if (r->d >= 0) r->d = -r->d - 1; @@ -94,64 +94,64 @@ solver_disablerule(struct _Solver *solv, Rule *r) */ static inline void -solver_enablerule(struct _Solver *solv, Rule *r) +solver_enablerule(struct s_Solver *solv, Rule *r) { if (r->d < 0) r->d = -r->d - 1; } -extern Rule *solver_addrule(struct _Solver *solv, Id p, Id p2, Id d); -extern void solver_unifyrules(struct _Solver *solv); -extern int solver_rulecmp(struct _Solver *solv, Rule *r1, Rule *r2); -extern void solver_shrinkrules(struct _Solver *solv, int nrules); +extern Rule *solver_addrule(struct s_Solver *solv, Id p, Id p2, Id d); +extern void solver_unifyrules(struct s_Solver *solv); +extern int solver_rulecmp(struct s_Solver *solv, Rule *r1, Rule *r2); +extern void solver_shrinkrules(struct s_Solver *solv, int nrules); /* pkg rules */ -extern void solver_addpkgrulesforsolvable(struct _Solver *solv, Solvable *s, Map *m); -extern void solver_addpkgrulesforweak(struct _Solver *solv, Map *m); -extern void solver_addpkgrulesforlinked(struct _Solver *solv, Map *m); -extern void solver_addpkgrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all); +extern void solver_addpkgrulesforsolvable(struct s_Solver *solv, Solvable *s, Map *m); +extern void solver_addpkgrulesforweak(struct s_Solver *solv, Map *m); +extern void solver_addpkgrulesforlinked(struct s_Solver *solv, Map *m); +extern void solver_addpkgrulesforupdaters(struct s_Solver *solv, Solvable *s, Map *m, int allow_all); /* update/feature rules */ -extern void solver_addfeaturerule(struct _Solver *solv, Solvable *s); -extern void solver_addupdaterule(struct _Solver *solv, Solvable *s); +extern void solver_addfeaturerule(struct s_Solver *solv, Solvable *s); +extern void solver_addupdaterule(struct s_Solver *solv, Solvable *s); /* infarch rules */ -extern void solver_addinfarchrules(struct _Solver *solv, Map *addedmap); +extern void solver_addinfarchrules(struct s_Solver *solv, Map *addedmap); /* dup rules */ -extern void solver_createdupmaps(struct _Solver *solv); -extern void solver_freedupmaps(struct _Solver *solv); -extern void solver_addduprules(struct _Solver *solv, Map *addedmap); +extern void solver_createdupmaps(struct s_Solver *solv); +extern void solver_freedupmaps(struct s_Solver *solv); +extern void solver_addduprules(struct s_Solver *solv, Map *addedmap); /* choice rules */ -extern void solver_addchoicerules(struct _Solver *solv); -extern void solver_disablechoicerules(struct _Solver *solv, Rule *r); +extern void solver_addchoicerules(struct s_Solver *solv); +extern void solver_disablechoicerules(struct s_Solver *solv, Rule *r); /* best rules */ -extern void solver_addbestrules(struct _Solver *solv, int havebestinstalljobs); +extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs); /* yumobs rules */ -extern void solver_addyumobsrules(struct _Solver *solv); +extern void solver_addyumobsrules(struct s_Solver *solv); /* policy rule disabling/reenabling */ -extern void solver_disablepolicyrules(struct _Solver *solv); -extern void solver_reenablepolicyrules(struct _Solver *solv, int jobidx); -extern void solver_reenablepolicyrules_cleandeps(struct _Solver *solv, Id pkg); +extern void solver_disablepolicyrules(struct s_Solver *solv); +extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx); +extern void solver_reenablepolicyrules_cleandeps(struct s_Solver *solv, Id pkg); /* rule info */ -extern int solver_allruleinfos(struct _Solver *solv, Id rid, Queue *rq); -extern SolverRuleinfo solver_ruleinfo(struct _Solver *solv, Id rid, Id *fromp, Id *top, Id *depp); -extern SolverRuleinfo solver_ruleclass(struct _Solver *solv, Id rid); -extern void solver_ruleliterals(struct _Solver *solv, Id rid, Queue *q); -extern int solver_rule2jobidx(struct _Solver *solv, Id rid); -extern Id solver_rule2job(struct _Solver *solv, Id rid, Id *whatp); -extern Id solver_rule2solvable(struct _Solver *solv, Id rid); -extern void solver_rule2rules(struct _Solver *solv, Id rid, Queue *q, int recursive); -extern Id solver_rule2pkgrule(struct _Solver *solv, Id rid); +extern int solver_allruleinfos(struct s_Solver *solv, Id rid, Queue *rq); +extern SolverRuleinfo solver_ruleinfo(struct s_Solver *solv, Id rid, Id *fromp, Id *top, Id *depp); +extern SolverRuleinfo solver_ruleclass(struct s_Solver *solv, Id rid); +extern void solver_ruleliterals(struct s_Solver *solv, Id rid, Queue *q); +extern int solver_rule2jobidx(struct s_Solver *solv, Id rid); +extern Id solver_rule2job(struct s_Solver *solv, Id rid, Id *whatp); +extern Id solver_rule2solvable(struct s_Solver *solv, Id rid); +extern void solver_rule2rules(struct s_Solver *solv, Id rid, Queue *q, int recursive); +extern Id solver_rule2pkgrule(struct s_Solver *solv, Id rid); /* orphan handling */ -extern void solver_breakorphans(struct _Solver *solv); -extern void solver_check_brokenorphanrules(struct _Solver *solv, Queue *dq); +extern void solver_breakorphans(struct s_Solver *solv); +extern void solver_check_brokenorphanrules(struct s_Solver *solv, Queue *dq); /* legacy */ diff --git a/src/selection.c b/src/selection.c index 0b36ea8..a160122 100644 --- a/src/selection.c +++ b/src/selection.c @@ -89,6 +89,7 @@ selection_solvables(Pool *pool, Queue *selection, Queue *pkgs) for (i = 0; i < selection->count; i += 2) { Id select = selection->elements[i] & SOLVER_SELECTMASK; + Id id = selection->elements[i + 1]; if (select == SOLVER_SOLVABLE_ALL) { FOR_POOL_SOLVABLES(p) @@ -97,16 +98,18 @@ selection_solvables(Pool *pool, Queue *selection, Queue *pkgs) if (select == SOLVER_SOLVABLE_REPO) { Solvable *s; - Repo *repo = pool_id2repo(pool, selection->elements[i + 1]); + Repo *repo = pool_id2repo(pool, id); if (repo) { FOR_REPO_SOLVABLES(repo, p, s) queue_push(pkgs, p); } } + else if (select == SOLVER_SOLVABLE) + queue_push(pkgs, id); else { - FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1]) + FOR_JOB_SELECT(p, pp, select, id) queue_push(pkgs, p); } } @@ -260,7 +263,7 @@ selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr) /* limit a selection to to repository */ /* prunes empty jobs */ static void -selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) +selection_filter_repo(Pool *pool, Queue *selection, Repo *repo, int setflags) { Queue q; int i, j; @@ -285,7 +288,12 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) else if (select == SOLVER_SOLVABLE_REPO) { if (id != repo->repoid) - select = 0; + continue; + } + else if (select == SOLVER_SOLVABLE) + { + if (pool->solvables[id].repo != repo) + continue; } else { @@ -299,11 +307,11 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) else queue_push(&q, p); } - if (bad || !q.count) + if (!q.count) + continue; + if (bad) { - if (!q.count) - select = 0; /* prune empty jobs */ - else if (q.count == 1) + if (q.count == 1) { select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; id = q.elements[0]; @@ -315,8 +323,6 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) } } } - if (!select) - continue; /* job is now empty */ if (select == SOLVER_SOLVABLE_REPO) { Id p; @@ -326,7 +332,7 @@ selection_filter_repo(Pool *pool, Queue *selection, Repo *repo) if (!p) continue; /* repo is empty */ } - selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SETREPO; + selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | setflags; selection->elements[j++] = id; } queue_truncate(selection, j); @@ -538,8 +544,8 @@ selection_addextra_provides(Pool *pool, Queue *selection, const char *name, int } /* this is the fast path of selection_provides: the id for the name - * is known and thus we can quickly check the existance of a - * package with that provides */ + * is known and thus we can use the whatprovides data to quickly + * check the existance of a package with that provides */ static int selection_provides_id(Pool *pool, Queue *selection, Id id, int flags) { @@ -550,20 +556,18 @@ selection_provides_id(Pool *pool, Queue *selection, Id id, int flags) Solvable *s = pool->solvables + p; if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed) continue; - break; - } - if (p) - { queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id); return SELECTION_PROVIDES; } if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0) { + /* misuse selection_addextra to test if there is an extra package + * that provides the id */ queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id); selection_addextra(pool, selection, flags); if (selection->elements[0] == SOLVER_SOLVABLE_PROVIDES) - queue_empty(selection); + queue_empty(selection); /* no extra package found */ else { selection->elements[0] = SOLVER_SOLVABLE_PROVIDES; @@ -575,7 +579,6 @@ selection_provides_id(Pool *pool, Queue *selection, Id id, int flags) return 0; } -/* add missing provides matchers to the selection */ /* match the provides of a package */ /* note that we only return raw SOLVER_SOLVABLE_PROVIDES jobs * so that the selection can be modified later. */ @@ -619,7 +622,7 @@ selection_provides(Pool *pool, Queue *selection, const char *name, int flags) for (id = 1; id < pool->ss.nstrings; id++) { /* do we habe packages providing this id? */ - if (!pool->whatprovides[id] || pool->whatprovides[id] == 1) + if ((!pool->whatprovides[id] && pool->addedfileprovides == 2) || pool->whatprovides[id] == 1) continue; n = pool_id2str(pool, id); if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0) @@ -632,6 +635,13 @@ selection_provides(Pool *pool, Queue *selection, const char *name, int flags) if (!p) continue; } + else if (!pool->whatprovides[id]) + { + FOR_PROVIDES(p, pp, id) + break; + if (!p) + continue; + } queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id); match = 1; } @@ -704,6 +714,34 @@ selection_name_id(Pool *pool, Queue *selection, Id id, int flags) return 0; } +/* does not check SELECTION_INSTALLED_ONLY, as it is normally done + * by other means */ +static inline int +solvable_matches_selection_flags(Pool *pool, Solvable *s, int flags) +{ + if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) + { + if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE)) + return 0; + /* source package are never installed and never have a bad arch */ + if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) + return 0; + } + else + { + if ((flags & SELECTION_SOURCE_ONLY) != 0) + return 0; + if (s->repo != pool->installed) + { + if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) + return 0; + if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s)) + return 0; + } + } + return 1; +} + /* match the name of a package */ /* note that for SELECTION_INSTALLED_ONLY the result is not trimmed */ static int @@ -743,20 +781,8 @@ selection_name(Pool *pool, Queue *selection, const char *name, int flags) Solvable *s = pool->solvables + p; if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed) continue; - if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) - { - if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE)) - continue; - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - } - else if (s->repo != pool->installed) - { - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s)) - continue; - } + if (!solvable_matches_selection_flags(pool, s, flags)) + continue; id = s->name; n = pool_id2str(pool, id); if (flags & SELECTION_SKIP_KIND) @@ -940,31 +966,14 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags) if ((flags & SELECTION_NOCASE) != 0) type |= SEARCH_NOCASE; queue_init(&q); - dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST); + dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES); while (dataiterator_step(&di)) { Solvable *s = pool->solvables + di.solvid; if (!s->repo) continue; - if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) - { - if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE)) - continue; - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - } - else - { - if ((flags & SELECTION_SOURCE_ONLY) != 0) - continue; - if (s->repo != pool->installed) - { - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s)) - continue; - } - } + if (!solvable_matches_selection_flags(pool, s, flags)) + continue; if ((flags & SELECTION_FLAT) != 0) { /* don't bother with the complex stuff */ @@ -1291,46 +1300,57 @@ selection_extrabits(Pool *pool, Queue *selection, int flags) return needflags; } +static int +selection_combine(Pool *pool, Queue *sel1, Queue *sel2, int flags, int ret) +{ + if ((flags & SELECTION_MODEBITS) == SELECTION_ADD) + selection_add(pool, sel1, sel2); + else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT) + selection_subtract(pool, sel1, sel2); + else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER) + { + if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY)) + { + if ((flags & SELECTION_FILTER_SWAPPED) != 0) + { + selection_filter(pool, sel2, sel1); + queue_free(sel1); + queue_init_clone(sel1, sel2); + } + else + selection_filter(pool, sel1, sel2); + } + } + else /* SELECTION_REPLACE */ + { + queue_free(sel1); + queue_init_clone(sel1, sel2); + } + queue_free(sel2); + return ret; +} + int selection_make(Pool *pool, Queue *selection, const char *name, int flags) { int ret = 0; - if ((flags & SELECTION_MODEBITS) != 0) + if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE) { Queue q; - queue_init(&q); if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER) { if (!selection->count) - { - queue_free(&q); - return 0; - } + return 0; if ((flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) != 0) { /* try to drop expensive extra bits */ flags = (flags & ~(SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) | selection_extrabits(pool, selection, flags); } } + queue_init(&q); ret = selection_make(pool, &q, name, flags & ~SELECTION_MODEBITS); - if ((flags & SELECTION_MODEBITS) == SELECTION_ADD) - selection_add(pool, selection, &q); - else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT) - selection_subtract(pool, selection, &q); - else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY)) - { - if ((flags & SELECTION_FILTER_SWAPPED) != 0) - { - selection_filter(pool, &q, selection); - queue_free(selection); - queue_init_clone(selection, &q); - } - else - selection_filter(pool, selection, &q); - } - queue_free(&q); - return ret; + return selection_combine(pool, selection, &q, flags, ret); } queue_empty(selection); if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed) @@ -1348,7 +1368,7 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) /* now do result filtering */ if (ret && (flags & SELECTION_INSTALLED_ONLY) != 0) - selection_filter_repo(pool, selection, pool->installed); + selection_filter_repo(pool, selection, pool->installed, SOLVER_SETREPO); /* flatten if requested */ if (ret && (flags & SELECTION_FLAT) != 0) @@ -1356,30 +1376,6 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags) return selection->count ? ret : 0; } -struct limiter { - int start; /* either 2 or repofilter->start */ - int end; /* either nsolvables or repofilter->end */ - Id *mapper; - Repo *repofilter; -}; - -/* add matching src packages to simple SOLVABLE_NAME selections */ -static void -setup_limiter(Pool *pool, int flags, struct limiter *limiter) -{ - limiter->start = 2; - limiter->end = pool->nsolvables; - limiter->mapper = 0; - limiter->repofilter = 0; - if ((flags & SELECTION_INSTALLED_ONLY) != 0) - { - Repo *repo = pool->installed; - limiter->repofilter = repo; - limiter->start = repo ? repo->start : 0; - limiter->end = repo ? repo->end : 0; - } -} - static int matchdep_str(const char *pattern, const char *string, int flags) { @@ -1430,8 +1426,88 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, int flags) return matchdep_str(rname, pool_id2str(pool, id), flags); } +struct limiter { + int start; /* either 2 or repofilter->start */ + int end; /* either nsolvables or repofilter->end */ + Repo *repofilter; + Id *mapper; + Queue qlimit; +}; + + +static int +selection_make_matchsolvable_common(Pool *pool, Queue *selection, Queue *solvidq, Id solvid, int flags, int keyname, int marker, struct limiter *limiter) +{ + Map m, missc; + int reloff; + int li, i, j; + Id p; + Queue q; + + if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE) + { + int ret; + Queue q; + queue_init(&q); + ret = selection_make_matchsolvable_common(pool, &q, solvidq, solvid, flags & ~SELECTION_MODEBITS, keyname, marker, limiter); + return selection_combine(pool, selection, &q, flags, ret); + } + + queue_empty(selection); + if (!limiter->end) + return 0; + if (!solvidq && !solvid) + return 0; + if (solvidq && solvid) + return 0; + + if (solvidq) + { + map_init(&m, pool->nsolvables); + for (i = 0; i < solvidq->count; i++) + MAPSET(&m, solvidq->elements[i]); + } + queue_init(&q); + reloff = pool->ss.nstrings; + map_init(&missc, reloff + pool->nrels); + for (li = limiter->start; li < limiter->end; li++) + { + Solvable *s; + p = limiter->mapper ? limiter->mapper[li] : li; + if (solvidq && MAPTST(&m, p)) + continue; + if (!solvidq && p == solvid) + continue; + s = pool->solvables + p; + if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter)) + continue; + if (!solvable_matches_selection_flags(pool, s, flags)) + continue; + if (solvable_matchessolvable_int(s, keyname, marker, solvid, solvidq ? &m : 0, &q, &missc, reloff)) + queue_push(selection, p); + } + queue_free(&q); + map_free(&missc); + if (solvidq) + map_free(&m); + + /* convert package list to selection */ + if (!selection->count) + return 0; + j = selection->count; + queue_insertn(selection, 0, selection->count, 0); + for (i = 0; i < selection->count; i += 2) + { + selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; + selection->elements[i + 1] = selection->elements[j++]; + } + if ((flags & SELECTION_FLAT) != 0) + selection_flatten(pool, selection); + return SELECTION_PROVIDES; +} + static int -selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter) +selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter) { int li, i, j; int ret = 0; @@ -1441,6 +1517,14 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char Id p; Queue q; + if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE) + { + Queue q; + queue_init(&q); + ret = selection_make_matchdeps_common(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, limiter); + return selection_combine(pool, selection, &q, flags, ret); + } + queue_empty(selection); if (!limiter->end) return 0; @@ -1468,7 +1552,7 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char revr = pool_str2id(pool, r, 1); ret |= SELECTION_REL; } - if ((flags & SELECTION_GLOB) != 0 && strpbrk(rname, "[*?") == 0) + if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0) flags &= ~SELECTION_GLOB; if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0) @@ -1505,25 +1589,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char s = pool->solvables + p; if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter)) continue; - if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) - { - if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE)) - continue; - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - } - else - { - if ((flags & SELECTION_SOURCE_ONLY) != 0) - continue; - if (s->repo != pool->installed) - { - if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s)) - continue; - if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s)) - continue; - } - } + if (!solvable_matches_selection_flags(pool, s, flags)) + continue; if (keyname == SOLVABLE_NAME) /* nevr match hack */ { if (dep) @@ -1558,7 +1625,8 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char queue_push(selection, p); continue; } - queue_empty(&q); + if (q.count) + queue_empty(&q); repo_lookup_deparray(s->repo, p, keyname, &q, marker); if (!q.count) continue; @@ -1597,16 +1665,16 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char } queue_free(&q); solv_free(rname); - if (!selection->count) - return 0; /* convert package list to selection */ + if (!selection->count) + return 0; j = selection->count; queue_insertn(selection, 0, selection->count, 0); - for (i = 0; i < selection->count; ) + for (i = 0; i < selection->count; i += 2) { - selection->elements[i++] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; - selection->elements[i++] = selection->elements[j++]; + selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET; + selection->elements[i + 1] = selection->elements[j++]; } if ((flags & SELECTION_FLAT) != 0) @@ -1614,75 +1682,56 @@ selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char return ret | (keyname == SOLVABLE_NAME ? SELECTION_NAME : SELECTION_PROVIDES); } -static int -selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker) +static void +setup_limiter(Pool *pool, Queue *selection, int flags, struct limiter *limiter) { - struct limiter limiter; - - setup_limiter(pool, flags, &limiter); - if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE) + limiter->start = 2; + limiter->end = pool->nsolvables; + limiter->mapper = 0; + limiter->repofilter = 0; + if ((flags & SELECTION_INSTALLED_ONLY) != 0) { - int ret; - Queue q, qlimit; - queue_init(&q); - queue_init(&qlimit); - /* deal with special filter cases */ - if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER && selection->count == 2 && limiter.end) - { - if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL) - flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE; - else if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO) - { - Repo *repo = pool_id2repo(pool, selection->elements[1]); - if (limiter.repofilter && repo != limiter.repofilter) - repo = 0; - limiter.repofilter = repo; - limiter.start = repo ? repo->start : 0; - limiter.end = repo ? repo->end : 0; - flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE; - } - } - if (limiter.end && ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER)) - { - selection_solvables(pool, selection, &qlimit); - limiter.start = 0; - limiter.end = qlimit.count; - limiter.mapper = qlimit.elements; - } - ret = selection_make_matchdeps_common_limited(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, &limiter); - queue_free(&qlimit); - if ((flags & SELECTION_MODEBITS) == SELECTION_ADD) - selection_add(pool, selection, &q); - else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT) - selection_subtract(pool, selection, &q); - else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER) - { - if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY)) - { - if ((flags & SELECTION_FILTER_SWAPPED) != 0) - { - selection_filter(pool, &q, selection); - queue_free(selection); - queue_init_clone(selection, &q); - } - else - selection_filter(pool, selection, &q); - } - } - else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY)) - { - /* special filter case from above */ - int i; - Id f = selection->elements[0] & ~(SOLVER_SELECTMASK|SOLVER_NOAUTOSET); /* job, jobflags, setflags */ - queue_free(selection); - queue_init_clone(selection, &q); - for (i = 0; i < selection->count; i += 2) - selection->elements[i] = (selection->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | f; - } - queue_free(&q); - return ret; + Repo *repo = pool->installed; + limiter->repofilter = repo; + limiter->start = repo ? repo->start : 0; + limiter->end = repo ? repo->end : 0; + } + if ((flags & SELECTION_MODEBITS) != SELECTION_SUBTRACT && (flags & SELECTION_MODEBITS) != SELECTION_FILTER) + return; + /* the result will be limited to the first selection */ + if (!selection->count) + limiter->start = limiter->end = 0; + if (!limiter->end) + return; + /* check for special cases where we do not need to call selection_solvables() */ + if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL) + return; + if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO) + { + Repo *repo = pool_id2repo(pool, selection->elements[1]); + if (limiter->repofilter && repo != limiter->repofilter) + repo = 0; + limiter->repofilter = repo; + limiter->start = repo ? repo->start : 0; + limiter->end = repo ? repo->end : 0; + return; } - return selection_make_matchdeps_common_limited(pool, selection, name, dep, flags, keyname, marker, &limiter); + /* convert selection into a package list and use it in the limiter */ + queue_init(&limiter->qlimit); + selection_solvables(pool, selection, &limiter->qlimit); + limiter->start = 0; + limiter->end = limiter->qlimit.count; + if (!limiter->qlimit.count) + queue_free(&limiter->qlimit); + else + limiter->mapper = limiter->qlimit.elements; +} + +static void +free_limiter(struct limiter *limiter) +{ + if (limiter->mapper) + queue_free(&limiter->qlimit); } /* @@ -1696,7 +1745,12 @@ selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, int selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker) { - return selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker); + struct limiter limiter; + int ret; + setup_limiter(pool, selection, flags, &limiter); + ret = selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker, &limiter); + free_limiter(&limiter); + return ret; } /* @@ -1705,7 +1759,34 @@ selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int fla int selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker) { - return selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker); + struct limiter limiter; + int ret; + setup_limiter(pool, selection, flags, &limiter); + ret = selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker, &limiter); + free_limiter(&limiter); + return ret; +} + +int +selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker) +{ + struct limiter limiter; + int ret; + setup_limiter(pool, selection, flags, &limiter); + ret = selection_make_matchsolvable_common(pool, selection, 0, solvid, flags, keyname, marker, &limiter); + free_limiter(&limiter); + return ret; +} + +int +selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker) +{ + struct limiter limiter; + int ret; + setup_limiter(pool, selection, flags, &limiter); + ret = selection_make_matchsolvable_common(pool, selection, solvidq, 0, flags, keyname, marker, &limiter); + free_limiter(&limiter); + return ret; } static inline int @@ -1742,7 +1823,9 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) for (i = j = 0; i < sel->count; i += 2) { Id select = sel->elements[i] & SOLVER_SELECTMASK; - queue_empty(&q); + Id id = sel->elements[i + 1]; + if (q.count) + queue_empty(&q); miss = 0; if (select == SOLVER_SOLVABLE_ALL) { @@ -1757,7 +1840,7 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) else if (select == SOLVER_SOLVABLE_REPO) { Solvable *s; - Repo *repo = pool_id2repo(pool, sel->elements[i + 1]); + Repo *repo = pool_id2repo(pool, id); if (repo) { FOR_REPO_SOLVABLES(repo, p, s) @@ -1769,9 +1852,18 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) } } } + else if (select == SOLVER_SOLVABLE) + { + if (!map_tst(m, id)) + continue; + sel->elements[j] = sel->elements[i] | setflags; + sel->elements[j + 1] = id; + j += 2; + continue; + } else { - FOR_JOB_SELECT(p, pp, select, sel->elements[i + 1]) + FOR_JOB_SELECT(p, pp, select, id) { if (map_tst(m, p)) queue_pushunique(&q, p); @@ -1784,7 +1876,7 @@ selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags) if (!miss) { sel->elements[j] = sel->elements[i] | setflags; - sel->elements[j + 1] = sel->elements[i + 1]; + sel->elements[j + 1] = id; } else if (q.count > 1) { @@ -1811,6 +1903,7 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) Map m2; Id setflags = 0; + /* handle special cases */ if (!sel1->count || !sel2->count) { if (invert && !sel2->count) @@ -1821,11 +1914,35 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL && !invert) { /* XXX: not 100% correct, but very useful */ - p = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */ + setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */ queue_free(sel1); queue_init_clone(sel1, sel2); for (i = 0; i < sel1->count; i += 2) - sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | p ; + sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | setflags; + return; + } + if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert) + { + Repo *repo = pool_id2repo(pool, sel1->elements[1]); + setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_NOAUTOSET); /* job, jobflags, setflags */ + queue_free(sel1); + queue_init_clone(sel1, sel2); + for (i = 0; i < sel1->count; i += 2) + sel1->elements[i] &= SOLVER_SELECTMASK | SOLVER_SETMASK; /* remove job and jobflags */ + selection_filter_repo(pool, sel1, repo, setflags); + return; + } + if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL) + { + if (invert) + queue_empty(sel1); + return; + } + if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert) + { + Repo *repo = pool_id2repo(pool, sel2->elements[1]); + setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET); + selection_filter_repo(pool, sel1, repo, setflags); return; } @@ -1897,7 +2014,7 @@ selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert) if (invert) map_invertall(&m2); if (sel2->count == 2) - setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET; + setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET); selection_filter_map(pool, sel1, &m2, setflags); map_free(&m2); } diff --git a/src/selection.h b/src/selection.h index 9938c2f..8e60a27 100644 --- a/src/selection.h +++ b/src/selection.h @@ -52,16 +52,19 @@ extern "C" { #define SELECTION_SUBTRACT (2 << 28) #define SELECTION_FILTER (3 << 28) -#define SELECTION_MODEBITS (3 << 28) /* internal */ /* extra SELECTION_FILTER bits */ #define SELECTION_FILTER_KEEP_IFEMPTY (1 << 30) #define SELECTION_FILTER_SWAPPED (1 << 31) +/* internal */ +#define SELECTION_MODEBITS (3 << 28) extern int selection_make(Pool *pool, Queue *selection, const char *name, int flags); extern int selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker); extern int selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker); +extern int selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker); +extern int selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker); extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2); extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2); @@ -51,12 +51,12 @@ * uintXX_t (from inttypes.h), you may need to define things by hand * for your system: */ -typedef struct _SHA256_CTX { +typedef struct s_SHA256_CTX { uint32_t state[8]; uint64_t bitcount; uint32_t buffer[SHA256_BLOCK_LENGTH/4]; } SHA256_CTX; -typedef struct _SHA512_CTX { +typedef struct s_SHA512_CTX { uint64_t state[8]; uint64_t bitcount[2]; uint64_t buffer[SHA512_BLOCK_LENGTH/8]; diff --git a/src/solvable.c b/src/solvable.c index 6f6ba1d..331f290 100644 --- a/src/solvable.c +++ b/src/solvable.c @@ -257,14 +257,14 @@ solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound) return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound); } -unsigned int -solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound) +unsigned long long +solvable_lookup_sizek(Solvable *s, Id keyname, unsigned long long notfound) { unsigned long long size; if (!s->repo) return notfound; - size = solvable_lookup_num(s, keyname, (unsigned long long)notfound << 10); - return (unsigned int)((size + 1023) >> 10); + size = solvable_lookup_num(s, keyname, (unsigned long long)-1); + return size == (unsigned long long)-1 ? notfound : ((size + 1023) >> 10); } int @@ -613,3 +613,67 @@ solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker) queue_free(&q); return i; } + +int +solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff) +{ + Pool *pool = s->repo->pool; + int i, boff; + Id *wp; + + if (depq->count) + queue_empty(depq); + solvable_lookup_deparray(s, keyname, depq, marker); + for (i = 0; i < depq->count; i++) + { + Id dep = depq->elements[i]; + boff = ISRELDEP(dep) ? reloff + GETRELID(dep) : dep; + if (MAPTST(missc, boff)) + continue; + if (ISRELDEP(dep)) + { + Reldep *rd = GETRELDEP(pool, dep); + if (!ISRELDEP(rd->name) && rd->flags < 8) + { + /* do pre-filtering on the base */ + if (MAPTST(missc, rd->name)) + continue; + wp = pool_whatprovides_ptr(pool, rd->name); + if (solvidmap) + { + for (; *wp; wp++) + if (MAPTST(solvidmap, *wp)) + break; + } + else + { + for (; *wp; wp++) + if (*wp == solvid) + break; + } + if (!*wp) + { + /* the base does not include solvid, no need to check the complete dep */ + MAPSET(missc, rd->name); + MAPSET(missc, boff); + continue; + } + } + } + wp = pool_whatprovides_ptr(pool, dep); + if (solvidmap) + { + for (; *wp; wp++) + if (MAPTST(solvidmap, *wp)) + return 1; + } + else + { + for (; *wp; wp++) + if (*wp == solvid) + return 1; + } + MAPSET(missc, boff); + } + return 0; +} diff --git a/src/solvable.h b/src/solvable.h index 090b758..bf92a00 100644 --- a/src/solvable.h +++ b/src/solvable.h @@ -23,15 +23,15 @@ extern "C" { #endif -struct _Repo; +struct s_Repo; -typedef struct _Solvable { +typedef struct s_Solvable { Id name; Id arch; Id evr; /* epoch:version-release */ Id vendor; - struct _Repo *repo; /* repo we belong to */ + struct s_Repo *repo; /* repo we belong to */ /* dependencies are offsets into repo->idarraydata */ Offset provides; /* terminated with Id 0 */ @@ -51,7 +51,7 @@ typedef struct _Solvable { Id solvable_lookup_type(Solvable *s, Id keyname); Id solvable_lookup_id(Solvable *s, Id keyname); unsigned long long solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound); -unsigned int solvable_lookup_sizek(Solvable *s, Id keyname, unsigned int notfound); +unsigned long long solvable_lookup_sizek(Solvable *s, Id keyname, unsigned long long notfound); const char *solvable_lookup_str(Solvable *s, Id keyname); const char *solvable_lookup_str_poollang(Solvable *s, Id keyname); const char *solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase); @@ -79,13 +79,18 @@ void solvable_unset(Solvable *s, Id keyname); int solvable_identical(Solvable *s1, Solvable *s2); Id solvable_selfprovidedep(Solvable *s); + int solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker); +/* internal */ +int solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff); + + /* weird suse stuff */ int solvable_is_irrelevant_patch(Solvable *s, Map *installedmap); int solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap); int solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap); -int solvable_trivial_installable_repo(Solvable *s, struct _Repo *installed, Map *multiversionmap); +int solvable_trivial_installable_repo(Solvable *s, struct s_Repo *installed, Map *multiversionmap); #ifdef __cplusplus } diff --git a/src/solver.c b/src/solver.c index 102d814..a4e0c4b 100644 --- a/src/solver.c +++ b/src/solver.c @@ -431,7 +431,7 @@ propagate(Solver *solv, int level) Id *decisionmap = solv->decisionmap; Id *watches = solv->watches + pool->nsolvables; /* place ptr in middle */ - POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate level %d -----\n", level); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate -----\n"); /* foreach non-propagated decision */ while (solv->propagate_index < solv->decisionq.count) @@ -444,7 +444,7 @@ propagate(Solver *solv, int level) IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE) { - POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagate decision %d:", -pkg); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "propagate for decision %d level %d\n", -pkg, level); solver_printruleelement(solv, SOLV_DEBUG_PROPAGATE, 0, -pkg); } @@ -462,10 +462,10 @@ propagate(Solver *solv, int level) continue; } - IF_POOLDEBUG (SOLV_DEBUG_WATCHES) + IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE) { - POOL_DEBUG(SOLV_DEBUG_WATCHES, " watch triggered "); - solver_printrule(solv, SOLV_DEBUG_WATCHES, r); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE," watch triggered "); + solver_printrule(solv, SOLV_DEBUG_PROPAGATE, r); } /* @@ -532,12 +532,12 @@ propagate(Solver *solv, int level) * if we found some p that is UNDEF or TRUE, move * watch to it */ - IF_POOLDEBUG (SOLV_DEBUG_WATCHES) + IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE) { if (p > 0) - POOL_DEBUG(SOLV_DEBUG_WATCHES, " -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p)); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, p)); else - POOL_DEBUG(SOLV_DEBUG_WATCHES, " -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p)); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE, " -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), pool_solvid2str(pool, -p)); } *rp = *next_rp; @@ -593,7 +593,7 @@ propagate(Solver *solv, int level) } /* while we have non-decided decisions */ - POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate end -----\n"); + POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "----- propagate end-----\n"); return 0; /* all is well */ } @@ -1790,69 +1790,6 @@ resolve_installed(Solver *solv, int level, int disablerules, Queue *dq) return level; } -/* one or more installed cleandeps packages in dq that are to be updated */ -/* we need to emulate the code in resolve_installed */ -static void -do_cleandeps_update_filter(Solver *solv, Queue *dq) -{ - Pool *pool = solv->pool; - Repo *installed = solv->installed; - Id *specialupdaters = solv->specialupdaters; - Id p, p2, pp, d; - Queue q; - int i, j, k; - - queue_init(&q); - for (i = 0; i < dq->count; i++) - { - Id p = dq->elements[i]; - if (p < 0) - p = -p; - if (pool->solvables[p].repo != installed || !MAPTST(&solv->cleandepsmap, p - installed->start)) - continue; - queue_empty(&q); - /* find updaters */ - if (specialupdaters && (d = specialupdaters[p - installed->start]) != 0) - { - while ((p2 = pool->whatprovidesdata[d++]) != 0) - if (solv->decisionmap[p2] >= 0) - queue_push(&q, p2); - } - else - { - Rule *r = solv->rules + solv->updaterules + (p - installed->start); - if (r->p) - { - FOR_RULELITERALS(p2, pp, r) - if (solv->decisionmap[p2] >= 0) - queue_push(&q, p2); - } - } - if (q.count && solv->update_targets && solv->update_targets->elements[p - installed->start]) - prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[p - installed->start], &q); - /* mark all elements in dq that are in the updaters list */ - dq->elements[i] = -p; - for (j = 0; j < dq->count; j++) - { - p = dq->elements[j]; - if (p < 0) - continue; - for (k = 0; k < q.count; k++) - if (q.elements[k] == p) - { - dq->elements[j] = -p; - break; - } - } - } - /* now prune to marked elements */ - for (i = j = 0; i < dq->count; i++) - if ((p = dq->elements[i]) < 0) - dq->elements[j++] = -p; - dq->count = j; - queue_free(&q); -} - static int resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq) { @@ -1880,8 +1817,6 @@ resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq) } if (i == solv->nrules) i = 1; - if (solv->focus_best && solv->do_extra_reordering && i >= solv->featurerules) - continue; r = solv->rules + i; if (r->d < 0) /* ignore disabled rules */ continue; @@ -1950,25 +1885,15 @@ resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq) /* prune to cleandeps packages */ if (solv->cleandepsmap.size && solv->installed) { - int cleandeps_update = 0; Repo *installed = solv->installed; for (j = 0; j < dq->count; j++) if (pool->solvables[dq->elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq->elements[j] - installed->start)) - { - if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - installed->start))) - { - cleandeps_update = 1; /* cleandeps package is marked for update */ - continue; - } - break; - } + break; if (j < dq->count) { dq->elements[0] = dq->elements[j]; queue_truncate(dq, 1); } - else if (cleandeps_update) - do_cleandeps_update_filter(solv, dq); /* special update filter */ } if (dq->count > 1 && postponed >= 0) @@ -3032,7 +2957,9 @@ add_update_target(Solver *solv, Id p, Id how) Pool *pool = solv->pool; Solvable *s = pool->solvables + p; Repo *installed = solv->installed; - Id pi, pip; + Id pi, pip, identicalp; + int startcnt, endcnt; + if (!solv->update_targets) { solv->update_targets = solv_calloc(1, sizeof(Queue)); @@ -3043,6 +2970,8 @@ add_update_target(Solver *solv, Id p, Id how) queue_push2(solv->update_targets, p, p); return; } + identicalp = 0; + startcnt = solv->update_targets->count; FOR_PROVIDES(pi, pip, s->name) { Solvable *si = pool->solvables + pi; @@ -3057,9 +2986,9 @@ add_update_target(Solver *solv, Id p, Id how) if (how & SOLVER_CLEANDEPS) add_cleandeps_updatepkg(solv, pi); queue_push2(solv->update_targets, pi, p); - /* check if it's ok to keep the installed package */ + /* remember an installed package that is identical to p */ if (s->evr == si->evr && solvable_identical(s, si)) - queue_push2(solv->update_targets, pi, pi); + identicalp = pi; } if (s->obsoletes) { @@ -3089,6 +3018,12 @@ add_update_target(Solver *solv, Id p, Id how) } } } + /* also allow upgrading to an identical installed package */ + if (identicalp) + { + for (endcnt = solv->update_targets->count; startcnt < endcnt; startcnt += 2) + queue_push2(solv->update_targets, solv->update_targets->elements[startcnt], identicalp); + } } static int @@ -3308,7 +3243,6 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_STATS, "solver started\n"); POOL_DEBUG(SOLV_DEBUG_STATS, "dosplitprovides=%d, noupdateprovide=%d, noinfarchcheck=%d\n", solv->dosplitprovides, solv->noupdateprovide, solv->noinfarchcheck); POOL_DEBUG(SOLV_DEBUG_STATS, "allowuninstall=%d, allowdowngrade=%d, allownamechange=%d, allowarchchange=%d, allowvendorchange=%d\n", solv->allowuninstall, solv->allowdowngrade, solv->allownamechange, solv->allowarchchange, solv->allowvendorchange); - POOL_DEBUG(SOLV_DEBUG_STATS, "dupallowdowngrade=%d, dupallownamechange=%d, dupallowarchchange=%d, dupallowvendorchange=%d\n", solv->dup_allowdowngrade, solv->dup_allownamechange, solv->dup_allowarchchange, solv->dup_allowvendorchange); POOL_DEBUG(SOLV_DEBUG_STATS, "promoteepoch=%d, forbidselfconflicts=%d\n", pool->promoteepoch, pool->forbidselfconflicts); POOL_DEBUG(SOLV_DEBUG_STATS, "obsoleteusesprovides=%d, implicitobsoleteusesprovides=%d, obsoleteusescolors=%d, implicitobsoleteusescolors=%d\n", pool->obsoleteusesprovides, pool->implicitobsoleteusesprovides, pool->obsoleteusescolors, pool->implicitobsoleteusescolors); POOL_DEBUG(SOLV_DEBUG_STATS, "dontinstallrecommended=%d, addalreadyrecommended=%d\n", solv->dontinstallrecommended, solv->addalreadyrecommended); @@ -3812,10 +3746,6 @@ solver_solve(Solver *solv, Queue *job) name_s = s; } solver_addjobrule(solv, -p, 0, 0, i, weak); -#ifdef ENABLE_LINKED_PKGS - if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1) - solver_addjobrule(solv, -solv->instbuddy[p - installed->start], 0, 0, i, weak); -#endif } /* special case for "erase a specific solvable": we also * erase all other solvables with that name, so that they @@ -3883,14 +3813,7 @@ solver_solve(Solver *solv, Queue *job) } } FOR_JOB_SELECT(p, pp, select, what) - { - s = pool->solvables + p; - solver_addjobrule(solv, installed && s->repo == installed ? p : -p, 0, 0, i, weak); -#ifdef ENABLE_LINKED_PKGS - if (solv->instbuddy && installed && s->repo == installed && solv->instbuddy[p - installed->start] > 1) - solver_addjobrule(solv, solv->instbuddy[p - installed->start], 0, 0, i, weak); -#endif - } + solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak); break; case SOLVER_DISTUPGRADE: POOL_DEBUG(SOLV_DEBUG_JOB, "job: distupgrade %s\n", solver_select2str(pool, select, what)); diff --git a/src/solver.h b/src/solver.h index ebb2232..4c85b4d 100644 --- a/src/solver.h +++ b/src/solver.h @@ -26,11 +26,11 @@ extern "C" { #endif -struct _Solver { +struct s_Solver { Pool *pool; /* back pointer to pool */ Queue job; /* copy of the job we're solving */ - int (*solution_callback)(struct _Solver *solv, void *data); + int (*solution_callback)(struct s_Solver *solv, void *data); void *solution_callback_data; int pooljobcnt; /* number of pooljob entries in job queue */ @@ -211,7 +211,7 @@ struct _Solver { #endif /* LIBSOLV_INTERNAL */ }; -typedef struct _Solver Solver; +typedef struct s_Solver Solver; /* * queue commands diff --git a/src/strpool.h b/src/strpool.h index f96c5c1..fd13bdb 100644 --- a/src/strpool.h +++ b/src/strpool.h @@ -17,7 +17,7 @@ extern "C" { #define STRID_NULL 0 #define STRID_EMPTY 1 -struct _Stringpool +struct s_Stringpool { Offset *strings; /* table of offsets into stringspace, indexed by Id: Id -> Offset */ int nstrings; /* number of ids in strings table */ diff --git a/src/transaction.c b/src/transaction.c index 9a32966..4a4189e 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -828,11 +828,11 @@ transaction_make_installedmap(Transaction *trans, Map *installedmap) } } -int +long long transaction_calc_installsizechange(Transaction *trans) { Map installedmap; - int change; + long long change; transaction_make_installedmap(trans, &installedmap); change = pool_calc_installsizechange(trans->pool, &installedmap); diff --git a/src/transaction.h b/src/transaction.h index c840838..5b01354 100644 --- a/src/transaction.h +++ b/src/transaction.h @@ -21,12 +21,12 @@ extern "C" { #endif -struct _Pool; -struct _DUChanges; -struct _TransactionOrderdata; +struct s_Pool; +struct s_DUChanges; +struct s_TransactionOrderdata; -typedef struct _Transaction { - struct _Pool *pool; /* back pointer to pool */ +typedef struct s_Transaction { + struct s_Pool *pool; /* back pointer to pool */ Queue steps; /* the transaction steps */ @@ -36,7 +36,7 @@ typedef struct _Transaction { Map transactsmap; Map multiversionmap; - struct _TransactionOrderdata *orderdata; + struct s_TransactionOrderdata *orderdata; #endif } Transaction; @@ -92,8 +92,8 @@ typedef struct _Transaction { #define SOLVER_ORDERCYCLE_NORMAL 1 #define SOLVER_ORDERCYCLE_CRITICAL 2 -extern Transaction *transaction_create(struct _Pool *pool); -extern Transaction *transaction_create_decisionq(struct _Pool *pool, Queue *decisionq, Map *multiversionmap); +extern Transaction *transaction_create(struct s_Pool *pool); +extern Transaction *transaction_create_decisionq(struct s_Pool *pool, Queue *decisionq, Map *multiversionmap); extern Transaction *transaction_create_clone(Transaction *srctrans); extern void transaction_free(Transaction *trans); @@ -115,8 +115,8 @@ extern void transaction_classify_pkgs(Transaction *trans, int mode, Id type, Id packages is returned */ extern int transaction_installedresult(Transaction *trans, Queue *installedq); -int transaction_calc_installsizechange(Transaction *trans); -void transaction_calc_duchanges(Transaction *trans, struct _DUChanges *mps, int nmps); +long long transaction_calc_installsizechange(Transaction *trans); +void transaction_calc_duchanges(Transaction *trans, struct s_DUChanges *mps, int nmps); diff --git a/test/testcases/allowuninstall/conflict.t b/test/testcases/allowuninstall/conflict.t deleted file mode 100644 index a66d322..0000000 --- a/test/testcases/allowuninstall/conflict.t +++ /dev/null @@ -1,14 +0,0 @@ -repo system 0 testtags <inline> -#>=Pkg: a 1 1 noarch -#>=Con: b -repo available 0 testtags <inline> -#>=Pkg: b 1 1 noarch - -system x86_64 rpm system -solverflags allowuninstall -disable pkg a-1-1.noarch@system -job install name b -result transaction,problems <inline> -#>problem a658cbaf info package a-1-1.noarch conflicts with b provided by b-1-1.noarch -#>problem a658cbaf solution 567aa15d erase a-1-1.noarch@system -#>problem a658cbaf solution e98e1a37 deljob install name b diff --git a/test/testcases/allowuninstall/forcebest.t b/test/testcases/allowuninstall/forcebest.t deleted file mode 100644 index 38ade6f..0000000 --- a/test/testcases/allowuninstall/forcebest.t +++ /dev/null @@ -1,19 +0,0 @@ -repo system 0 testtags <inline> -#>=Pkg: a 1 1 noarch -#>=Req: b = 1-1 -#>=Pkg: b 1 1 noarch -repo available 0 testtags <inline> -#>=Pkg: a 2 1 noarch -#>=Req: b = 2-1 -#>=Pkg: b 2 1 noarch - -system x86_64 rpm system -disable pkg b-1-1.noarch@system -disable pkg b-2-1.noarch@available -job allowuninstall pkg a-1-1.noarch@system -job allowuninstall pkg b-1-1.noarch@system -job update name a [forcebest] -result transaction,problems <inline> -#>problem e6d3911d info nothing provides b = 2-1 needed by a-2-1.noarch -#>problem e6d3911d solution 0011b04f allow a-1-1.noarch@system -#>problem e6d3911d solution 44d189a0 erase a-1-1.noarch@system diff --git a/test/testcases/cleandeps/cleandeps_up3.t b/test/testcases/cleandeps/cleandeps_up3.t deleted file mode 100644 index 7a4bfbc..0000000 --- a/test/testcases/cleandeps/cleandeps_up3.t +++ /dev/null @@ -1,23 +0,0 @@ -repo system 0 testtags <inline> -#>=Pkg: a 1 1 x86_64 -#>=Req: b -#>=Pkg: b 1 1 x86_64 -repo available 0 testtags <inline> -#>=Pkg: a 2 1 x86_64 -#>=Req: b -#>=Pkg: b 2 1 x86_64 -#>=Pkg: c 2 1 x86_64 -#>=Prv: b = 4 -repo available2 0 testtags <inline> -#>=Pkg: b 3 1 x86_64 -system x86_64 rpm system - -job update all packages [cleandeps] -result transaction,problems <inline> -#>upgrade a-1-1.x86_64@system a-2-1.x86_64@available -#>upgrade b-1-1.x86_64@system b-3-1.x86_64@available2 -nextjob -job update repo available [cleandeps] -result transaction,problems <inline> -#>upgrade a-1-1.x86_64@system a-2-1.x86_64@available -#>upgrade b-1-1.x86_64@system b-2-1.x86_64@available diff --git a/test/testcases/selection/selection_matchsolvable.t b/test/testcases/selection/selection_matchsolvable.t new file mode 100644 index 0000000..545abc4 --- /dev/null +++ b/test/testcases/selection/selection_matchsolvable.t @@ -0,0 +1,27 @@ +repo available 0 testtags <inline> +#>=Pkg: A1 1 1 noarch +#>=Req: B > 1 + B < 3 +#>=Pkg: A2 1 1 noarch +#>=Req: B > 1 & B < 3 +#>=Pkg: X 1 1 noarch +#>=Prv: B = 4 +#>=Pkg: Y 1 1 noarch +#>=Prv: B = 2 +#>=Pkg: A1 2 1 noarch +system i686 rpm + +job noop selection_matchsolvable solvable:requires X-1-1.noarch@available flat +result jobs <inline> +#>job noop pkg A2-1-1.noarch@available [noautoset] + +nextjob +job noop selection_matchsolvable solvable:requires Y-1-1.noarch@available flat +result jobs <inline> +#>job noop oneof A1-1-1.noarch@available A2-1-1.noarch@available + +nextjob +job noop selection A1 name +job noop selection_matchsolvable solvable:requires Y-1-1.noarch@available flat,filter +result jobs <inline> +#>job noop pkg A1-1-1.noarch@available [noautoset] + diff --git a/tools/appdata2solv.c b/tools/appdata2solv.c index ce6c98c..e5a42cf 100644 --- a/tools/appdata2solv.c +++ b/tools/appdata2solv.c @@ -70,7 +70,7 @@ main(int argc, char **argv) exit(1); } } - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/archpkgs2solv.c b/tools/archpkgs2solv.c index 4ce95a4..14c3ba4 100644 --- a/tools/archpkgs2solv.c +++ b/tools/archpkgs2solv.c @@ -57,16 +57,12 @@ main(int argc, char **argv) Repo *repo; FILE *fp; char buf[4096], *p; - const char *basefile = 0; int flags = 0; - while ((c = getopt(argc, argv, "0b:m:i")) >= 0) + while ((c = getopt(argc, argv, "0:m:i")) >= 0) { switch(c) { - case 'b': - basefile = optarg; - break; case 'm': manifest = optarg; break; @@ -124,7 +120,7 @@ main(int argc, char **argv) res = 1; } repo_internalize(repo); - tool_write(repo, basefile, 0); + tool_write(repo, stdout); pool_free(pool); for (c = 0; c < npkgs; c++) solv_free((char *)pkgs[c]); diff --git a/tools/archrepo2solv.c b/tools/archrepo2solv.c index 5f8eade..e60960f 100644 --- a/tools/archrepo2solv.c +++ b/tools/archrepo2solv.c @@ -73,7 +73,7 @@ main(int argc, char **argv) fprintf(stderr, "archrepo2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/common_write.c b/tools/common_write.c index 577b1ab..36f8dd8 100644 --- a/tools/common_write.c +++ b/tools/common_write.c @@ -21,322 +21,51 @@ * 1.1: changed PRODUCT_ENDOFLIFE parsing */ -static Id verticals[] = { - SOLVABLE_AUTHORS, - SOLVABLE_DESCRIPTION, - SOLVABLE_MESSAGEDEL, - SOLVABLE_MESSAGEINS, - SOLVABLE_EULA, - SOLVABLE_DISKUSAGE, - SOLVABLE_FILELIST, - SOLVABLE_CHANGELOG_AUTHOR, - SOLVABLE_CHANGELOG_TEXT, - 0 -}; - -static char *languagetags[] = { - "solvable:summary:", - "solvable:description:", - "solvable:messageins:", - "solvable:messagedel:", - "solvable:eula:", - 0 -}; - -static int test_separate = 0; - -struct keyfilter_data { - char **languages; - int nlanguages; - int haveaddedfileprovides; - int haveexternal; -}; - static int -keyfilter_solv(Repo *data, Repokey *key, void *kfdata) +keyfilter_solv(Repo *repo, Repokey *key, void *kfdata) { - struct keyfilter_data *kd = kfdata; - int i; - const char *keyname; - - if (test_separate && key->storage != KEY_STORAGE_SOLVABLE) - return KEY_STORAGE_DROPPED; - if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES) - return KEY_STORAGE_DROPPED; - if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL) - return KEY_STORAGE_DROPPED; if (key->name == SUSETAGS_SHARE_NAME || key->name == SUSETAGS_SHARE_EVR || key->name == SUSETAGS_SHARE_ARCH) return KEY_STORAGE_DROPPED; - for (i = 0; verticals[i]; i++) - if (key->name == verticals[i]) - return KEY_STORAGE_VERTICAL_OFFSET; - keyname = pool_id2str(data->pool, key->name); - for (i = 0; languagetags[i] != 0; i++) - if (!strncmp(keyname, languagetags[i], strlen(languagetags[i]))) - return KEY_STORAGE_VERTICAL_OFFSET; - return KEY_STORAGE_INCORE; -} - -static int -keyfilter_attr(Repo *data, Repokey *key, void *kfdata) -{ - int i; - const char *keyname; - if (key->storage == KEY_STORAGE_SOLVABLE) - return KEY_STORAGE_DROPPED; - /* those must only be in the main solv file */ - if (key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_TOOLVERSION) - return KEY_STORAGE_DROPPED; - for (i = 0; verticals[i]; i++) - if (key->name == verticals[i]) - return KEY_STORAGE_VERTICAL_OFFSET; - keyname = pool_id2str(data->pool, key->name); - for (i = 0; languagetags[i] != 0; i++) - if (!strncmp(keyname, languagetags[i], strlen(languagetags[i]))) - return KEY_STORAGE_VERTICAL_OFFSET; - return KEY_STORAGE_INCORE; -} - -static int -keyfilter_language(Repo *repo, Repokey *key, void *kfdata) -{ - Pool *pool = repo->pool; - const char *name, *p; - char *lang = kfdata; - int i; - - name = pool_id2str(repo->pool, key->name); - p = strrchr(name, ':'); - if (!p || strcmp(p + 1, lang) != 0) - return KEY_STORAGE_DROPPED; - for (i = 0; verticals[i]; i++) - { - const char *vname = pool_id2str(pool, verticals[i]); - if (!strncmp(name, vname, p - name) && vname[p - name] == 0) - return KEY_STORAGE_VERTICAL_OFFSET; - } - return KEY_STORAGE_INCORE; -} - -static int -keyfilter_DU(Repo *repo, Repokey *key, void *kfdata) -{ - int i; - if (key->name != SOLVABLE_DISKUSAGE) - return KEY_STORAGE_DROPPED; - for (i = 0; verticals[i]; i++) - if (key->name == verticals[i]) - return KEY_STORAGE_VERTICAL_OFFSET; - return KEY_STORAGE_INCORE; -} - -static int -keyfilter_FL(Repo *repo, Repokey *key, void *kfdata) -{ - int i; - if (key->name != SOLVABLE_FILELIST) - return KEY_STORAGE_DROPPED; - for (i = 0; verticals[i]; i++) - if (key->name == verticals[i]) - return KEY_STORAGE_VERTICAL_OFFSET; - return KEY_STORAGE_INCORE; -} - -static int -keyfilter_other(Repo *repo, Repokey *key, void *kfdata) -{ - const char *name, *p; - struct keyfilter_data *kd = kfdata; - int i; - - if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES) - return KEY_STORAGE_DROPPED; - if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL) - return KEY_STORAGE_DROPPED; - - if (key->name == SOLVABLE_FILELIST || key->name == SOLVABLE_DISKUSAGE) - return KEY_STORAGE_DROPPED; - - name = pool_id2str(repo->pool, key->name); - p = strrchr(name, ':'); - if (p) - { - for (i = 0; i < kd->nlanguages; i++) - if (!strcmp(p + 1, kd->languages[i])) - return KEY_STORAGE_DROPPED; - } - for (i = 0; verticals[i]; i++) - if (key->name == verticals[i]) - return KEY_STORAGE_VERTICAL_OFFSET; - return KEY_STORAGE_INCORE; + return repo_write_stdkeyfilter(repo, key, kfdata); } /* - * Write <repo> to stdout - * If <attrname> is given, write attributes to <attrname> - * If <basename> is given, split attributes + * Write <repo> to fp */ - -#define REPODATAFILE_BLOCK 15 - -static void -write_info(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodata *info, const char *location) -{ - Id h; - Queue keyq; - - queue_init(&keyq); - if (repo_write_filtered(repo, fp, keyfilter, kfdata, &keyq) != 0) - { - fprintf(stderr, "repo_write failed\n"); - exit(1); - } - h = repodata_new_handle(info); - if (keyq.count) - repodata_set_idarray(info, h, REPOSITORY_KEYS, &keyq); - queue_free(&keyq); - repodata_set_str(info, h, REPOSITORY_LOCATION, location); - repodata_add_flexarray(info, SOLVID_META, REPOSITORY_EXTERNAL, h); -} - void -tool_write(Repo *repo, const char *basename, const char *attrname) +tool_write(Repo *repo, FILE *fp) { - Repodata *data; - Repodata *info = 0; - Repokey *key; - char **languages = 0; - int nlanguages = 0; - int i, j, k, l; - struct keyfilter_data kd; + Repodata *info; Queue addedfileprovides; + Repowriter *writer; - memset(&kd, 0, sizeof(kd)); - info = repo_add_repodata(repo, 0); + info = repo_add_repodata(repo, 0); /* add new repodata for our meta info */ repodata_set_str(info, SOLVID_META, REPOSITORY_TOOLVERSION, LIBSOLV_TOOLVERSION); + repodata_unset(info, SOLVID_META, REPOSITORY_EXTERNAL); /* do not propagate this */ + queue_init(&addedfileprovides); pool_addfileprovides_queue(repo->pool, &addedfileprovides, 0); if (addedfileprovides.count) - { - kd.haveaddedfileprovides = 1; - repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides); - } + repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides); + else + repodata_unset(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES); queue_free(&addedfileprovides); pool_freeidhashes(repo->pool); /* free some mem */ - if (basename) - { - char fn[4096]; - FILE *fp; - int has_DU = 0; - int has_FL = 0; - - /* find languages and other info */ - FOR_REPODATAS(repo, i, data) - { - for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++) - { - const char *keyname = pool_id2str(repo->pool, key->name); - if (key->name == SOLVABLE_DISKUSAGE) - has_DU = 1; - if (key->name == SOLVABLE_FILELIST) - has_FL = 1; - for (k = 0; languagetags[k] != 0; k++) - if (!strncmp(keyname, languagetags[k], strlen(languagetags[k]))) - break; - if (!languagetags[k]) - continue; - l = strlen(languagetags[k]); - if (strlen(keyname + l) > 5) - continue; - for (k = 0; k < nlanguages; k++) - if (!strcmp(languages[k], keyname + l)) - break; - if (k < nlanguages) - continue; - languages = solv_realloc2(languages, nlanguages + 1, sizeof(char *)); - languages[nlanguages++] = strdup(keyname + l); - } - } - /* write language subfiles */ - for (i = 0; i < nlanguages; i++) - { - sprintf(fn, "%s.%s.solv", basename, languages[i]); - if (!(fp = fopen(fn, "w"))) - { - perror(fn); - exit(1); - } - write_info(repo, fp, keyfilter_language, languages[i], info, fn); - fclose(fp); - kd.haveexternal = 1; - } - /* write DU subfile */ - if (has_DU) - { - sprintf(fn, "%s.DU.solv", basename); - if (!(fp = fopen(fn, "w"))) - { - perror(fn); - exit(1); - } - write_info(repo, fp, keyfilter_DU, 0, info, fn); - fclose(fp); - kd.haveexternal = 1; - } - /* write filelist */ - if (has_FL) - { - sprintf(fn, "%s.FL.solv", basename); - if (!(fp = fopen(fn, "w"))) - { - perror(fn); - exit(1); - } - write_info(repo, fp, keyfilter_FL, 0, info, fn); - fclose(fp); - kd.haveexternal = 1; - } - /* write everything else */ - sprintf(fn, "%s.solv", basename); - if (!(fp = fopen(fn, "w"))) - { - perror(fn); - exit(1); - } - kd.languages = languages; - kd.nlanguages = nlanguages; - repodata_internalize(info); - if (repo_write_filtered(repo, fp, keyfilter_other, &kd, 0) != 0) - { - fprintf(stderr, "repo_write failed\n"); - exit(1); - } - if (fclose(fp) != 0) - { - perror("fclose"); - exit(1); - } - for (i = 0; i < nlanguages; i++) - free(languages[i]); - solv_free(languages); - repodata_free(info); - } - if (attrname) + repodata_internalize(info); + writer = repowriter_create(repo); + repowriter_set_keyfilter(writer, keyfilter_solv, 0); + if (repowriter_write(writer, fp) != 0) { - FILE *fp; - test_separate = 1; - fp = fopen(attrname, "w"); - write_info(repo, fp, keyfilter_attr, 0, info, attrname); - fclose(fp); - kd.haveexternal = 1; + fprintf(stderr, "repo write failed: %s\n", pool_errstr(repo->pool)); + exit(1); } - repodata_internalize(info); - if (repo_write_filtered(repo, stdout, keyfilter_solv, &kd, 0) != 0) + if (fflush(fp)) { - fprintf(stderr, "repo_write failed\n"); + perror("fflush"); exit(1); } - repodata_free(info); + repowriter_free(writer); + repodata_free(info); /* delete meta info repodata again */ } diff --git a/tools/common_write.h b/tools/common_write.h index 7630edd..fda1fd5 100644 --- a/tools/common_write.h +++ b/tools/common_write.h @@ -10,6 +10,6 @@ #include "repo.h" -void tool_write(Repo *repo, const char *basename, const char *attrname); +void tool_write(Repo *repo, FILE *fp); #endif diff --git a/tools/comps2solv.c b/tools/comps2solv.c index cdbcf74..ebb39b5 100644 --- a/tools/comps2solv.c +++ b/tools/comps2solv.c @@ -34,7 +34,7 @@ main(int argc, char **argv) fprintf(stderr, "comps2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/deb2solv.c b/tools/deb2solv.c index 63b6839..ad27541 100644 --- a/tools/deb2solv.c +++ b/tools/deb2solv.c @@ -60,13 +60,10 @@ main(int argc, char **argv) const char *basefile = 0; int is_repo = 0; - while ((c = getopt(argc, argv, "0b:m:r")) >= 0) + while ((c = getopt(argc, argv, "0:m:r")) >= 0) { switch(c) { - case 'b': - basefile = optarg; - break; case 'm': manifest = optarg; break; @@ -150,7 +147,7 @@ main(int argc, char **argv) } } repo_internalize(repo); - tool_write(repo, basefile, 0); + tool_write(repo, stdout); pool_free(pool); for (c = 0; c < ndebs; c++) free((char *)debs[c]); diff --git a/tools/deltainfoxml2solv.c b/tools/deltainfoxml2solv.c index 7d6348f..906b3ad 100644 --- a/tools/deltainfoxml2solv.c +++ b/tools/deltainfoxml2solv.c @@ -20,10 +20,9 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "deltainfoxml2solv [-a][-h][-n <attrname>]\n" + "deltainfoxml2solv [-h]\n" " reads a 'deltainfo.xml' file from <stdin> and writes a .solv file to <stdout>\n" " -h : print help & exit\n" - " -n <name>: save attributes as <name>.attr\n" ); exit(status); } @@ -32,21 +31,17 @@ int main(int argc, char **argv) { int c, flags = 0; - char *attrname = 0; Pool *pool = pool_create(); Repo *repo = repo_create(pool, "<stdin>"); - while ((c = getopt(argc, argv, "hn:")) >= 0) + while ((c = getopt(argc, argv, "h")) >= 0) { switch(c) { case 'h': usage(0); break; - case 'n': - attrname = optarg; - break; default: usage(1); break; @@ -57,7 +52,7 @@ main(int argc, char **argv) fprintf(stderr, "deltainfoxml2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, attrname); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/diskusagexml2solv.c b/tools/diskusagexml2solv.c index 59ac79a..850b02c 100644 --- a/tools/diskusagexml2solv.c +++ b/tools/diskusagexml2solv.c @@ -22,10 +22,9 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "diskusagexml2solv [-a][-h][-n <attrname>]\n" + "diskusagexml2solv [-h]\n" " reads a 'diskusage.xml' file from <stdin> and writes a .solv file to <stdout>\n" " -h : print help & exit\n" - " -n <name>: save attributes as <name>.attr\n" ); exit(status); } @@ -34,21 +33,17 @@ int main(int argc, char **argv) { int c, flags = 0; - char *attrname = 0; Pool *pool = pool_create(); Repo *repo = repo_create(pool, "<stdin>"); - while ((c = getopt(argc, argv, "hn:")) >= 0) + while ((c = getopt(argc, argv, "h")) >= 0) { switch(c) { case 'h': usage(0); break; - case 'n': - attrname = optarg; - break; default: usage(1); break; @@ -59,7 +54,7 @@ main(int argc, char **argv) fprintf(stderr, "diskusagexml2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, attrname); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/dumpsolv.c b/tools/dumpsolv.c index 1aaee16..bdd521e 100644 --- a/tools/dumpsolv.c +++ b/tools/dumpsolv.c @@ -54,7 +54,6 @@ dump_attr(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv) case REPOKEY_TYPE_VOID: printf("%s: (void)\n", keyname); break; - case REPOKEY_TYPE_U32: case REPOKEY_TYPE_CONSTANT: printf("%s: %u\n", keyname, kv->num); break; @@ -225,7 +224,6 @@ dump_attr_json(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv, struct cb case REPOKEY_TYPE_VOID: printf("null"); break; - case REPOKEY_TYPE_U32: case REPOKEY_TYPE_CONSTANT: printf("%u", kv->num); break; diff --git a/tools/helix2solv.c b/tools/helix2solv.c index 04c6b48..8ab531e 100644 --- a/tools/helix2solv.c +++ b/tools/helix2solv.c @@ -33,7 +33,7 @@ main(int argc, char **argv) fprintf(stderr, "helix2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/mdk2solv.c b/tools/mdk2solv.c index bd77fb7..3a6cf94 100644 --- a/tools/mdk2solv.c +++ b/tools/mdk2solv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Novell Inc. + * Copyright (c) 2012, Novell Inc.); * * This program is licensed under the BSD license, read LICENSE.BSD * for further information @@ -104,7 +104,7 @@ main(int argc, char **argv) fclose(fp); } repo_internalize(repo); - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/mergesolv.c b/tools/mergesolv.c index ae6e163..8746ac6 100644 --- a/tools/mergesolv.c +++ b/tools/mergesolv.c @@ -60,7 +60,6 @@ main(int argc, char **argv) { Pool *pool; Repo *repo; - const char *basefile = 0; int with_attr = 0; #ifdef SUSE int add_auto = 0; @@ -70,7 +69,7 @@ main(int argc, char **argv) pool = pool_create(); repo = repo_create(pool, "<mergesolv>"); - while ((c = getopt(argc, argv, "ahb:X")) >= 0) + while ((c = getopt(argc, argv, "ahX")) >= 0) { switch (c) { @@ -80,9 +79,6 @@ main(int argc, char **argv) case 'a': with_attr = 1; break; - case 'b': - basefile = optarg; - break; case 'X': #ifdef SUSE add_auto = 1; @@ -115,7 +111,7 @@ main(int argc, char **argv) if (add_auto) repo_add_autopattern(repo, 0); #endif - tool_write(repo, basefile, 0); + tool_write(repo, stdout); pool_free(pool); return 0; } diff --git a/tools/repo2solv.c b/tools/repo2solv.c index ece4225..d5b3328 100644 --- a/tools/repo2solv.c +++ b/tools/repo2solv.c @@ -169,9 +169,9 @@ read_plaindir_repo(Repo *repo, const char *dir) close(fds[1]); } if (recursive) - execl("/usr/bin/find", "/usr/bin/find", ".", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0); + execl("/usr/bin/find", ".", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0); else - execl("/usr/bin/find", "/usr/bin/find", ".", "-maxdepth", "1", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0); + execl("/usr/bin/find", ".", "-maxdepth", "1", "-name", ".", "-o", "-name", ".*", "-prune", "-o", "-name", "*.delta.rpm", "-o", "-name", "*.patch.rpm", "-o", "-name", "*.rpm", "-a", "-type", "f", "-print0", (char *)0); perror("/usr/bin/find"); _exit(1); } @@ -208,7 +208,6 @@ read_plaindir_repo(Repo *repo, const char *dir) repodata_set_location(data, p, 0, 0, bp[0] == '.' && bp[1] == '/' ? bp + 2 : bp); solv_free(rpm); } - solv_free(buf); fclose(fp); while (waitpid(pid, &wstatus, 0) == -1) { @@ -828,12 +827,7 @@ main(int argc, char **argv) if (add_auto) repo_add_autopattern(repo, 0); #endif - tool_write(repo, 0, 0); - if (fflush(stdout)) - { - perror("fflush"); - exit(1); - } + tool_write(repo, stdout); pool_free(pool); solv_free(dir); exit(res); diff --git a/tools/repomdxml2solv.c b/tools/repomdxml2solv.c index e3159de..fdf7666 100644 --- a/tools/repomdxml2solv.c +++ b/tools/repomdxml2solv.c @@ -115,7 +115,7 @@ main(int argc, char **argv) if (query) doquery(pool, repo, query); else - tool_write(repo, 0, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/rpmdb2solv.c b/tools/rpmdb2solv.c index 9fa8580..58ef567 100644 --- a/tools/rpmdb2solv.c +++ b/tools/rpmdb2solv.c @@ -41,14 +41,11 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "rpmdb2solv [-P] [-C] [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n" + "rpmdb2solv [-n] [-b <basefile>] [-p <productsdir>] [-r <root>]\n" " -n : No packages, do not read rpmdb, useful to only parse products\n" - " -b <basefile> : Write .solv to <basefile>.solv instead of stdout\n" " -p <productsdir> : Scan <productsdir> for .prod files, representing installed products\n" " -r <root> : Prefix rpmdb path and <productsdir> with <root>\n" " -o <solv> : Write .solv to file instead of stdout\n" - " -P : print percentage done\n" - " -C : include the changelog\n" ); exit(status); } @@ -65,7 +62,6 @@ main(int argc, char **argv) int nopacks = 0; int add_changelog = 0; const char *root = 0; - const char *basefile = 0; const char *refname = 0; #ifdef ENABLE_SUSEREPO char *proddir = 0; @@ -85,7 +81,7 @@ main(int argc, char **argv) * parse arguments */ - while ((c = getopt(argc, argv, "ACPhnkxXb:r:p:o:")) >= 0) + while ((c = getopt(argc, argv, "ACPhnkxXr:p:o:")) >= 0) switch (c) { case 'h': @@ -94,9 +90,6 @@ main(int argc, char **argv) case 'r': root = optarg; break; - case 'b': - basefile = optarg; - break; case 'n': nopacks = 1; break; @@ -231,7 +224,7 @@ main(int argc, char **argv) repo_add_autopattern(repo, ADD_NO_AUTOPRODUCTS); #endif - tool_write(repo, basefile, 0); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/rpmmd2solv.c b/tools/rpmmd2solv.c index 437c83d..ad75025 100644 --- a/tools/rpmmd2solv.c +++ b/tools/rpmmd2solv.c @@ -27,11 +27,9 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "rpmmd2solv [-a][-h][-n <attrname>][-l <locale>]\n" + "rpmmd2solv [-h]\n" " reads 'primary' from a 'rpmmd' repository from <stdin> and writes a .solv file to <stdout>\n" " -h : print help & exit\n" - " -n <name>: save attributes as <name>.attr\n" - " -l <locale>: parse localization data for <locale>\n" ); exit(status); } @@ -39,11 +37,7 @@ usage(int status) int main(int argc, char **argv) { - int c, flags = 0; - const char *attrname = 0; - const char *basefile = 0; - const char *dir = 0; - const char *locale = 0; + int c; #ifdef SUSE int add_auto = 0; #endif @@ -51,25 +45,13 @@ main(int argc, char **argv) Pool *pool = pool_create(); Repo *repo = repo_create(pool, "<stdin>"); - while ((c = getopt (argc, argv, "hn:b:d:l:X")) >= 0) + while ((c = getopt (argc, argv, "hX")) >= 0) { - switch(c) + switch (c) { case 'h': usage(0); break; - case 'n': - attrname = optarg; - break; - case 'b': - basefile = optarg; - break; - case 'd': - dir = optarg; - break; - case 'l': - locale = optarg; - break; case 'X': #ifdef SUSE add_auto = 1; @@ -80,81 +62,16 @@ main(int argc, char **argv) break; } } - if (dir) - { - FILE *fp; - int l; - char *fnp; - l = strlen(dir) + 128; - fnp = solv_malloc(l+1); - snprintf(fnp, l, "%s/primary.xml.gz", dir); - if (!(fp = solv_xfopen(fnp, 0))) - { - perror(fnp); - exit(1); - } - if (repo_add_rpmmd(repo, fp, 0, flags)) - { - fprintf(stderr, "rpmmd2solv: %s: %s\n", fnp, pool_errstr(pool)); - exit(1); - } - fclose(fp); - snprintf(fnp, l, "%s/diskusagedata.xml.gz", dir); - if ((fp = solv_xfopen(fnp, 0))) - { - if (repo_add_rpmmd(repo, fp, 0, flags)) - { - fprintf(stderr, "rpmmd2solv: %s: %s\n", fnp, pool_errstr(pool)); - exit(1); - } - fclose(fp); - } - if (locale) - { - if (snprintf(fnp, l, "%s/translation-%s.xml.gz", dir, locale) >= l) - { - fprintf(stderr, "-l parameter too long\n"); - exit(1); - } - while (!(fp = solv_xfopen(fnp, 0))) - { - fprintf(stderr, "not opened %s\n", fnp); - if (strlen(locale) > 2) - { - if (snprintf(fnp, l, "%s/translation-%.2s.xml.gz", dir, locale) >= l) - { - fprintf(stderr, "-l parameter too long\n"); - exit(1); - } - if ((fp = solv_xfopen(fnp, 0))) - break; - } - perror(fnp); - exit(1); - } - fprintf(stderr, "opened %s\n", fnp); - if (repo_add_rpmmd(repo, fp, 0, flags)) - { - fprintf(stderr, "rpmmd2solv: %s: %s\n", fnp, pool_errstr(pool)); - exit(1); - } - fclose(fp); - } - solv_free(fnp); - } - else + if (repo_add_rpmmd(repo, stdin, 0, 0)) { - if (repo_add_rpmmd(repo, stdin, 0, flags)) - { - fprintf(stderr, "rpmmd2solv: %s\n", pool_errstr(pool)); - exit(1); - } + fprintf(stderr, "rpmmd2solv: %s\n", pool_errstr(pool)); + exit(1); } #ifdef SUSE if (add_auto) repo_add_autopattern(repo, 0); #endif - tool_write(repo, basefile, attrname); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/rpms2solv.c b/tools/rpms2solv.c index 7852b08..c012b46 100644 --- a/tools/rpms2solv.c +++ b/tools/rpms2solv.c @@ -64,7 +64,6 @@ main(int argc, char **argv) Repo *repo; FILE *fp; char buf[4096], *p; - const char *basefile = 0; #ifdef ENABLE_PUBKEY int pubkeys = 0; #endif @@ -73,13 +72,10 @@ main(int argc, char **argv) #endif int filtered_filelist = 0; - while ((c = getopt(argc, argv, "0XkKb:m:F")) >= 0) + while ((c = getopt(argc, argv, "0XkKm:F")) >= 0) { switch(c) { - case 'b': - basefile = optarg; - break; case 'm': manifest = optarg; break; @@ -184,7 +180,7 @@ main(int argc, char **argv) if (add_auto) repo_add_autopattern(repo, 0); #endif - tool_write(repo, basefile, 0); + tool_write(repo, stdout); pool_free(pool); for (c = 0; c < nrpms; c++) free((char *)rpms[c]); diff --git a/tools/susetags2solv.c b/tools/susetags2solv.c index ced614b..f7544dc 100644 --- a/tools/susetags2solv.c +++ b/tools/susetags2solv.c @@ -29,13 +29,11 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "susetags2solv [-b <base>][-c <content>][-d <descrdir>][-h][-n <name>]\n" + "susetags2solv [-c <content>][-d <descrdir>][-h][-n <name>]\n" " reads a 'susetags' repository from <stdin> and writes a .solv file to <stdout>\n" - " -b <base>: save as multiple files starting with <base>\n" " -c <contentfile> : parse given contentfile (for product information)\n" " -d <descrdir> : do not read from stdin, but use data in descrdir\n" " -h : print help & exit\n" - " -n <name>: save attributes as <name>.attr\n" ); exit(status); } @@ -61,9 +59,7 @@ int main(int argc, char **argv) { const char *contentfile = 0; - const char *attrname = 0; const char *descrdir = 0; - const char *basefile = 0; const char *query = 0; const char *mergefile = 0; Id defvendor = 0; @@ -75,25 +71,19 @@ main(int argc, char **argv) Pool *pool; Repo *repo; - while ((c = getopt(argc, argv, "hn:c:d:b:q:M:X")) >= 0) + while ((c = getopt(argc, argv, "hc:d:q:M:X")) >= 0) { switch (c) { case 'h': usage(0); break; - case 'n': - attrname = optarg; - break; case 'c': contentfile = optarg; break; case 'd': descrdir = optarg; break; - case 'b': - basefile = optarg; - break; case 'q': query = optarg; break; @@ -132,20 +122,6 @@ main(int argc, char **argv) fclose(fp); } - if (attrname) - { - /* ensure '.attr' suffix */ - const char *dot = strrchr(attrname, '.'); - if (!dot || strcmp(dot, ".attr")) - { - int len = strlen (attrname); - char *newname = (char *)malloc(len + 6); /* alloc for <attrname>+'.attr'+'\0' */ - strcpy (newname, attrname); - strcpy (newname+len, ".attr"); - attrname = newname; - } - } - /* * descrdir path given, open files and read from there */ @@ -311,7 +287,7 @@ main(int argc, char **argv) if (query) doquery(pool, repo, query); else - tool_write(repo, basefile, attrname); + tool_write(repo, stdout); pool_free(pool); exit(0); } diff --git a/tools/updateinfoxml2solv.c b/tools/updateinfoxml2solv.c index 6a97b0d..9bc038e 100644 --- a/tools/updateinfoxml2solv.c +++ b/tools/updateinfoxml2solv.c @@ -20,10 +20,9 @@ static void usage(int status) { fprintf(stderr, "\nUsage:\n" - "updateinfoxml2solv [-h][-n <attrname>]\n" + "updateinfoxml2solv [-h]\n" " reads a 'updateinfo.xml' file from <stdin> and writes a .solv file to <stdout>\n" " -h : print help & exit\n" - " -n <name>: save attributes as <name>.attr\n" ); exit(status); } @@ -32,21 +31,17 @@ int main(int argc, char **argv) { int c, flags = 0; - char *attrname = 0; Pool *pool = pool_create(); Repo *repo = repo_create(pool, "<stdin>"); - while ((c = getopt(argc, argv, "hn:")) >= 0) + while ((c = getopt(argc, argv, "h")) >= 0) { switch(c) { case 'h': usage(0); break; - case 'n': - attrname = optarg; - break; default: usage(1); break; @@ -57,7 +52,7 @@ main(int argc, char **argv) fprintf(stderr, "updateinfoxml2solv: %s\n", pool_errstr(pool)); exit(1); } - tool_write(repo, 0, attrname); + tool_write(repo, stdout); pool_free(pool); exit(0); } |