2727
2828#include "xbps_api_impl.h"
2929
30- bool HIDDEN
31- xbps_transaction_store (struct xbps_handle * xhp , xbps_array_t pkgs ,
32- xbps_dictionary_t pkgrd , bool autoinst )
30+ static int
31+ transaction_replace_package (xbps_array_t pkgs , const char * pkgname , const char * pkgver )
3332{
34- bool alloc_replaces = false;
35- xbps_dictionary_t d , pkgd ;
36- xbps_array_t replaces ;
37- const char * pkgver , * pkgname , * curpkgver , * repo ;
38- char * self_replaced ;
39- int rv ;
33+ xbps_dictionary_t pkgd ;
34+ const char * curpkgver = NULL ;
35+ int r ;
4036
41- assert (xhp );
42- assert (pkgs );
43- assert (pkgrd );
37+ pkgd = xbps_find_pkg_in_array (pkgs , pkgname , 0 );
38+ if (!pkgd )
39+ return 1 ;
40+
41+ /* compare version stored in transaction vs current */
42+ if (!xbps_dictionary_get_cstring_nocopy (pkgd , "pkgver" , & curpkgver ))
43+ xbps_unreachable ();
44+
45+ r = xbps_cmpver (pkgver , curpkgver );
46+ if (r == 0 )
47+ return 0 ;
48+ // XXX: should it be possible to replace with lower version?
49+ if (r == -1 )
50+ return 0 ;
51+
52+ if (!xbps_remove_pkg_from_array_by_pkgver (pkgs , curpkgver ))
53+ xbps_unreachable ();
54+
55+ xbps_dbg_printf ("[trans] replaced %s with %s\n" , curpkgver , pkgver );
4456
45- if (!xbps_dictionary_get_cstring_nocopy (pkgrd , "pkgver" , & pkgver )) {
46- return false;
57+ return 1 ;
58+ }
59+
60+ // XXX: the automatic self replace is weird, there should be a better way
61+ // than having to add and remove it from the metdata...
62+ static int
63+ package_self_replace (xbps_dictionary_t pkgd , const char * pkgname )
64+ {
65+ char buf [XBPS_NAME_SIZE + sizeof (">=0" ) - 1 ];
66+ xbps_array_t replaces ;
67+
68+ replaces = xbps_dictionary_get (pkgd , "replaces" );
69+ if (!replaces ) {
70+ replaces = xbps_array_create ();
71+ if (!replaces )
72+ return xbps_error_oom ();
73+ } else {
74+ xbps_object_retain (replaces );
4775 }
48- if (!xbps_dictionary_get_cstring_nocopy (pkgrd , "pkgname" , & pkgname )) {
49- return false;
76+
77+ snprintf (buf ,sizeof (buf ), "%s>=0" , pkgname );
78+ if (!xbps_array_add_cstring (replaces , buf )) {
79+ xbps_object_release (replaces );
80+ return xbps_error_oom ();
5081 }
51- d = xbps_find_pkg_in_array (pkgs , pkgname , 0 );
52- if (xbps_object_type (d ) == XBPS_TYPE_DICTIONARY ) {
53- /* compare version stored in transaction vs current */
54- if (!xbps_dictionary_get_cstring_nocopy (d , "pkgver" , & curpkgver )) {
55- return false;
56- }
57- rv = xbps_cmpver (pkgver , curpkgver );
58- if (rv == 0 || rv == -1 ) {
59- /* same version or stored version greater than current */
60- return true;
61- } else {
62- /*
63- * Current version is greater than stored,
64- * replace stored with current.
65- */
66- if (!xbps_remove_pkg_from_array_by_pkgver (pkgs , curpkgver )) {
67- return false;
68- }
69- xbps_dbg_printf ("[trans] replaced %s with %s\n" , curpkgver , pkgver );
70- }
82+
83+ if (!xbps_dictionary_set (pkgd , "replaces" , replaces )) {
84+ xbps_object_release (replaces );
85+ return xbps_error_oom ();
7186 }
7287
73- if ((pkgd = xbps_dictionary_copy_mutable (pkgrd )) == NULL )
74- return false;
88+ xbps_object_release (replaces );
89+ return 0 ;
90+ }
7591
76- /*
77- * Add required objects into package dep's dictionary.
78- */
79- if (autoinst && !xbps_dictionary_set_bool (pkgd , "automatic-install" , true))
80- goto err ;
92+ int HIDDEN
93+ xbps_transaction_store (struct xbps_handle * xhp , xbps_array_t pkgs ,
94+ xbps_dictionary_t pkgrd , bool autoinst )
95+ {
96+ xbps_dictionary_t pkgd ;
97+ const char * pkgver = NULL , * pkgname = NULL , * repo = NULL ;
98+ int r ;
8199
82- /*
83- * Set a replaces to itself, so that virtual packages are always replaced.
84- */
85- if ((replaces = xbps_dictionary_get (pkgd , "replaces" )) == NULL ) {
86- replaces = xbps_array_create ();
87- if (!replaces ) {
88- xbps_error_oom ();
89- goto err ;
90- }
91- alloc_replaces = true;
100+ assert (xhp );
101+ assert (pkgs );
102+ assert (pkgrd );
103+
104+ if (!xbps_dictionary_get_cstring_nocopy (pkgrd , "pkgver" , & pkgver ))
105+ xbps_unreachable ();
106+ if (!xbps_dictionary_get_cstring_nocopy (pkgrd , "pkgname" , & pkgname ))
107+ xbps_unreachable ();
108+
109+ r = transaction_replace_package (pkgs , pkgname , pkgver );
110+ if (r < 0 )
111+ return r ;
112+ if (r == 0 )
113+ return 0 ;
114+
115+ pkgd = xbps_dictionary_copy_mutable (pkgrd );
116+ if (!pkgd ) {
117+ xbps_object_release (pkgd );
118+ return xbps_error_oom ();
92119 }
93120
94- self_replaced = xbps_xasprintf ("%s>=0" , pkgname );
95- xbps_array_add_cstring (replaces , self_replaced );
96- free (self_replaced );
121+ if (autoinst && !xbps_dictionary_set_bool (pkgd , "automatic-install" , true)) {
122+ xbps_object_release (pkgd );
123+ return xbps_error_oom ();
124+ }
97125
98- if (! xbps_dictionary_set ( pkgd , "replaces" , replaces )) {
99- if (alloc_replaces )
100- xbps_object_release (replaces );
101- goto err ;
126+ r = package_self_replace ( pkgd , pkgname );
127+ if (r < 0 ) {
128+ xbps_object_release (pkgd );
129+ return r ;
102130 }
103- if (alloc_replaces )
104- xbps_object_release (replaces );
105131
106- /*
107- * Add the dictionary into the unsorted queue.
108- */
109- if (!xbps_array_add (pkgs , pkgd ))
110- goto err ;
132+ if (!xbps_array_add (pkgs , pkgd )) {
133+ xbps_object_release (pkgd );
134+ return xbps_error_oom ();
135+ }
111136
112137 xbps_dictionary_get_cstring_nocopy (pkgd , "repository" , & repo );
113138
@@ -118,8 +143,5 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs,
118143 autoinst ? " as automatic install" : "" , repo );
119144 xbps_object_release (pkgd );
120145
121- return true;
122- err :
123- xbps_object_release (pkgd );
124- return false;
146+ return 0 ;
125147}
0 commit comments