librazor/importer.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Apr 29 17:00:01 2009 +0100 (2009-04-29)
changeset 361 2523d03a840e
parent 309 a69289c9080c
child 369 f8c27fe9fe63
permissions -rw-r--r--
Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
krh@248
     1
/*
krh@248
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
krh@248
     3
 * Copyright (C) 2008  Red Hat, Inc
krh@248
     4
 *
krh@248
     5
 * This program is free software; you can redistribute it and/or modify
krh@248
     6
 * it under the terms of the GNU General Public License as published by
krh@248
     7
 * the Free Software Foundation; either version 2 of the License, or
krh@248
     8
 * (at your option) any later version.
krh@248
     9
 *
krh@248
    10
 * This program is distributed in the hope that it will be useful,
krh@248
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
krh@248
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
krh@248
    13
 * GNU General Public License for more details.
krh@248
    14
 *
krh@248
    15
 * You should have received a copy of the GNU General Public License along
krh@248
    16
 * with this program; if not, write to the Free Software Foundation, Inc.,
krh@248
    17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
krh@248
    18
 */
krh@248
    19
krh@248
    20
#define _GNU_SOURCE
krh@248
    21
krh@248
    22
#include <string.h>
krh@248
    23
#include "razor-internal.h"
krh@248
    24
#include "razor.h"
krh@248
    25
krh@309
    26
/**
krh@309
    27
 * razor_importer_create:
krh@309
    28
 *
krh@309
    29
 * Create a new %razor_importer.
krh@309
    30
 *
krh@309
    31
 * Returns: the new %razor_importer.
krh@309
    32
 **/
krh@309
    33
RAZOR_EXPORT struct razor_importer *
krh@309
    34
razor_importer_create(void)
krh@309
    35
{
krh@309
    36
	struct razor_importer *importer;
krh@309
    37
krh@309
    38
	importer = zalloc(sizeof *importer);
krh@309
    39
	importer->set = razor_set_create();
krh@309
    40
	hashtable_init(&importer->table, &importer->set->string_pool);
krh@309
    41
	hashtable_init(&importer->details_table,
krh@309
    42
		       &importer->set->details_string_pool);
krh@309
    43
	hashtable_init(&importer->file_table,
krh@309
    44
		       &importer->set->file_string_pool);
krh@309
    45
krh@309
    46
	return importer;
krh@309
    47
}
krh@309
    48
krh@309
    49
/**
krh@309
    50
 * razor_importer_destroy:
krh@309
    51
 * @importer: the %razor_importer
krh@309
    52
 *
krh@309
    53
 * Destroy an importer without creating a %razor_set.  Normally,
krh@309
    54
 * %razor_importer_finish will create a new %razor_set and destroy the
krh@309
    55
 * importer.  If the import must be aborted without creating the set,
krh@309
    56
 * just destroy the import using this function.
krh@309
    57
 **/
krh@309
    58
RAZOR_EXPORT void
krh@309
    59
razor_importer_destroy(struct razor_importer *importer)
krh@309
    60
{
krh@309
    61
	/* FIXME: write this */
krh@309
    62
}
krh@309
    63
krh@309
    64
krh@309
    65
/**
krh@309
    66
 * razor_importer_begin_package:
krh@309
    67
 * @importer: the %razor_importer
krh@309
    68
 * @name: the name of the new package
krh@309
    69
 * @version: the version of the new package
krh@309
    70
 * @arch: the architechture of the new package.
krh@309
    71
 *
krh@309
    72
 * Begin describing a new package to the importer.  This creates a new
krh@309
    73
 * package and sets the %name, %version and %arch.  Subsequent calls
krh@309
    74
 * to %razor_importer_add_details, %razor_importer_add_property and
krh@309
    75
 * %razor_importer_add_file further describe this package and
krh@309
    76
 * %razor_importer_finish_package marks the end of meta data for this
krh@309
    77
 * package.
krh@309
    78
 **/
krh@269
    79
RAZOR_EXPORT void
krh@248
    80
