3535#include <string.h>
3636#include <unistd.h>
3737
38+ #include "xbps.h"
3839#include "xbps_api_impl.h"
3940
4041/**
@@ -145,26 +146,35 @@ pkgdb_map_vpkgs(struct xbps_handle *xhp)
145146{
146147 xbps_object_iterator_t iter ;
147148 xbps_object_t obj ;
148- int rv = 0 ;
149+ int r = 0 ;
149150
150151 if (!xbps_dictionary_count (xhp -> pkgdb ))
151152 return 0 ;
152153
153154 if (xhp -> vpkgd == NULL ) {
154155 xhp -> vpkgd = xbps_dictionary_create ();
155- assert (xhp -> vpkgd );
156+ if (!xhp -> vpkgd ) {
157+ r = - errno ;
158+ xbps_error_printf ("failed to create dictionary\n" );
159+ return r ;
160+ }
156161 }
162+
157163 /*
158164 * This maps all pkgs that have virtualpkgs in pkgdb.
159165 */
160166 iter = xbps_dictionary_iterator (xhp -> pkgdb );
161- assert (iter );
167+ if (!iter ) {
168+ r = - errno ;
169+ xbps_error_printf ("failed to create iterator" );
170+ goto out ;
171+ }
162172
163173 while ((obj = xbps_object_iterator_next (iter ))) {
164174 xbps_array_t provides ;
165175 xbps_dictionary_t pkgd ;
166176 const char * pkgver = NULL ;
167- char pkgname [ XBPS_NAME_SIZE ] = { 0 } ;
177+ const char * pkgname = NULL ;
168178 unsigned int cnt ;
169179
170180 pkgd = xbps_dictionary_get_keysym (xhp -> pkgdb , obj );
@@ -174,26 +184,53 @@ pkgdb_map_vpkgs(struct xbps_handle *xhp)
174184 continue ;
175185
176186 xbps_dictionary_get_cstring_nocopy (pkgd , "pkgver" , & pkgver );
177- if (!xbps_pkg_name (pkgname , sizeof (pkgname ), pkgver )) {
178- rv = EINVAL ;
179- goto out ;
180- }
187+ xbps_dictionary_get_cstring_nocopy (pkgd , "pkgname" , & pkgname );
188+ assert (pkgname );
189+
181190 for (unsigned int i = 0 ; i < cnt ; i ++ ) {
191+ char vpkgname [XBPS_NAME_SIZE ];
182192 const char * vpkg = NULL ;
193+ xbps_dictionary_t providers ;
194+ bool alloc = false;
183195
184196 xbps_array_get_cstring_nocopy (provides , i , & vpkg );
185- if (!xbps_dictionary_set_cstring (xhp -> vpkgd , vpkg , pkgname )) {
186- xbps_dbg_printf ("%s: set_cstring vpkg "
187- "%s pkgname %s\n" , __func__ , vpkg , pkgname );
188- rv = EINVAL ;
197+ if (!xbps_pkg_name (vpkgname , sizeof (vpkgname ), vpkg )) {
198+ xbps_warn_printf ("%s: invalid provides: %s\n" , pkgver , vpkg );
199+ continue ;
200+ }
201+
202+ providers = xbps_dictionary_get (xhp -> vpkgd , vpkgname );
203+ if (!providers ) {
204+ providers = xbps_dictionary_create ();
205+ if (!providers ) {
206+ r = - errno ;
207+ xbps_error_printf ("failed to create dictionary\n" );
208+ goto out ;
209+ }
210+ if (!xbps_dictionary_set (xhp -> vpkgd , vpkgname , providers )) {
211+ r = - errno ;
212+ xbps_error_printf ("failed to set dictionary entry\n" );
213+ xbps_object_release (providers );
214+ goto out ;
215+ }
216+ alloc = true;
217+ }
218+
219+ if (!xbps_dictionary_set_cstring (providers , vpkg , pkgname )) {
220+ r = - errno ;
221+ xbps_error_printf ("failed to set dictionary entry\n" );
222+ if (alloc )
223+ xbps_object_release (providers );
189224 goto out ;
190225 }
226+ if (alloc )
227+ xbps_object_release (providers );
191228 xbps_dbg_printf ("[pkgdb] added vpkg %s for %s\n" , vpkg , pkgname );
192229 }
193230 }
194231out :
195232 xbps_object_iterator_release (iter );
196- return rv ;
233+ return r ;
197234}
198235
199236static int
@@ -398,13 +435,17 @@ generate_full_revdeps_tree(struct xbps_handle *xhp)
398435{
399436 xbps_object_t obj ;
400437 xbps_object_iterator_t iter ;
438+ xbps_dictionary_t vpkg_cache ;
401439
402440 if (xhp -> pkgdb_revdeps )
403441 return ;
404442
405443 xhp -> pkgdb_revdeps = xbps_dictionary_create ();
406444 assert (xhp -> pkgdb_revdeps );
407445
446+ vpkg_cache = xbps_dictionary_create ();
447+ assert (vpkg_cache );
448+
408449 iter = xbps_dictionary_iterator (xhp -> pkgdb );
409450 assert (iter );
410451
@@ -421,20 +462,33 @@ generate_full_revdeps_tree(struct xbps_handle *xhp)
421462 xbps_dictionary_get_cstring_nocopy (pkgd , "pkgver" , & pkgver );
422463 for (unsigned int i = 0 ; i < xbps_array_count (rundeps ); i ++ ) {
423464 xbps_array_t pkg ;
424- const char * pkgdep = NULL , * vpkgname = NULL ;
425- char * v , curpkgname [XBPS_NAME_SIZE ];
465+ const char * pkgdep = NULL , * v ;
466+ char curpkgname [XBPS_NAME_SIZE ];
426467 bool alloc = false;
427468
428469 xbps_array_get_cstring_nocopy (rundeps , i , & pkgdep );
429470 if ((!xbps_pkgpattern_name (curpkgname , sizeof (curpkgname ), pkgdep )) &&
430471 (!xbps_pkg_name (curpkgname , sizeof (curpkgname ), pkgdep ))) {
431472 abort ();
432473 }
433- vpkgname = vpkg_user_conf (xhp , curpkgname , false);
434- if (vpkgname == NULL ) {
435- v = strdup (curpkgname );
436- } else {
437- v = strdup (vpkgname );
474+
475+ /* TODO: this is kind of a workaround, to avoid calling vpkg_user_conf
476+ * over and over again for the same packages which is slow. A better
477+ * solution for itself vpkg_user_conf being slow should probably be
478+ * implemented at some point.
479+ */
480+ if (!xbps_dictionary_get_cstring_nocopy (vpkg_cache , curpkgname , & v )) {
481+ const char * vpkgname = vpkg_user_conf (xhp , curpkgname );
482+ if (vpkgname ) {
483+ v = vpkgname ;
484+ } else {
485+ v = curpkgname ;
486+ }
487+ errno = 0 ;
488+ if (!xbps_dictionary_set_cstring_nocopy (vpkg_cache , curpkgname , v )) {
489+ xbps_error_printf ("%s\n" , strerror (errno ? errno : ENOMEM ));
490+ abort ();
491+ }
438492 }
439493
440494 pkg = xbps_dictionary_get (xhp -> pkgdb_revdeps , v );
@@ -446,12 +500,12 @@ generate_full_revdeps_tree(struct xbps_handle *xhp)
446500 xbps_array_add_cstring_nocopy (pkg , pkgver );
447501 xbps_dictionary_set (xhp -> pkgdb_revdeps , v , pkg );
448502 }
449- free (v );
450503 if (alloc )
451504 xbps_object_release (pkg );
452505 }
453506 }
454507 xbps_object_iterator_release (iter );
508+ xbps_object_release (vpkg_cache );
455509}
456510
457511xbps_array_t
0 commit comments