@@ -22,6 +22,9 @@ struct parsedata {
2222 Pool * pool ;
2323 Repo * repo ;
2424 Repodata * data ;
25+
26+ Stringpool fnpool ;
27+ Queue fndata ;
2528};
2629
2730static int
@@ -84,18 +87,53 @@ parse_trackfeatures(struct parsedata *pd, struct solv_jsonparser *jp, Id handle)
8487 return type ;
8588}
8689
90+ static void
91+ swap_solvables (Repo * repo , Repodata * data , Id pa , Id pb )
92+ {
93+ Pool * pool = repo -> pool ;
94+ Solvable tmp ;
95+
96+ tmp = pool -> solvables [pa ];
97+ pool -> solvables [pa ] = pool -> solvables [pb ];
98+ pool -> solvables [pb ] = tmp ;
99+ repodata_swap_attrs (data , pa , pb );
100+ }
101+
102+ static Id *
103+ fn2data (struct parsedata * pd , const char * fn , Id * fntypep , int create )
104+ {
105+ size_t l = strlen (fn ), extl = 0 ;
106+ Id fnid ;
107+ if (l > 6 && !strcmp (fn + l - 6 , ".conda" ))
108+ extl = 6 ;
109+ else if (l > 8 && !strcmp (fn + l - 8 , ".tar.bz2" ))
110+ extl = 8 ;
111+ else
112+ return 0 ;
113+ fnid = stringpool_strn2id (& pd -> fnpool , fn , l - extl , create );
114+ if (!fnid )
115+ return 0 ;
116+ if (fnid * 2 + 2 > pd -> fndata .count )
117+ queue_insertn (& pd -> fndata , pd -> fndata .count , fnid * 2 + 2 - pd -> fndata .count , 0 );
118+ if (fntypep )
119+ * fntypep = extl == 8 ? 1 : 2 ; /* 1: legacy .tar.bz2 2: .conda */
120+ return pd -> fndata .elements + 2 * fnid ;
121+ }
122+
87123static int
88124parse_package (struct parsedata * pd , struct solv_jsonparser * jp , char * kfn )
89125{
90126 int type = JP_OBJECT ;
91127 Pool * pool = pd -> pool ;
92128 Repodata * data = pd -> data ;
93129 Solvable * s ;
94- Id handle = repo_add_solvable (pd -> repo );
95- s = pool_id2solvable (pool , handle );
130+ Id handle ;
96131 char * fn = 0 ;
97132 char * subdir = 0 ;
133+ Id * fndata = 0 , fntype = 0 ;
98134
135+ handle = repo_add_solvable (pd -> repo );
136+ s = pool_id2solvable (pool , handle );
99137 while (type > 0 && (type = jsonparser_parse (jp )) > 0 && type != JP_OBJECT_END )
100138 {
101139 if (type == JP_STRING && !strcmp (jp -> key , "build" ))
@@ -151,13 +189,36 @@ parse_package(struct parsedata *pd, struct solv_jsonparser *jp, char *kfn)
151189 type = jsonparser_skip (jp , type );
152190 }
153191 if (fn || kfn )
154- repodata_set_location (data , handle , 0 , subdir , fn ? fn : kfn );
192+ {
193+ repodata_set_location (data , handle , 0 , subdir , fn ? fn : kfn );
194+ fndata = fn2data (pd , fn ? fn : kfn , & fntype , 1 );
195+ }
155196 solv_free (fn );
156197 solv_free (subdir );
157198 if (!s -> evr )
158199 s -> evr = 1 ;
159200 if (s -> name )
160201 s -> provides = repo_addid_dep (pd -> repo , s -> provides , pool_rel2id (pool , s -> name , s -> evr , REL_EQ , 1 ), 0 );
202+
203+ if (fndata )
204+ {
205+ /* deal with legacy package entries */
206+ if (fndata [0 ] && fndata [0 ] > fntype )
207+ {
208+ /* ignore this package */
209+ repo_free_solvable (pd -> repo , handle , 1 );
210+ return type ;
211+ }
212+ if (fndata [0 ] && fndata [0 ] < fntype )
213+ {
214+ /* replace old package */
215+ swap_solvables (pd -> repo , data , handle , fndata [1 ]);
216+ repo_free_solvable (pd -> repo , handle , 1 );
217+ handle = fndata [1 ];
218+ }
219+ fndata [0 ] = fntype ;
220+ fndata [1 ] = handle ;
221+ }
161222 return type ;
162223}
163224
@@ -228,6 +289,8 @@ repo_add_conda(Repo *repo, FILE *fp, int flags)
228289 pd .pool = pool ;
229290 pd .repo = repo ;
230291 pd .data = data ;
292+ stringpool_init_empty (& pd .fnpool );
293+ queue_init (& pd .fndata );
231294
232295 jsonparser_init (& jp , fp );
233296 if ((type = jsonparser_parse (& jp )) != JP_OBJECT )
@@ -236,6 +299,8 @@ repo_add_conda(Repo *repo, FILE *fp, int flags)
236299 ret = pool_error (pool , -1 , "parse error line %d" , jp .line );
237300 jsonparser_free (& jp );
238301
302+ queue_free (& pd .fndata );
303+ stringpool_free (& pd .fnpool );
239304 if (!(flags & REPO_NO_INTERNALIZE ))
240305 repodata_internalize (data );
241306
0 commit comments