razor_importer_begin_package(struct razor_importer *importer,
krh@248
    81
			     const char *name,
krh@248
    82
			     const char *version,
krh@248
    83
			     const char *arch)
krh@248
    84
{
krh@248
    85
	struct razor_package *p;
krh@248
    86
krh@248
    87
	p = array_add(&importer->set->packages, sizeof *p);
krh@248
    88
	p->name = hashtable_tokenize(&importer->table, name);
krh@248
    89
	p->flags = 0;
krh@248
    90
	p->version = hashtable_tokenize(&importer->table, version);
krh@248
    91
	p->arch = hashtable_tokenize(&importer->table, arch);
krh@248
    92
krh@248
    93
	importer->package = p;
krh@248
    94
	array_init(&importer->properties);
krh@248
    95
}
krh@248
    96
krh@309
    97
/**
krh@309
    98
 * razor_importer_finish_package:
krh@309
    99
 * @importer: the %razor_importer
krh@309
   100
 *
krh@309
   101
 * Tells the importer that the current package is complete.
krh@309
   102
 **/
krh@269
   103
RAZOR_EXPORT void
krh@248
   104
razor_importer_finish_package(struct razor_importer *importer)
krh@248
   105
{
krh@248
   106
	list_set_array(&importer->package->properties,
krh@248
   107
		       &importer->set->property_pool,
krh@248
   108
		       &importer->properties,
krh@248
   109
		       1);
krh@248
   110
krh@248
   111
	array_release(&importer->properties);
krh@248
   112
}
krh@248
   113
krh@309
   114
/**
krh@309
   115
 * razor_importer_add_details:
krh@309
   116
 * @importer: the %razor_importer
krh@309
   117
 * @summary: the package summary
krh@309
   118
 * @description: the package description
krh@309
   119
 * @url: the package url
krh@309
   120
 * @license: the package license
krh@309
   121
 *
krh@309
   122
 * Provide additional information for the current package.
krh@309
   123
 **/
krh@269
   124
RAZOR_EXPORT void
jbowes@258
   125
razor_importer_add_details(struct razor_importer *importer,
jbowes@258
   126
			   const char *summary,
jbowes@258
   127
			   const char *description,
jbowes@258
   128
			   const char *url,
jbowes@258
   129
			   const char *license)
jbowes@258
   130
{
jbowes@258
   131
	importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
jbowes@258
   132
	importer->package->description = hashtable_tokenize(&importer->details_table, description);
jbowes@258
   133
	importer->package->url = hashtable_tokenize(&importer->details_table, url);
jbowes@258
   134
	importer->package->license = hashtable_tokenize(&importer->details_table, license);
jbowes@258
   135
}
jbowes@258
   136
krh@309
   137
/**
krh@309
   138
 * razor_importer_add_property:
krh@309
   139
 * @importer: the %razor_importer
krh@309
   140
 * @name: name of the property
krh@309
   141
 * @flags: property flags
krh@309
   142
 * @version: version of the property or %NULL
krh@309
   143
 *
krh@309
   144
 * Add a property for the current package.  The %flags parameter
krh@309
   145
 * determines the type of the property and optionally the relation to
krh@309
   146
 * the specified version and the availability constraint.  See
krh@309
   147
 * %razor_property_flags for further information about the flag
krh@309
   148
 * parameter.
krh@309
   149
 **/
krh@269
   150
RAZOR_EXPORT void
krh@248
   151
razor_importer_add_property(struct razor_importer *importer,
krh@248
   152
			    const char *name,
krh@248
   153
			    uint32_t flags,
krh@248
   154
			    const char *version)
krh@248
   155
{
krh@248
   156
	struct razor_property *p;
krh@248
   157
	uint32_t *r;
krh@248
   158
krh@248
   159
	p = array_add(&importer->set->properties, sizeof *p);
krh@248
   160
	p->name = hashtable_tokenize(&importer->table, name);
krh@248
   161
	p->flags = flags;
krh@248
   162
	p->version = hashtable_tokenize(&importer->table, version);
krh@248
   163
	list_set_ptr(&p->packages, importer->package -
krh@248
   164
		     (struct razor_package *) importer->set->packages.data);
krh@248
   165
krh@248
   166
	r = array_add(&importer->properties, sizeof *r);
krh@248
   167
	*r = p - (struct razor_property *) importer->set->properties.data;
krh@248
   168
krh@248
   169
	if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
krh@248
   170
	    *name == '/') {
krh@248
   171
		r = array_add(&importer->file_requires, sizeof *r);
krh@248
   172
		*r = p->name;
krh@248
   173
	}
