librazor/importer.c
author James Bowes <jbowes@redhat.com>
Wed Jul 09 10:11:13 2008 -0400 (2008-07-09)
changeset 318 829d6711b316
parent 269 03fc85294bc9
child 359 c9c90315ea24
permissions -rw-r--r--
Use strings to identify section types in the on-disk repo format.

Previously, a given razor file type had a fixed number of sections in a
fixed order, identified by an integer type. Now, sections are identified
by a named string (stored in a string pool after the section lists).

This will allow for razor files to contain arbitrary sections.

For bonus points, also drop the 4k section alignment and change the
magic byte string to "RZDB".

committer: Kristian H?gsberg <krh@redhat.com>
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;
krh@248
   370
	uint32_t name, *r;
krh@248
   371
	char dirname[256];
krh@248
   372
	struct import_directory *d, root;
krh@248
   373
	struct razor_entry *e;
krh@248
   374
krh@248
   375
	count = importer->files.size / sizeof (struct import_entry);
krh@248
   376
	razor_qsort_with_data(importer->files.data,
krh@248
   377
			      count,
krh@248
   378
			      sizeof (struct import_entry),
krh@248
   379
			      compare_filenames,
krh@248
   380
			      NULL);
krh@248
   381
jbowes@264
   382
	root.name = hashtable_tokenize(&importer->file_table, "");
krh@248
   383
	array_init(&root.files);
krh@248
   384
	array_init(&root.packages);
krh@248
   385
	root.last = NULL;
krh@248
   386
krh@248
   387
	filenames = importer->files.data;
krh@248
   388
	for (i = 0; i < count; i++) {
krh@248
   389
		f = filenames[i].name;
krh@248
   390
		if (*f != '/')
krh@248
   391
			continue;
krh@248
   392
		f++;
krh@248
   393
krh@248
   394
		d = &root;
krh@248
   395
		while (*f) {
krh@248
   396
			end = strchr(f, '/');
krh@248
   397
			if (end == NULL)
krh@248
   398
				end = f + strlen(f);
krh@248
   399
			length = end - f;
krh@248
   400
			memcpy(dirname, f, length);
krh@248
   401
			dirname[length] ='\0';
jbowes@264
   402
			name = hashtable_tokenize(&importer->file_table,
jbowes@264
   403
						  dirname);
krh@248
   404
			if (d->last == NULL || d->last->name != name) {
krh@248
   405
				d->last = array_add(&d->files, sizeof *d);
krh@248
   406
				d->last->name = name;
krh@248
   407
				d->last->last = NULL;
krh@248
   408
				array_init(&d->last->files);
krh@248
   409
				array_init(&d->last->packages);
krh@248
   410
			}
krh@248
   411
			d = d->last;
krh@248
   412
			f = end + 1;
krh@248
   413
			if (*end == '\0')
krh@248
   414
				break;
krh@248
   415
		}
krh@248
   416
krh@248
   417
		r = array_add(&d->packages, sizeof *r);
krh@248
   418
		*r = filenames[i].package;
krh@248
   419
		free(filenames[i].name);
krh@248
   420
	}
krh@248
   421
krh@248
   422
	count_entries(&root);
krh@248
   423
	e = importer->set->files.data;
krh@248
   424
	e->name = root.name;
krh@248
   425
	e->flags = RAZOR_ENTRY_LAST;
krh@248
   426
	e->start = importer->files.size ? 1 : 0;
krh@248
   427
	list_set_empty(&e->packages);
krh@248
   428
krh@248
   429
	serialize_files(importer->set, &root, &importer->set->files);
krh@248
   430
krh@248
   431
	array_release(&importer->files);
krh@248
   432
}
krh@248
   433
krh@248
   434
static void
krh@248
   435
list_to_array(struct list *list, struct array *array)
krh@248
   436
{
krh@248
   437
	uint32_t *item;
krh@248
   438
krh@248
   439
	while (list) {
krh@248
   440
		 item = array_add(array, sizeof *item);
krh@248
   441
		 *item = list->data;
krh@248
   442
		 list = list_next(list);
krh@248
   443
	}
krh@248
   444
}
krh@248
   445
krh@248
   446
static int
krh@248
   447
compare_file_requires(const void *p1, const void *p2, void *data)
krh@248
   448
{
krh@248
   449
	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
krh@248
   450
	const char *pool = data;
krh@248
   451
krh@248
   452
	return strcmp(&pool[*f1], &pool[*f2]);
krh@248
   453
}
krh@248
   454
krh@248
   455
static void
krh@248
   456
find_file_provides(struct razor_importer *importer)
krh@248
   457
{
krh@248
   458
	struct razor_property *prop;
krh@248
   459
	struct razor_entry *top, *entry;
krh@248
   460
	struct razor_package *packages;
krh@248
   461
	struct array pkgprops;
krh@248
   462
	struct list *pkg;
krh@248
   463
	uint32_t *req, *req_start, *req_end;
krh@248
   464
	uint32_t *map, *newprop;
krh@248
   465
	char *pool;
krh@248
   466
krh@248
   467
	pool = importer->set->string_pool.data;
krh@248
   468
	packages = importer->set->packages.data;
krh@248
   469
	top = importer->set->files.data;
krh@248
   470
krh@248
   471
	req = req_start = importer->file_requires.data;
krh@248
   472
	req_end = importer->file_requires.data + importer->file_requires.size;
krh@248
   473
	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
krh@248
   474
				    compare_file_requires, pool);
