summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-09-10 15:38:34 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-09-10 15:38:34 +0900
commit2491213c77850ed26991b572809a5ca4a61fa89b (patch)
treecd2e4928ad52795bc4a318a0721f487c282a33be
parent0e46e80434781d1acbc4f5716827bf8688450a30 (diff)
downloadlibsolv-2491213c77850ed26991b572809a5ca4a61fa89b.tar.gz
libsolv-2491213c77850ed26991b572809a5ca4a61fa89b.tar.bz2
libsolv-2491213c77850ed26991b572809a5ca4a61fa89b.zip
Imported Upstream version 0.7.0upstream/0.7.0
-rw-r--r--BUGS7
-rw-r--r--CMakeLists.txt14
-rw-r--r--NEWS28
-rw-r--r--TODO_1.012
-rw-r--r--VERSION.cmake8
-rw-r--r--bindings/solv.i27
-rw-r--r--doc/gen/helix2solv.14
-rw-r--r--doc/gen/installcheck.14
-rw-r--r--doc/gen/libsolv-bindings.3135
-rw-r--r--doc/gen/libsolv-constantids.34
-rw-r--r--doc/gen/libsolv-history.34
-rw-r--r--doc/gen/libsolv-pool.34
-rw-r--r--doc/gen/libsolv.34
-rw-r--r--doc/gen/mdk2solv.14
-rw-r--r--doc/gen/mergesolv.14
-rw-r--r--doc/gen/repo2solv.14
-rw-r--r--doc/gen/repomdxml2solv.14
-rw-r--r--doc/gen/rpmdb2solv.14
-rw-r--r--doc/gen/rpmmd2solv.14
-rw-r--r--doc/gen/rpms2solv.14
-rw-r--r--doc/gen/solv.14
-rw-r--r--doc/gen/susetags2solv.14
-rw-r--r--doc/gen/testsolv.14
-rw-r--r--doc/gen/updateinfoxml2solv.14
-rw-r--r--doc/libsolv-bindings.txt77
-rw-r--r--doc/rpmdb2solv.txt3
-rwxr-xr-xexamples/p5solv4
-rwxr-xr-xexamples/pysolv4
-rw-r--r--examples/solv/fastestmirror.c6
-rw-r--r--examples/solv/solv.c26
-rw-r--r--ext/repo_appdata.c56
-rw-r--r--ext/repo_autopattern.c4
-rw-r--r--ext/repo_pubkey.h2
-rw-r--r--ext/repo_repomdxml.c2
-rw-r--r--ext/repo_rpmdb.c104
-rw-r--r--ext/repo_rpmmd.c29
-rw-r--r--ext/repo_susetags.c28
-rw-r--r--ext/solv_xfopen.c75
-rw-r--r--ext/testcase.c75
-rw-r--r--package/libsolv.changes23
-rw-r--r--package/libsolv.spec.in2
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/bitmap.h2
-rw-r--r--src/chksum.c2
-rw-r--r--src/chksum.h4
-rw-r--r--src/cleandeps.c2
-rw-r--r--src/dataiterator.h32
-rw-r--r--src/dirpool.h2
-rw-r--r--src/diskusage.c6
-rw-r--r--src/filelistfilter.c196
-rw-r--r--src/fileprovides.c552
-rw-r--r--src/knownid.h36
-rw-r--r--src/libsolv.ver22
-rw-r--r--src/order.c40
-rw-r--r--src/policy.c12
-rw-r--r--src/pool.c44
-rw-r--r--src/pool.h54
-rw-r--r--src/poolarch.c4
-rw-r--r--src/poolid.h2
-rw-r--r--src/pooltypes.h8
-rw-r--r--src/problems.c17
-rw-r--r--src/problems.h42
-rw-r--r--src/queue.h2
-rw-r--r--src/repo.c408
-rw-r--r--src/repo.h9
-rw-r--r--src/repo_solv.c29
-rw-r--r--src/repo_write.c1275
-rw-r--r--src/repo_write.h34
-rw-r--r--src/repodata.c699
-rw-r--r--src/repodata.h81
-rw-r--r--src/repopack.h118
-rw-r--r--src/repopage.h4
-rw-r--r--src/rules.c32
-rw-r--r--src/rules.h72
-rw-r--r--src/selection.c525
-rw-r--r--src/selection.h5
-rw-r--r--src/sha2.h4
-rw-r--r--src/solvable.c72
-rw-r--r--src/solvable.h15
-rw-r--r--src/solver.c125
-rw-r--r--src/solver.h6
-rw-r--r--src/strpool.h2
-rw-r--r--src/transaction.c4
-rw-r--r--src/transaction.h20
-rw-r--r--test/testcases/allowuninstall/conflict.t14
-rw-r--r--test/testcases/allowuninstall/forcebest.t19
-rw-r--r--test/testcases/cleandeps/cleandeps_up3.t23
-rw-r--r--test/testcases/selection/selection_matchsolvable.t27
-rw-r--r--tools/appdata2solv.c2
-rw-r--r--tools/archpkgs2solv.c8
-rw-r--r--tools/archrepo2solv.c2
-rw-r--r--tools/common_write.c315
-rw-r--r--tools/common_write.h2
-rw-r--r--tools/comps2solv.c2
-rw-r--r--tools/deb2solv.c7
-rw-r--r--tools/deltainfoxml2solv.c11
-rw-r--r--tools/diskusagexml2solv.c11
-rw-r--r--tools/dumpsolv.c2
-rw-r--r--tools/helix2solv.c2
-rw-r--r--tools/mdk2solv.c4
-rw-r--r--tools/mergesolv.c8
-rw-r--r--tools/repo2solv.c12
-rw-r--r--tools/repomdxml2solv.c2
-rw-r--r--tools/rpmdb2solv.c13
-rw-r--r--tools/rpmmd2solv.c99
-rw-r--r--tools/rpms2solv.c8
-rw-r--r--tools/susetags2solv.c30
-rw-r--r--tools/updateinfoxml2solv.c11
108 files changed, 3332 insertions, 2743 deletions
diff --git a/BUGS b/BUGS
deleted file mode 100644
index 0e33eb5..0000000
--- a/BUGS
+++ /dev/null
@@ -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)
diff --git a/NEWS b/NEWS
index 5b1a2af..16b79a8 100644
--- a/NEWS
+++ b/NEWS
@@ -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:
diff --git a/TODO_1.0 b/TODO_1.0
index 13000fc..d77df67 100644
--- a/TODO_1.0
+++ b/TODO_1.0
@@ -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);
}
}
diff --git a/src/pool.c b/src/pool.c
index 279359a..383edb2 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -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)
{
diff --git a/src/pool.h b/src/pool.h
index 40e3777..37583a1 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -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 */
diff --git a/src/repo.c b/src/repo.c
index 9e59fe2..d163f13 100644
--- a/src/repo.c
+++ b/src/repo.c
@@ -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;
}
diff --git a/src/repo.h b/src/repo.h
index bd9c58c..4abfb0f 100644
--- a/src/repo.h
+++ b/src/repo.h
@@ -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 = &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);
diff --git a/src/sha2.h b/src/sha2.h
index 220af32..5377360 100644
--- a/src/sha2.h
+++ b/src/sha2.h
@@ -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);
}