krh@248
   174
}
krh@248
   175
krh@309
   176
/**
krh@309
   177
 * razor_importer_add_file:
krh@309
   178
 * @importer: the %razor_importer
krh@309
   179
 * @name: name of the file
krh@309
   180
 *
krh@309
   181
 * Add a file to the current package.
krh@309
   182
 **/
krh@269
   183
RAZOR_EXPORT void
krh@248
   184
razor_importer_add_file(struct razor_importer *importer, const char *name)
krh@248
   185
{
krh@248
   186
	struct import_entry *e;
krh@248
   187
krh@248
   188
	e = array_add(&importer->files, sizeof *e);
krh@248
   189
krh@248
   190
	e->package = importer->package -
krh@248
   191
		(struct razor_package *) importer->set->packages.data;
krh@248
   192
	e->name = strdup(name);
krh@248
   193
}
krh@248
   194
krh@248
   195
static int
krh@248
   196
compare_packages(const void *p1, const void *p2, void *data)
krh@248
   197
{
krh@248
   198
	const struct razor_package *pkg1 = p1, *pkg2 = p2;
krh@248
   199
	struct razor_set *set = data;
krh@248
   200
	char *pool = set->string_pool.data;
krh@248
   201
krh@248
   202
	/* FIXME: what if the flags are different? */
krh@248
   203
	if (pkg1->name == pkg2->name)
krh@248
   204
		return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
krh@248
   205
	else
krh@248
   206
		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
krh@248
   207
}
krh@248
   208
krh@248
   209
static int
krh@248
   210
compare_properties(const void *p1, const void *p2, void *data)
krh@248
   211
{
krh@248
   212
	const struct razor_property *prop1 = p1, *prop2 = p2;
krh@248
   213
	struct razor_set *set = data;
krh@248
   214
	char *pool = set->string_pool.data;
krh@248
   215
krh@248
   216
	if (prop1->name != prop2->name)
krh@248
   217
		return strcmp(&pool[prop1->name], &pool[prop2->name]);
krh@248
   218
	else if (prop1->flags != prop2->flags)
krh@248
   219
		return prop1->flags - prop2->flags;
krh@257
   220
	else if (prop1->version != prop2->version)
krh@257
   221
		return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
krh@248
   222
	else
krh@257
   223
		return prop1->packages.list_ptr - prop2->packages.list_ptr;
krh@248
   224
}
krh@248
   225
krh@248
   226
static uint32_t *
krh@248
   227
uniqueify_properties(struct razor_set *set)
krh@248
   228
{
krh@248
   229
	struct razor_property *rp, *up, *rp_end;
krh@248
   230
	struct array *pkgs, *p;
krh@248
   231
	struct list_head *r;
krh@248
   232
	uint32_t *map, *rmap;
krh@248
   233
	int i, count, unique;
krh@248
   234
krh@248
   235
	count = set->properties.size / sizeof(struct razor_property);
krh@248
   236
	map = razor_qsort_with_data(set->properties.data,
krh@248
   237
				    count,
krh@248
   238
				    sizeof(struct razor_property),
krh@248
   239
				    compare_properties,
krh@248
   240
				    set);
krh@248
   241
krh@248
   242
	rp_end = set->properties.data + set->properties.size;
krh@248
   243
	rmap = malloc(count * sizeof *map);
krh@248
   244
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   245
	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
krh@248
   246
		if (rp->name != up->name ||
krh@248
   247
		    rp->flags != up->flags ||
krh@248
   248
		    rp->version != up->version) {
krh@248
   249
			up++;
krh@248
   250
			up->name = rp->name;
krh@248
   251
			up->flags = rp->flags;
krh@248
   252
			up->version = rp->version;
krh@248
   253
		}
krh@248
   254
krh@248
   255
		unique = up - (struct razor_property *) set->properties.data;
krh@248
   256
		rmap[map[i]] = unique;
krh@248
   257
		r = array_add(&pkgs[unique], sizeof *r);
krh@248
   258
		*r = rp->packages;
krh@248
   259
	}