krh@248
   475
	free(map);
krh@248
   476
krh@248
   477
	for (req = req_start; req < req_end; req++) {
krh@248
   478
		if (req > req_start && req[0] == req[-1])
krh@248
   479
			continue;
krh@248
   480
		entry = razor_set_find_entry(importer->set, top, &pool[*req]);
krh@248
   481
		if (!entry)
krh@248
   482
			continue;
krh@248
   483
krh@248
   484
		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
krh@248
   485
			prop = array_add(&importer->set->properties, sizeof *prop);
krh@248
   486
			prop->name = *req;
krh@248
   487
			prop->flags =
krh@248
   488
				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
krh@248
   489
			prop->version = hashtable_tokenize(&importer->table, "");
krh@248
   490
			list_set_ptr(&prop->packages, pkg->data);
krh@248
   491
krh@248
   492
			/* Update property list of pkg */
krh@248
   493
			array_init(&pkgprops);
krh@248
   494
			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
krh@248
   495
			newprop = array_add(&pkgprops, sizeof *newprop);
krh@248
   496
			*newprop = prop - (struct razor_property *)importer->set->properties.data;
krh@248
   497
			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
krh@248
   498
			array_release(&pkgprops);
krh@248
   499
		}
krh@248
   500
	}
krh@248
   501
krh@248
   502
	array_release(&importer->file_requires);
krh@248
   503
}
krh@248
   504
krh@248
   505
static void
krh@248
   506
build_package_file_lists(struct razor_set *set, uint32_t *rmap)
krh@248
   507
{
krh@248
   508
	struct razor_package *p, *packages;
krh@248
   509
	struct array *pkgs;
krh@248
   510
	struct razor_entry *e, *end;
krh@248
   511
	struct list *r;
krh@248
   512
	uint32_t *q;
krh@248
   513
	int i, count;
krh@248
   514
krh@248
   515
	count = set->packages.size / sizeof *p;
krh@248
   516
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   517
krh@248
   518
	end = set->files.data + set->files.size;
krh@248
   519
	for (e = set->files.data; e < end; e++) {
krh@248
   520
		list_remap_head(&e->packages, rmap);
krh@248
   521
		r = list_first(&e->packages, &set->package_pool);
krh@248
   522
		while (r) {
krh@248
   523
			q = array_add(&pkgs[r->data], sizeof *q);
krh@248
   524
			*q = e - (struct razor_entry *) set->files.data;
krh@248
   525
			r = list_next(r);
krh@248
   526
		}
krh@248
   527
	}
krh@248
   528
krh@248
   529
	packages = set->packages.data;
krh@248
   530
	for (i = 0; i < count; i++) {
krh@248
   531
		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
krh@248
   532
		array_release(&pkgs[i]);
krh@248
   533
	}
krh@248
   534
	free(pkgs);
krh@248
   535
}
krh@248
   536
krh@309
   537
/**
krh@309
   538
 * razor_importer_finish:
krh@309
   539
 * @importer: the %razor_importer
krh@309
   540
 *
krh@309
   541
 * Finish importing packages and create the package set.  This sorts
krh@309
   542
 * and indexes all the packages, properties and files in the importer
krh@309
   543
 * and creates a new %razor_set.  After creating the new package set,
krh@309
   544
 * the importer is destroyed.
krh@309
   545
 *
krh@309
   546
 * Returns: the new %razor_set
krh@309
   547
 **/
krh@269
   548
RAZOR_EXPORT struct razor_set *
krh@248
   549
razor_importer_finish(struct razor_importer *importer)
krh@248
   550
{
krh@248
   551
	struct razor_set *set;
krh@248
   552
	uint32_t *map, *rmap;
krh@248
   553
	int i, count;
krh@248
   554
krh@248
   555
	build_file_tree(importer);
krh@248
   556
	find_file_provides(importer);
krh@248
   557
krh@248
   558
	map = uniqueify_properties(importer->set);
krh@248
   559
	list_remap_pool(&importer->set->property_pool, map);
krh@248
   560
	free(map);
krh@248
   561
krh@248
   562
	count = importer->set->packages.size / sizeof(struct razor_package);
krh@248
   563
	map = razor_qsort_with_data(importer->set->packages.data,
krh@248
   564
				    count,
krh@248
   565
				    sizeof(struct razor_package),
krh@248
   566
				    compare_packages,
krh@248
   567
				    importer->set);
krh@248
   568
krh@248
   569
	rmap = malloc(count * sizeof *rmap);
krh@248
   570
	for (i = 0; i < count; i++)
krh@248
   571
		rmap[map[i]] = i;
krh@248
   572
	free(map);
krh@248
   573
krh@248
   574
	list_remap_pool(&importer->set->package_pool, rmap);
krh@248
   575
	build_package_file_lists(importer->set, rmap);
krh@248
   576
	remap_property_package_links(&importer->set->properties, rmap);
krh@248
   577
	free(rmap);
krh@248
   578
krh@248
   579
	set = importer->set;
krh@248
   580
	hashtable_release(&importer->table);
jbowes@264
   581
	hashtable_release(&importer->details_table);
jbowes@264
   582
	hashtable_release(&importer->file_table);
krh@248
   583
	free(importer);
krh@248
   584
krh@248
   585
	return set;
krh@248
   586
}