Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
5 : : * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
6 : : * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
7 : : * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
8 : : * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
9 : : * Copyright (c) 2013 Gerald Pfeifer <gerald@pfeifer.com>
10 : : * Copyright (c) 2013-2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
11 : : * All rights reserved.
12 : : *
13 : : * Redistribution and use in source and binary forms, with or without
14 : : * modification, are permitted provided that the following conditions
15 : : * are met:
16 : : * 1. Redistributions of source code must retain the above copyright
17 : : * notice, this list of conditions and the following disclaimer
18 : : * in this position and unchanged.
19 : : * 2. Redistributions in binary form must reproduce the above copyright
20 : : * notice, this list of conditions and the following disclaimer in the
21 : : * documentation and/or other materials provided with the distribution.
22 : : *
23 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
24 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
27 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 : : */
34 : :
35 : : #ifdef HAVE_CONFIG_H
36 : : #include "pkg_config.h"
37 : : #endif
38 : :
39 : : #include <assert.h>
40 : : #include <errno.h>
41 : : #include <regex.h>
42 : : #include <grp.h>
43 : : #ifdef HAVE_LIBUTIL_H
44 : : #include <libutil.h>
45 : : #endif
46 : : #include <stdlib.h>
47 : : #include <stdio.h>
48 : : #include <stdbool.h>
49 : : #include <string.h>
50 : : #include <unistd.h>
51 : : #include <signal.h>
52 : :
53 : : #include <sqlite3.h>
54 : :
55 : : #include "pkg.h"
56 : : #include "private/event.h"
57 : : #include "private/pkg.h"
58 : : #include "private/pkgdb.h"
59 : : #include "private/utils.h"
60 : :
61 : : const char *
62 : 6132 : pkgdb_get_pattern_query(const char *pattern, match_t match)
63 : : {
64 : 6132 : char *checkorigin = NULL;
65 : 6132 : char *checkuid = NULL;
66 : 6132 : const char *comp = NULL;
67 : :
68 [ + + ]: 6132 : if (pattern != NULL) {
69 : 4229 : checkuid = strchr(pattern, '~');
70 [ - + ]: 4229 : if (checkuid == NULL)
71 : 4229 : checkorigin = strchr(pattern, '/');
72 : 4229 : }
73 : :
74 [ - + + + : 6132 : switch (match) {
+ ]
75 : : case MATCH_ALL:
76 : 1903 : comp = "";
77 : 1903 : break;
78 : : case MATCH_EXACT:
79 [ - + ]: 4117 : if (pkgdb_case_sensitive()) {
80 [ # # ]: 0 : if (checkuid == NULL) {
81 [ # # ]: 0 : if (checkorigin == NULL)
82 : 0 : comp = " WHERE (name = ?1 "
83 : : "OR (name = SPLIT_VERSION('name', ?1) AND "
84 : : " version = SPLIT_VERSION('version', ?1)))";
85 : : else
86 : 0 : comp = " WHERE origin = ?1";
87 : 0 : } else {
88 : 0 : comp = " WHERE name = ?1";
89 : : }
90 : 0 : } else {
91 [ - + ]: 4117 : if (checkuid == NULL) {
92 [ + + ]: 4117 : if (checkorigin == NULL)
93 : 4113 : comp = " WHERE (name = ?1 COLLATE NOCASE "
94 : : "OR (name = SPLIT_VERSION('name', ?1) COLLATE NOCASE AND "
95 : : " version = SPLIT_VERSION('version', ?1)))";
96 : : else
97 : 4 : comp = " WHERE origin = ?1 COLLATE NOCASE";
98 : 4117 : } else {
99 : 0 : comp = " WHERE name = ?1 COLLATE NOCASE";
100 : : }
101 : : }
102 : 4117 : break;
103 : : case MATCH_GLOB:
104 [ - + ]: 92 : if (checkuid == NULL) {
105 [ - + ]: 92 : if (checkorigin == NULL)
106 : 92 : comp = " WHERE (name GLOB ?1 "
107 : : "OR name || '-' || version GLOB ?1)";
108 : : else
109 : 0 : comp = " WHERE origin GLOB ?1";
110 : 92 : } else {
111 : 0 : comp = " WHERE name = ?1";
112 : : }
113 : 92 : break;
114 : : case MATCH_REGEX:
115 [ - + ]: 20 : if (checkuid == NULL) {
116 [ + - ]: 20 : if (checkorigin == NULL)
117 : 20 : comp = " WHERE (name REGEXP ?1 "
118 : : "OR name || '-' || version REGEXP ?1)";
119 : : else
120 : 0 : comp = " WHERE origin REGEXP ?1";
121 : 20 : } else {
122 : 0 : comp = " WHERE name = ?1";
123 : : }
124 : 20 : break;
125 : : }
126 : :
127 : 6132 : return (comp);
128 : : }
129 : :
130 : : struct pkgdb_it *
131 : 4111 : pkgdb_query_cond(struct pkgdb *db, const char *cond, const char *pattern, match_t match)
132 : : {
133 : : char sql[BUFSIZ];
134 : : sqlite3_stmt *stmt;
135 : 4111 : const char *comp = NULL;
136 : :
137 [ + - ]: 4111 : assert(db != NULL);
138 : :
139 [ + + + - : 4111 : if (match != MATCH_ALL && (pattern == NULL || pattern[0] == '\0'))
+ - ]
140 : 0 : return (NULL);
141 : :
142 : 4111 : comp = pkgdb_get_pattern_query(pattern, match);
143 : :
144 [ + + ]: 4111 : if (cond)
145 : 1812 : sqlite3_snprintf(sizeof(sql), sql,
146 : : "SELECT id, origin, name, name as uniqueid, "
147 : : "version, comment, desc, "
148 : : "message, arch, maintainer, www, "
149 : : "prefix, flatsize, licenselogic, automatic, "
150 : : "locked, time, manifestdigest, vital "
151 : : "FROM packages AS p%s %s (%s) ORDER BY p.name;",
152 : 906 : comp, pattern == NULL ? "WHERE" : "AND", cond + 7);
153 : : else
154 : 6410 : sqlite3_snprintf(sizeof(sql), sql,
155 : : "SELECT id, origin, name, name as uniqueid, "
156 : : "version, comment, desc, "
157 : : "message, arch, maintainer, www, "
158 : : "prefix, flatsize, licenselogic, automatic, "
159 : : "locked, time, manifestdigest, vital "
160 : : "FROM packages AS p%s "
161 : 3205 : "ORDER BY p.name;", comp);
162 : :
163 : 4111 : pkg_debug(4, "Pkgdb: running '%s'", sql);
164 [ - + ]: 4111 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
165 : 0 : ERROR_SQLITE(db->sqlite, sql);
166 : 0 : return (NULL);
167 : : }
168 : :
169 [ + + ]: 4111 : if (match != MATCH_ALL)
170 : 3007 : sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);
171 : :
172 : 4111 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
173 : 4111 : }
174 : :
175 : : struct pkgdb_it *
176 : 3123 : pkgdb_query(struct pkgdb *db, const char *pattern, match_t match)
177 : : {
178 : 3123 : return pkgdb_query_cond(db, NULL, pattern, match);
179 : : }
180 : :
181 : : bool
182 : 280 : pkgdb_file_exists(struct pkgdb *db, const char *path)
183 : : {
184 : : sqlite3_stmt *stmt;
185 : : char sql[BUFSIZ];
186 : 280 : bool ret = false;
187 : :
188 [ + - ]: 280 : assert(db != NULL);
189 : :
190 [ + - ]: 280 : if (path == NULL)
191 : 0 : return (false);
192 : :
193 : 280 : sqlite3_snprintf(sizeof(sql), sql,
194 : : "select path from files where path = ?1;");
195 : 280 : pkg_debug(4, "Pkgdb: running '%s'", sql);
196 : :
197 [ + - ]: 280 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
198 : 0 : ERROR_SQLITE(db->sqlite, sql);
199 : 0 : }
200 : :
201 : 280 : sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT);
202 : :
203 [ + + ]: 280 : if (sqlite3_step(stmt) != SQLITE_DONE) {
204 : 47 : ret = true;
205 : 47 : }
206 : :
207 : 280 : sqlite3_finalize(stmt);
208 : 280 : return (ret);
209 : 280 : }
210 : :
211 : : struct pkgdb_it *
212 : 4 : pkgdb_query_which(struct pkgdb *db, const char *path, bool glob)
213 : : {
214 : : sqlite3_stmt *stmt;
215 : : char sql[BUFSIZ];
216 : :
217 [ + - ]: 4 : assert(db != NULL);
218 : :
219 [ + - ]: 4 : if (path == NULL)
220 : 0 : return (NULL);
221 : :
222 : 8 : sqlite3_snprintf(sizeof(sql), sql,
223 : : "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
224 : : "p.version, p.comment, p.desc, "
225 : : "p.message, p.arch, p.maintainer, p.www, "
226 : : "p.prefix, p.flatsize, p.time "
227 : : "FROM packages AS p "
228 : : "LEFT JOIN files AS f ON p.id = f.package_id "
229 : 4 : "WHERE f.path %s ?1 GROUP BY p.id;", glob ? "GLOB" : "=");
230 : :
231 : 4 : pkg_debug(4, "Pkgdb: running '%s'", sql);
232 [ - + ]: 4 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
233 : 0 : ERROR_SQLITE(db->sqlite, sql);
234 : 0 : return (NULL);
235 : : }
236 : :
237 : 4 : sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT);
238 : :
239 : 4 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
240 : 4 : }
241 : :
242 : : struct pkgdb_it *
243 : 0 : pkgdb_query_shlib_require(struct pkgdb *db, const char *shlib)
244 : : {
245 : : sqlite3_stmt *stmt;
246 : 0 : const char sql[] = ""
247 : : "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
248 : : "p.version, p.comment, p.desc, "
249 : : "p.message, p.arch, p.maintainer, p.www, "
250 : : "p.prefix, p.flatsize, p.time "
251 : : "FROM packages AS p, pkg_shlibs_required AS ps, shlibs AS s "
252 : : "WHERE p.id = ps.package_id "
253 : : "AND ps.shlib_id = s.id "
254 : : "AND s.name = ?1;";
255 : :
256 [ # # ]: 0 : assert(db != NULL);
257 : :
258 : 0 : pkg_debug(4, "Pkgdb: running '%s'", sql);
259 [ # # ]: 0 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
260 : 0 : ERROR_SQLITE(db->sqlite, sql);
261 : 0 : return (NULL);
262 : : }
263 : :
264 : 0 : sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
265 : :
266 : 0 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
267 : 0 : }
268 : :
269 : : struct pkgdb_it *
270 : 4 : pkgdb_query_shlib_provide(struct pkgdb *db, const char *shlib)
271 : : {
272 : : sqlite3_stmt *stmt;
273 : 4 : const char sql[] = ""
274 : : "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
275 : : "p.version, p.comment, p.desc, "
276 : : "p.message, p.arch, p.maintainer, p.www, "
277 : : "p.prefix, p.flatsize, p.manifestdigest, p.time "
278 : : "FROM packages AS p, pkg_shlibs_provided AS ps, shlibs AS s "
279 : : "WHERE p.id = ps.package_id "
280 : : "AND ps.shlib_id = s.id "
281 : : "AND s.name = ?1;";
282 : :
283 [ + - ]: 4 : assert(db != NULL);
284 : :
285 : 4 : pkg_debug(4, "Pkgdb: running '%s'", sql);
286 [ - + ]: 4 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
287 : 0 : ERROR_SQLITE(db->sqlite, sql);
288 : 0 : return (NULL);
289 : : }
290 : :
291 : 4 : sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
292 : :
293 : 4 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
294 : 4 : }
295 : :
296 : : struct pkgdb_it *
297 : 0 : pkgdb_query_require(struct pkgdb *db, const char *req)
298 : : {
299 : : sqlite3_stmt *stmt;
300 : 0 : const char sql[] = ""
301 : : "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
302 : : "p.version, p.comment, p.desc, "
303 : : "p.message, p.arch, p.maintainer, p.www, "
304 : : "p.prefix, p.flatsize, p.time "
305 : : "FROM packages AS p, pkg_requires AS ps, requires AS s "
306 : : "WHERE p.id = ps.package_id "
307 : : "AND ps.require_id = s.id "
308 : : "AND s.require = ?1;";
309 : :
310 [ # # ]: 0 : assert(db != NULL);
311 : :
312 : 0 : pkg_debug(4, "Pkgdb: running '%s'", sql);
313 [ # # ]: 0 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
314 : 0 : ERROR_SQLITE(db->sqlite, sql);
315 : 0 : return (NULL);
316 : : }
317 : :
318 : 0 : sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
319 : :
320 : 0 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
321 : 0 : }
322 : :
323 : : struct pkgdb_it *
324 : 20 : pkgdb_query_provide(struct pkgdb *db, const char *req)
325 : : {
326 : : sqlite3_stmt *stmt;
327 : 20 : const char sql[] = ""
328 : : "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
329 : : "p.version, p.comment, p.desc, "
330 : : "p.message, p.arch, p.maintainer, p.www, "
331 : : "p.prefix, p.flatsize, p.time "
332 : : "FROM packages AS p, pkg_provides AS ps, provides AS s "
333 : : "WHERE p.id = ps.package_id "
334 : : "AND ps.provide_id = s.id "
335 : : "AND s.provide = ?1;";
336 : :
337 [ + - ]: 20 : assert(db != NULL);
338 : :
339 : 20 : pkg_debug(4, "Pkgdb: running '%s'", sql);
340 [ - + ]: 20 : if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
341 : 0 : ERROR_SQLITE(db->sqlite, sql);
342 : 0 : return (NULL);
343 : : }
344 : :
345 : 20 : sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
346 : :
347 : 20 : return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
348 : 20 : }
349 : :
350 : : struct pkgdb_it *
351 : 1032 : pkgdb_repo_query_cond(struct pkgdb *db, const char *cond, const char *pattern, match_t match,
352 : : const char *repo)
353 : : {
354 : : struct pkgdb_it *it;
355 : : struct pkg_repo_it *rit;
356 : : struct _pkg_repo_list_item *cur;
357 : :
358 : 1032 : it = pkgdb_it_new_repo(db);
359 [ - + ]: 1032 : if (it == NULL)
360 : 0 : return (NULL);
361 : :
362 [ + + ]: 2274 : LL_FOREACH(db->repos, cur) {
363 [ + + - + ]: 1242 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
364 : 1242 : rit = cur->repo->ops->query(cur->repo, cond, pattern, match);
365 [ + - ]: 1242 : if (rit != NULL)
366 : 1242 : pkgdb_it_repo_attach(it, rit);
367 : 1242 : }
368 : 1242 : }
369 : :
370 : 1032 : return (it);
371 : 1032 : }
372 : :
373 : 1000 : struct pkgdb_it *pkgdb_repo_query(struct pkgdb *db, const char *pattern,
374 : : match_t match, const char *repo)
375 : : {
376 : 1000 : return pkgdb_repo_query_cond(db, NULL, pattern, match, repo);
377 : : }
378 : :
379 : : struct pkgdb_it *
380 : 0 : pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo)
381 : : {
382 : : struct pkgdb_it *it;
383 : : struct pkg_repo_it *rit;
384 : : struct _pkg_repo_list_item *cur;
385 : :
386 : 0 : it = pkgdb_it_new_repo(db);
387 [ # # ]: 0 : if (it == NULL)
388 : 0 : return (NULL);
389 : :
390 [ # # ]: 0 : LL_FOREACH(db->repos, cur) {
391 [ # # # # ]: 0 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
392 [ # # ]: 0 : if (cur->repo->ops->shlib_required != NULL) {
393 : 0 : rit = cur->repo->ops->shlib_required(cur->repo, require);
394 [ # # ]: 0 : if (rit != NULL)
395 : 0 : pkgdb_it_repo_attach(it, rit);
396 : 0 : }
397 : 0 : }
398 : 0 : }
399 : :
400 : 0 : return (it);
401 : 0 : }
402 : :
403 : : struct pkgdb_it *
404 : 4 : pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo)
405 : : {
406 : : struct pkgdb_it *it;
407 : : struct pkg_repo_it *rit;
408 : : struct _pkg_repo_list_item *cur;
409 : :
410 : 4 : it = pkgdb_it_new_repo(db);
411 [ - + ]: 4 : if (it == NULL)
412 : 0 : return (NULL);
413 : :
414 [ + + ]: 8 : LL_FOREACH(db->repos, cur) {
415 [ - + # # ]: 4 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
416 [ + - ]: 4 : if (cur->repo->ops->shlib_required != NULL) {
417 : 4 : rit = cur->repo->ops->shlib_provided(cur->repo, require);
418 [ - + ]: 4 : if (rit != NULL)
419 : 4 : pkgdb_it_repo_attach(it, rit);
420 : 4 : }
421 : 4 : }
422 : 4 : }
423 : :
424 : 4 : return (it);
425 : 4 : }
426 : :
427 : : struct pkgdb_it *
428 : 0 : pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
429 : : {
430 : : struct pkgdb_it *it;
431 : : struct pkg_repo_it *rit;
432 : : struct _pkg_repo_list_item *cur;
433 : :
434 : 0 : it = pkgdb_it_new_repo(db);
435 [ # # ]: 0 : if (it == NULL)
436 : 0 : return (NULL);
437 : :
438 [ # # ]: 0 : LL_FOREACH(db->repos, cur) {
439 [ # # # # ]: 0 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
440 [ # # ]: 0 : if (cur->repo->ops->required != NULL) {
441 : 0 : rit = cur->repo->ops->required(cur->repo, require);
442 [ # # ]: 0 : if (rit != NULL)
443 : 0 : pkgdb_it_repo_attach(it, rit);
444 : 0 : }
445 : 0 : }
446 : 0 : }
447 : :
448 : 0 : return (it);
449 : 0 : }
450 : :
451 : : struct pkgdb_it *
452 : 20 : pkgdb_repo_provide(struct pkgdb *db, const char *require, const char *repo)
453 : : {
454 : : struct pkgdb_it *it;
455 : : struct pkg_repo_it *rit;
456 : : struct _pkg_repo_list_item *cur;
457 : :
458 : 20 : it = pkgdb_it_new_repo(db);
459 [ - + ]: 20 : if (it == NULL)
460 : 0 : return (NULL);
461 : :
462 [ + + ]: 40 : LL_FOREACH(db->repos, cur) {
463 [ - + # # ]: 20 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
464 [ + - ]: 20 : if (cur->repo->ops->required != NULL) {
465 : 20 : rit = cur->repo->ops->provided(cur->repo, require);
466 [ - + ]: 20 : if (rit != NULL)
467 : 20 : pkgdb_it_repo_attach(it, rit);
468 : 20 : }
469 : 20 : }
470 : 20 : }
471 : :
472 : 20 : return (it);
473 : 20 : }
474 : : struct pkgdb_it *
475 : 16 : pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
476 : : pkgdb_field field, pkgdb_field sort, const char *repo)
477 : : {
478 : : struct pkgdb_it *it;
479 : : struct pkg_repo_it *rit;
480 : : struct _pkg_repo_list_item *cur;
481 : :
482 : 16 : it = pkgdb_it_new_repo(db);
483 [ - + ]: 16 : if (it == NULL)
484 : 0 : return (NULL);
485 : :
486 [ + + ]: 32 : LL_FOREACH(db->repos, cur) {
487 [ - + # # ]: 16 : if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
488 [ + - ]: 16 : if (cur->repo->ops->search != NULL) {
489 : 32 : rit = cur->repo->ops->search(cur->repo, pattern, match,
490 : 16 : field, sort);
491 [ - + ]: 16 : if (rit != NULL)
492 : 16 : pkgdb_it_repo_attach(it, rit);
493 : 16 : }
494 : 16 : }
495 : 16 : }
496 : :
497 : 16 : return (it);
498 : 16 : }
|