krh@248
   260
	free(map);
krh@248
   261
krh@248
   262
	if (up != rp)
krh@248
   263
		up++;
krh@248
   264
	set->properties.size = (void *) up - set->properties.data;
krh@248
   265
	rp_end = up;
krh@248
   266
	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
krh@248
   267
		list_set_array(&rp->packages, &set->package_pool, p, 0);
krh@248
   268
		array_release(p);
krh@248
   269
	}
krh@248
   270
krh@248
   271
	free(pkgs);
krh@248
   272
krh@248
   273
	return rmap;
krh@248
   274
}
krh@248
   275
krh@248
   276
static int
krh@248
   277
compare_filenames(const void *p1, const void *p2, void *data)
krh@248
   278
{
krh@248
   279
	const struct import_entry *e1 = p1;
krh@248
   280
	const struct import_entry *e2 = p2;
krh@248
   281
	const char *n1 = e1->name;
krh@248
   282
	const char *n2 = e2->name;
krh@248
   283
krh@248
   284
	/* Need to make sure that the contents of a directory
krh@248
   285
	 * are sorted immediately after it. So "foo/bar" has to
krh@248
   286
	 * sort before "foo.conf"
krh@248
   287
	 *
krh@248
   288
	 * FIXME: this is about 60% slower than strcmp
krh@248
   289
	 */
krh@248
   290
	while (*n1 && *n2) {
krh@248
   291
		if (*n1 < *n2)
krh@248
   292
			return *n2 == '/' ? 1 : -1;
krh@248
   293
		else if (*n1 > *n2)
krh@248
   294
			return *n1 == '/' ? -1 : 1;
krh@248
   295
		n1++;
krh@248
   296
		n2++;
krh@248
   297
	}
krh@248
   298
	if (*n1)
krh@248
   299
		return 1;
krh@248
   300
	else if (*n2)
krh@248
   301
		return -1;
krh@248
   302
	else
krh@248
   303
		return 0;
krh@248
   304
}
krh@248
   305
krh@248
   306
static void
krh@248
   307
count_entries(struct import_directory *d)
krh@248
   308
{
krh@248
   309
	struct import_directory *p, *end;
krh@248
   310
krh@248
   311
	p = d->files.data;
krh@248
   312
	end = d->files.data + d->files.size;
krh@248
   313
	d->count = 0;
krh@248
   314
	while (p < end) {
krh@248
   315
		count_entries(p);
krh@248
   316
		d->count += p->count + 1;
krh@248
   317
		p++;
krh@248
   318
	}
krh@248
   319
}
krh@248
   320
krh@248
   321
static void
krh@248
   322
serialize_files(struct razor_set *set,
krh@248
   323
		struct import_directory *d, struct array *array)
krh@248
   324
{
krh@248
   325
	struct import_directory *p, *end;
krh@248
   326
	struct razor_entry *e = NULL;
krh@248
   327
	uint32_t s;
krh@248
   328
krh@248
   329
	p = d->files.data;
krh@248
   330
	end = d->files.data + d->files.size;
krh@248
   331
	s = array->size / sizeof *e + d->files.size / sizeof *p;
krh@248
   332
	while (p < end) {
krh@248
   333
		e = array_add(array, sizeof *e);
krh@248
   334
		e->name = p->name;
krh@248
   335
		e->flags = 0;
krh@248
   336
		e->start = p->count > 0 ? s : 0;
krh@248
   337
		s += p->count;
krh@248
   338
krh@248
   339
		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
krh@248
   340
		array_release(&p->packages);
krh@248
   341
		p++;
krh@248
   342
	}
krh@248
   343
	if (e != NULL)
krh@248
   344
		e->flags |= RAZOR_ENTRY_LAST;
krh@248
   345
krh@248
   346
	p = d->files.data;
krh@248
   347
	end = d->files.data + d->files.size;
krh@248
   348
	while (p < end) {
krh@248
   349
		serialize_files(set, p, array);
krh@248
   350
		p++;
krh@248
   351
	}
krh@248
   352
}
krh@248
   353
