+++ /dev/null
-
-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.
-
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
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)
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})
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)
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:
-- 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
- 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?
# 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")
typedef struct {
Pool* const pool;
+ int const flags;
} Selection;
typedef struct {
queue_free(&$self->q);
solv_free($self);
}
- int flags() {
- return $self->flags;
- }
#ifdef SWIGRUBY
%rename("isempty?") isempty;
#endif
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) {
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);
}
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);
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.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
.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
.\}
.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
.\}
.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
.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
.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
.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
.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
.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
.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
.\}
.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
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
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)
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
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
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()
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()
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)
=== 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);
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)
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),
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
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.
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});
}
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])
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)
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
return 0;
}
-
#define MODE_LIST 0
#define MODE_INSTALL 1
#define MODE_ERASE 2
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;
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++;
}
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);
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);
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);
}
#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);
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);
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);
}
}
}
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);
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;
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);
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;
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;
}
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;
{
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 */
}
else
{
- Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */
+ Id *dircache;
+ Id *oldkeyskip = 0;
struct rpmdbentry *entries = 0, *rp;
int nentries = 0;
char *namedata = 0;
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)
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;
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;
}
}
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);
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);
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;
}
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;
}
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;
}
{
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;
}
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;
}
if (fread(lead, 16, 1, fp) != 1)
{
pool_error(pool, -1, "%s: unexpected EOF", rpm);
- solv_chksum_free(chksumh, 0);
fclose(fp);
return 0;
}
if (getu32(lead) != 0x8eade801)
{
pool_error(pool, -1, "%s: bad header", rpm);
- solv_chksum_free(chksumh, 0);
fclose(fp);
return 0;
}
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;
}
if (!headfromfp(&state, rpm, fp, lead, sigcnt, sigdsize, 0, chksumh, 0))
{
- solv_chksum_free(chksumh, 0);
fclose(fp);
return 0;
}
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);
}
}
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));
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;
}
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);
#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)
{
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);
return zchunkopen(0, mode, fd);
}
-#endif
+#endif /* ENABLE_ZCHUNK_COMPRESSION */
+
FILE *
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);
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);
{ SELECTION_MATCH_DEPSTR, "depstr" },
{ SELECTION_WITH_DISABLED, "withdisabled" },
{ SELECTION_WITH_BADARCH, "withbadarch" },
+ { SELECTION_ADD, "add" },
+ { SELECTION_SUBTRACT, "subtract" },
+ { SELECTION_FILTER, "filter" },
{ 0, 0 }
};
Id flags, id, id2, namespaceid = 0;
struct oplist *op;
- if (!s)
- return 0;
while (*s == ' ' || *s == '\t')
s++;
if (!strncmp(s, "namespace:", 10))
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++)
{
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;
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);
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);
}
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++)
Id lowscore;
FILE *fp;
Strqueue sq;
- char *cmd, *out, *result;
+ char *cmd, *out;
const char *s;
if (!testcasename)
if ((resultflags & ~TESTCASE_RESULT_REUSE_SOLVER) != 0)
{
+ char *result;
cmd = 0;
for (i = 0; resultflags2str[i].str; i++)
if ((resultflags & resultflags2str[i].flag) != 0)
result = testcase_solverresult(solv, resultflags);
if (!strcmp(resultname, "<inline>"))
{
+ int i;
Strqueue rsq;
strqueue_init(&rsq);
strqueue_split(&rsq, result);
if (fclose(fp))
{
pool_error(solv->pool, 0, "testcase_write: write error");
- solv_free(result);
strqueue_free(&sq);
return 0;
}
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;
}
}
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 */
{
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]);
}
-------------------------------------------------------------------
-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
%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
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
extern "C" {
#endif
-typedef struct _Map {
+typedef struct s_Map {
unsigned char *map;
int size;
} Map;
#include "sha1.h"
#include "sha2.h"
-struct _Chksum {
+struct s_Chksum {
Id type;
int done;
unsigned char result[64];
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);
if (MAPTST(&solv->multiversion, p))
break;
if (p)
- continue; /* found a multiversion package that will not obsolate anything */
+ continue;
}
om.size = 0;
extern "C" {
#endif
-struct _Repo;
+struct s_Repo;
-typedef struct _KeyValue {
+typedef struct s_KeyValue {
Id id;
const char *str;
unsigned int num;
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)
#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)
#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 */
* 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;
Id *keyp;
/* the result */
- struct _Repokey *key;
+ struct s_Repokey *key;
KeyValue kv;
/* our matcher */
char *dupstr;
int dupstrn;
+ Id *keyskip;
+ Id *oldkeyskip;
} 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);
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);
extern "C" {
#endif
-typedef struct _Dirpool {
+typedef struct s_Dirpool {
Id *dirs;
int ndirs;
Id *dirtraverse;
{
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);
}
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++)
--- /dev/null
+/*
+ * 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;
+}
+
#include "util.h"
#include "bitmap.h"
+
struct searchfiles {
Id *ids;
int nfiles;
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
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));
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)
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));
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"),
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"),
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"),
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"),
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
pool_trivial_installable_multiversionmap;
pool_vendor2mask;
pool_whatmatchesdep;
+ pool_whatmatchessolvable;
pool_whatcontainsdep;
queue_alloc_one;
queue_alloc_one_head;
repo_addid;
repo_addid_dep;
repo_create;
+ repo_create_keyskip;
repo_disable_paging;
repo_empty;
repo_fix_conflicts;
repo_lookup_str;
repo_lookup_type;
repo_lookup_void;
- repo_matchvalue;
repo_reserve_ids;
repo_rewrite_suse_deps;
repo_search;
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;
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;
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;
#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;
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));
{
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)
struct orderdata {
Transaction *trans;
- struct _TransactionElement *tes;
+ struct s_TransactionElement *tes;
int ntes;
Id *edgedata;
int nedgedata;
addteedge(struct orderdata *od, int from, int to, int type)
{
int i;
- struct _TransactionElement *te;
+ struct s_TransactionElement *te;
if (from == to)
return 0;
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); */
Pool *pool = od->trans->pool;
Id ddegmin, ddegmax, ddeg;
int k, l;
- struct _TransactionElement *te;
+ struct s_TransactionElement *te;
l = 0;
ddegmin = ddegmax = 0;
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++)
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)
Transaction *trans = od->trans;
Pool *pool = trans->pool;
#endif
- struct _TransactionElement *te;
+ struct s_TransactionElement *te;
int i, j, k, tail;
int head;
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;
/* 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);
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)
{
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)
{
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;
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;
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;
Solvable *s;
Id p, pp;
- if (!pool->installed)
- return;
for (i = j = 0; i < plist->count; i++)
{
s = pool->solvables + plist->elements[i];
{
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 */
{
else
prune_obsoleted(pool, plist);
}
+ if (plist->count > 1 && pool->installed)
+ move_installed_to_front(pool, plist);
}
#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);
{
dislike_old_versions(pool, plist);
sort_by_common_dep(pool, plist);
- move_installed_to_front(pool, plist);
}
}
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;
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
vprintf(format, args);
else
vfprintf(stderr, format, args);
- va_end(args);
return;
}
vsnprintf(buf, sizeof(buf), format, args);
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;
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)
{
/*----------------------------------------------- */
-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;
/* 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;
#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 */
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 */
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 */
#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)
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);
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);
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);
* 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);
#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);
"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",
* 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 */
#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 */
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)
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;
#endif
-struct _Solver;
+struct s_Solver;
#define SOLVER_SOLUTION_JOB (0)
#define SOLVER_SOLUTION_DISTUPGRADE (-1)
#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
}
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 */
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;
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;
}
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;
}
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)
}
}
+ 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;
}
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:
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)
{
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)
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;
}
int
repo_lookup_idarray(Repo *repo, Id entry, Id keyname, Queue *q)
{
- Pool *pool = repo->pool;
Repodata *data;
int i;
if (entry >= 0)
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;
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;
}
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;
}
extern "C" {
#endif
-typedef struct _Repo {
+typedef struct s_Repo {
const char *name; /* name pointer */
Id repoid; /* our id */
void *appdata; /* application private pointer */
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);
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) \
int oldnstrings = pool->ss.nstrings;
int oldnrels = pool->nrels;
- struct _Stringpool *spool;
+ struct s_Stringpool *spool;
Repodata *parent = 0;
Repodata data;
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;
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");
}
/* 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;
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)
{
/* overwrite stub repodata */
repodata_freedata(parent);
data.repodataid = parent->repodataid;
+ data.loadcallback = parent->loadcallback;
*parent = data;
}
else
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)
{
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));
} NeedId;
-#define RELOFF(id) (needid[0].map + GETRELID(id))
+#define NEEDIDOFF(id) (ISRELDEP(id) ? (needid[0].map + GETRELID(id)) : id)
/*
* increment need Id
*
*/
-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;
}
{
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)
};
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;
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
{
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])
{
Id id = ids[len];
if (needid)
- id = needid[ISRELDEP(id) ? RELOFF(id) : id].need;
+ id = needid[NEEDIDOFF(id)].need;
sids[len] = id;
}
}
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);
}
}
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;
}
/*
* 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)
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)
{
}
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;
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;
}
* 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:
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);
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;
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);
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)
{
}
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 */
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" */
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)
{
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:
*
* 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;
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 = ⌖
/* 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)
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;
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)
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;
}
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)
{
}
}
}
- 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;
}
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;
#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);
/********************************************************************/
{
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)
/********************************************************************/
- 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;
+ }
}
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 */
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
* 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);
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
/* 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));
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)
}
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;
/********************************************************************/
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;
*/
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);
}
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)
{
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;
}
+
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
/*
- * Copyright (c) 2007, Novell Inc.
+ * Copyright (c) 2018, SUSE LLC.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
solv_free(data->attrnum64data);
solv_free(data->dircache);
+
+ repodata_free_filelistfilter(data);
}
void
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
{
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 *
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)
{
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 *
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 (;;)
{
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)
{
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;
}
/************************************************************************
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++)
}
+/* 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;
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
{
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)
{
{
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
{
}
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;
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,
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
datamatcher_free(&di->matcher);
if (di->dupstr)
solv_free(di->dupstr);
+ if (di->oldkeyskip)
+ solv_free(di->oldkeyskip);
}
static unsigned char *
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)
/* 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:
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);
}
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;
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:
/* 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 */
/* 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 */
}
+ /* we have a potential match */
if (di->matcher.match)
{
const char *str;
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))
}
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);
}
}
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;
}
*pp = 0;
}
-/* XXX: does not work correctly, needs fix in iterators! */
void
repodata_unset(Repodata *data, Id solvid, Id keyname)
{
}
}
+/* 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)
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;
}
else
{
repodata_add_stubkey(sdata, xkeyname, di.kv.id);
+ if (xkeyname == SOLVABLE_FILELIST)
+ repodata_set_filelisttype(sdata, REPODATA_FILELIST_EXTENSION);
xkeyname = 0;
}
}
return data;
}
+void
+repodata_set_filelisttype(Repodata *data, int type)
+{
+ data->filelisttype = type;
+}
+
unsigned int
repodata_memused(Repodata *data)
{
#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;
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 */
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 */
#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
/* 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
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);
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);
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
}
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;
switch (key->type)
{
case REPOKEY_TYPE_VOID:
+ case REPOKEY_TYPE_DELETED:
return dp;
case REPOKEY_TYPE_CONSTANT:
kv->num2 = 0;
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;
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;
}
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:
}
}
-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 */
#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
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 */
}
}
-/* 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
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;
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;
* 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 */
#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;
*/
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 */
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)
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);
}
}
/* 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;
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
{
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];
}
}
}
- if (!select)
- continue; /* job is now empty */
if (select == SOLVER_SOLVABLE_REPO)
{
Id p;
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);
}
/* 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)
{
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;
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. */
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)
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;
}
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
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)
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 */
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)
/* 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)
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)
{
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;
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;
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)
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)
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;
}
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)
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);
}
/*
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;
}
/*
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
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)
{
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)
}
}
}
+ 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);
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)
{
Map m2;
Id setflags = 0;
+ /* handle special cases */
if (!sel1->count || !sel2->count)
{
if (invert && !sel2->count)
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;
}
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);
}
#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);
* 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];
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
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;
+}
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 */
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);
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
}
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)
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);
}
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);
}
/*
* 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;
} /* 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 */
}
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)
{
}
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;
/* 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)
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));
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;
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)
{
}
}
}
+ /* 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
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);
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
}
}
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));
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 */
#endif /* LIBSOLV_INTERNAL */
};
-typedef struct _Solver Solver;
+typedef struct s_Solver Solver;
/*
* queue commands
#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 */
}
}
-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);
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 */
Map transactsmap;
Map multiversionmap;
- struct _TransactionOrderdata *orderdata;
+ struct s_TransactionOrderdata *orderdata;
#endif
} 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);
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);
+++ /dev/null
-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
+++ /dev/null
-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
+++ /dev/null
-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
--- /dev/null
+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]
+
exit(1);
}
}
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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;
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]);
fprintf(stderr, "archrepo2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
* 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 */
}
#include "repo.h"
-void tool_write(Repo *repo, const char *basename, const char *attrname);
+void tool_write(Repo *repo, FILE *fp);
#endif
fprintf(stderr, "comps2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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;
}
}
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]);
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);
}
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;
fprintf(stderr, "deltainfoxml2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, attrname);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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);
}
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;
fprintf(stderr, "diskusagexml2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, attrname);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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;
case REPOKEY_TYPE_VOID:
printf("null");
break;
- case REPOKEY_TYPE_U32:
case REPOKEY_TYPE_CONSTANT:
printf("%u", kv->num);
break;
fprintf(stderr, "helix2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
/*
- * Copyright (c) 2012, Novell Inc.
+ * Copyright (c) 2012, Novell Inc.);
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
fclose(fp);
}
repo_internalize(repo);
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
{
Pool *pool;
Repo *repo;
- const char *basefile = 0;
int with_attr = 0;
#ifdef SUSE
int add_auto = 0;
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)
{
case 'a':
with_attr = 1;
break;
- case 'b':
- basefile = optarg;
- break;
case 'X':
#ifdef SUSE
add_auto = 1;
if (add_auto)
repo_add_autopattern(repo, 0);
#endif
- tool_write(repo, basefile, 0);
+ tool_write(repo, stdout);
pool_free(pool);
return 0;
}
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);
}
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)
{
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);
if (query)
doquery(pool, repo, query);
else
- tool_write(repo, 0, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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);
}
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;
* 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':
case 'r':
root = optarg;
break;
- case 'b':
- basefile = optarg;
- break;
case 'n':
nopacks = 1;
break;
repo_add_autopattern(repo, ADD_NO_AUTOPRODUCTS);
#endif
- tool_write(repo, basefile, 0);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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);
}
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
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;
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);
}
Repo *repo;
FILE *fp;
char buf[4096], *p;
- const char *basefile = 0;
#ifdef ENABLE_PUBKEY
int pubkeys = 0;
#endif
#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;
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]);
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);
}
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;
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;
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
*/
if (query)
doquery(pool, repo, query);
else
- tool_write(repo, basefile, attrname);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}
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);
}
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;
fprintf(stderr, "updateinfoxml2solv: %s\n", pool_errstr(pool));
exit(1);
}
- tool_write(repo, 0, attrname);
+ tool_write(repo, stdout);
pool_free(pool);
exit(0);
}