krh@248
   354
static void
krh@248
   355
remap_property_package_links(struct array *properties, uint32_t *rmap)
krh@248
   356
{
krh@248
   357
	struct razor_property *p, *end;
krh@248
   358
krh@248
   359
	end = properties->data + properties->size;
krh@248
   360
	for (p = properties->data; p < end; p++)
krh@248
   361
		list_remap_head(&p->packages, rmap);
krh@248
   362
}
krh@248
   363
krh@248
   364
static void
krh@248
   365
build_file_tree(struct razor_importer *importer)
krh@248
   366
{
krh@248
   367
	int count, i, length;
krh@248
   368
	struct import_entry *filenames;
krh@248
   369
	char *f, *end;
ali@359
   370
	uint32_t name, *r, s;
ali@359
   371
	char rootname[256], dirname[256];
ali@359
   372
	struct import_directory *d, *last_root;
ali@359
   373
	struct array roots;
krh@248
   374
	struct razor_entry *e;
krh@248
   375
krh@248
   376
	count = importer->files.size / sizeof (struct import_entry);
ali@359
   377
	filenames = importer->files.data;
ali@359
   378
	razor_qsort_with_data(filenames,
krh@248
   379
			      count,
krh@248
   380
			      sizeof (struct import_entry),
krh@248
   381
			      compare_filenames,
krh@248
   382
			      NULL);
krh@248
   383
ali@359
   384
	array_init(&roots);
ali@359
   385
	last_root = NULL;
krh@248
   386
krh@248
   387
	for (i = 0; i < count; i++) {
krh@248
   388
		f = filenames[i].name;
ali@359
   389
		d = NULL;
krh@248
   390
		while (*f) {
krh@248
   391
			end = strchr(f, '/');
krh@248
   392
			if (end == NULL)
krh@248
   393
				end = f + strlen(f);
krh@248
   394
			length = end - f;
krh@248
   395
			memcpy(dirname, f, length);
ali@359
   396
			dirname[length] = '\0';
jbowes@264
   397
			name = hashtable_tokenize(&importer->file_table,
jbowes@264
   398
						  dirname);
ali@359
   399
			if (!d) {
ali@359
   400
				if (!last_root || last_root->name != name) {
ali@359
   401
					d = array_add(&roots, sizeof *d);
ali@359
   402
					d->name = name;
ali@359
   403
					d->last = NULL;
ali@359
   404
					array_init(&d->files);
ali@359
   405
					array_init(&d->packages);
ali@359
   406
					last_root = d;
ali@359
   407
				}
ali@359
   408
				d = last_root;
ali@359
   409
			} else {
ali@359
   410
				if (!d->last || d->last->name != name) {
ali@359
   411
					d->last = array_add(&d->files,
ali@359
   412
							    sizeof *d);
ali@359
   413
					d->last->name = name;
ali@359
   414
					d->last->last = NULL;
ali@359
   415
					array_init(&d->last->files);
ali@359
   416
					array_init(&d->last->packages);
ali@359
   417
				}
ali@359
   418
				d = d->last;
krh@248
   419
			}
krh@248
   420
			f = end + 1;
krh@248
   421
			if (*end == '\0')
krh@248
   422
				break;
krh@248
   423
		}
krh@248
   424
krh@248
   425
		r = array_add(&d->packages, sizeof *r);
krh@248
   426
		*r = filenames[i].package;
krh@248
   427
		free(filenames[i].name);
krh@248
   428
	}
krh@248
   429
ali@359
   430
	count = roots.size / sizeof (struct import_directory);
ali@359
   431
	d = roots.data;
ali@359
   432
	s = count;
ali@359
   433
	for (i = 0; i < count; i++) {
ali@359
   434
		count_entries(d);
ali@359
   435
		if (i)
ali@359
   436
			e = array_add(&importer->set->files, sizeof *e);
ali@359
   437
		else
ali@359
   438
			e = importer->set->files.data;
ali@359
   439
		e->name = d->name;
ali@359
   440
		e->flags = 0;
ali@359
   441
		e->start = d->count > 0 ? s : 0;
ali@359
   442
		s += d->count;
ali@359
   443
		list_set_empty(&e->packages);
ali@359
   444
		d++;
ali@359
   445
	}
ali@359
   446
	if (count)
ali@359
   447
		e->flags |= RAZOR_ENTRY_LAST;
krh@248
   448
ali@359
   449
	d = roots.data;
ali@359
   450
	for (i = 0; i < count; i++) {
ali@359
   451
		serialize_files(importer->set, d, &importer->set->files);
ali@359
   452
		d++;
ali@359
   453
	}
krh@248
   454
krh@248
   455
	array_release(&importer->files);
ali@359
   456
	array_release(&roots);
krh@248
   457
}
krh@248
   458
krh@248
   459
static void
krh@248
   460
list_to_array(struct list *list, struct array *array)
krh@248
   461
{
krh@248
   462
	uint32_t *item;
krh@248
   463
krh@248
   464
	while (list) {
krh@248
   465
		 item = array_add(array, sizeof *item);
krh@248
   466
		 *item = list->data;
krh@248
   467
		 list = list_next(list);
krh@248
   468
	}
krh@248
   469
}
krh@248
   470
krh@248
   471
static int
krh@248
   472
compare_file_requires(const void *p1, const void *p2, void *data)
krh@248
   473
{
krh@248
   474
	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
krh@248
   475
	const char *pool = data;
krh@248
   476
krh@248
   477
	return strcmp(&pool[*f1], &pool[*f2]);
krh@248
   478
}
krh@248
   479
krh@248
   480
static void
krh@248
   481
find_file_provides(struct razor_importer *importer)
krh@248
   482
{
krh@248
   483
	struct razor_property *prop;
krh@248
   484
	struct razor_entry *top, *entry;
krh@248
   485
	struct razor_package *packages;
krh@248
   486
	struct array pkgprops;
krh@248
   487
	struct list *pkg;
krh@248
   488
	uint32_t *req, *req_start, *req_end;
krh@248
   489
	uint32_t *map, *newprop;
krh@248
   490
	char *pool;
krh@248
   491
krh@248
   492
	pool = importer->set->string_pool.data;
krh@248
   493
	packages = importer->set->packages.data;
krh@248
   494
	top = importer->set->files.data;
krh@248
   495
krh@248
   496
	req = req_start = importer->file_requires.data;
krh@248
   497
	req_end = importer->file_requires.data + importer->file_requires.size;
krh@248
   498
	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
krh@248
   499
				    compare_file_requires, pool);
krh@248
   500
	free(map);
krh@248
   501
krh@248
   502
	for (req = req_start; req < req_end; req++) {
krh@248
   503
		if (req > req_start && req[0] == req[-1])
krh@248
   504
			continue;
krh@248
   505
		entry = razor_set_find_entry(importer->set, top, &pool[*req]);
krh@248
   506
		if (!entry)
krh@248
   507
			continue;
krh@248
   508
krh@248
   509
		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
krh@248
   510
			prop = array_add(&importer->set->properties, sizeof *prop);
krh@248
   511
			prop->name = *req;
krh@248
   512
			prop->flags =
krh@248
   513
				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
krh@248
   514
			prop->version = hashtable_tokenize(&importer->table, "");
krh@248
   515
			list_set_ptr(&prop->packages, pkg->data);
krh@248
   516
krh@248
   517
			/* Update property list of pkg */
krh@248
   518
			array_init(&pkgprops);
krh@248
   519
			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
krh@248
   520
			newprop = array_add(&pkgprops, sizeof *newprop);
krh@248
   521
			*newprop = prop - (struct razor_property *)importer->set->properties.data;
krh@248
   522
			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
krh@248
   523
			array_release(&pkgprops);
krh@248
   524
		}
krh@248
   525
	}
krh@248
   526
krh@248
   527
	array_release(&importer->file_requires);
krh@248
   528
}
krh@248
   529
krh@248
   530
static void
krh@248
   531
build_package_file_lists(struct razor_set *set, uint32_t *rmap)
krh@248
   532
{
krh@248
   533
	struct razor_package *p, *packages;
krh@248
   534
	struct array *pkgs;
krh@248
   535
	struct razor_entry *e, *end;
krh@248
   536
	struct list *r;
krh@248
   537
	uint32_t *q;
krh@248
   538
	int i, count;
krh@248
   539
krh@248
   540
	count = set->packages.size / sizeof *p;
krh@248
   541
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   542
krh@248
   543
	end = set->files.data + set->files.size;
krh@248
   544
	for (e = set->files.data; e < end; e++) {
krh@248
   545
		list_remap_head(&e->packages, rmap);
krh@248
   546
		r = list_first(&e->packages, &set->package_pool);
krh@248
   547
		while (r) {
krh@248
   548
			q = array_add(&pkgs[r->data], sizeof *q);
krh@248
   549
			*q = e - (struct razor_entry *) set->files.data;
krh@248
   550
			r = list_next(r);
krh@248
   551
		}
krh@248
   552
	}
krh@248
   553
krh@248
   554
	packages = set->packages.data;
krh@248
   555
	for (i = 0; i < count; i++) {
krh@248
   556
		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
krh@248
   557
		array_release(&pkgs[i]);
krh@248
   558
	}
krh@248
   559
	free(pkgs);
krh@248
   560
}
krh@248
   561
krh@309
   562
/**
krh@309
   563
 * razor_importer_finish:
krh@309
   564
 * @importer: the %razor_importer
krh@309
   565
 *
krh@309
   566
 * Finish importing packages and create the package set.  This sorts
krh@309
   567
 * and indexes all the packages, properties and files in the importer
krh@309
   568
 * and creates a new %razor_set.  After creating the new package set,
krh@309
   569
 * the importer is destroyed.
krh@309
   570
 *
krh@309
   571
 * Returns: the new %razor_set
krh@309
   572
 **/
krh@269
   573
RAZOR_EXPORT struct razor_set *
krh@248
   574
razor_importer_finish(struct razor_importer *importer)
krh@248
   575
{
krh@248
   576
	struct razor_set *set;
krh@248
   577
	uint32_t *map, *rmap;
krh@248
   578
	int i, count;
krh@248
   579
krh@248
   580
	build_file_tree(importer);
krh@248
   581
	find_file_provides(importer);
krh@248
   582
krh@248
   583
	map = uniqueify_properties(importer->set);
krh@248
   584
	list_remap_pool(&importer->set->property_pool, map);
krh@248
   585
	free(map);
krh@248
   586
krh@248
   587
	count = importer->set->packages.size / sizeof(struct razor_package);
krh@248
   588
	map = razor_qsort_with_data(importer->set->packages.data,
krh@248
   589
				    count,
krh@248
   590
				    sizeof(struct razor_package),
krh@248
   591
				    compare_packages,
krh@248
   592
				    importer->set);
krh@248
   593
krh@248
   594
	rmap = malloc(count * sizeof *rmap);
krh@248
   595
	for (i = 0; i < count; i++)
krh@248
   596
		rmap[map[i]] = i;
krh@248
   597
	free(map);
krh@248
   598
krh@248
   599
	list_remap_pool(&importer->set->package_pool, rmap);
krh@248
   600
	build_package_file_lists(importer->set, rmap);
krh@248
   601
	remap_property_package_links(&importer->set->properties, rmap);
krh@248
   602
	free(rmap);
krh@248
   603
krh@248
   604
	set = importer->set;
krh@248
   605
	hashtable_release(&importer->table);
jbowes@264
   606
	hashtable_release(&importer->details_table);
jbowes@264
   607
	hashtable_release(&importer->file_table);
krh@248
   608
	free(importer);
krh@248
   609
krh@248
   610
	return set;
krh@248
   611
}