librazor/merger.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 403 e63951c1d0f8
child 458 3f841a46eab5
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
krh@248
     1
/*
krh@248
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
krh@248
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@403
     4
 * Copyright (C) 2009-2011  J. Ali Harlow <ali@juiblex.co.uk>
krh@248
     5
 *
krh@248
     6
 * This program is free software; you can redistribute it and/or modify
krh@248
     7
 * it under the terms of the GNU General Public License as published by
krh@248
     8
 * the Free Software Foundation; either version 2 of the License, or
krh@248
     9
 * (at your option) any later version.
krh@248
    10
 *
krh@248
    11
 * This program is distributed in the hope that it will be useful,
krh@248
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
krh@248
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
krh@248
    14
 * GNU General Public License for more details.
krh@248
    15
 *
krh@248
    16
 * You should have received a copy of the GNU General Public License along
krh@248
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
krh@248
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
krh@248
    19
 */
krh@248
    20
ali@438
    21
#include "config.h"
krh@248
    22
#include <string.h>
ali@369
    23
#include <assert.h>
krh@248
    24
#include "razor-internal.h"
krh@248
    25
#include "razor.h"
krh@248
    26
krh@248
    27
#define UPSTREAM_SOURCE 0x80
krh@248
    28
krh@248
    29
struct source {
krh@248
    30
	struct razor_set *set;
krh@248
    31
	uint32_t *property_map;
krh@248
    32
	uint32_t *file_map;
krh@248
    33
};
krh@248
    34
krh@248
    35
struct razor_merger {
ali@369
    36
	int committed;
krh@248
    37
	struct razor_set *set;
krh@248
    38
	struct hashtable table;
ali@348
    39
	struct hashtable file_table;
ali@394
    40
	struct hashtable details_table;
krh@248
    41
	struct source source1;
krh@248
    42
	struct source source2;
krh@248
    43
};
krh@248
    44
krh@248
    45
struct razor_merger *
krh@248
    46
razor_merger_create(struct razor_set *set1, struct razor_set *set2)
krh@248
    47
{
krh@248
    48
	struct razor_merger *merger;
krh@248
    49
	int count;
krh@248
    50
	size_t size;
ali@403
    51
	uint32_t header_version;
krh@248
    52
krh@248
    53
	merger = zalloc(sizeof *merger);
krh@248
    54
	merger->set = razor_set_create();
ali@403
    55
	if (set1->packages.size) {
ali@403
    56
		header_version = razor_set_get_header_version(set1);
ali@403
    57
		if (set2->packages.size &&
ali@403
    58
		    razor_set_get_header_version(set2) > header_version)
ali@403
    59
			header_version = razor_set_get_header_version(set2);
ali@403
    60
	} else
ali@403
    61
		header_version = razor_set_get_header_version(set2);
ali@403
    62
	razor_set_set_header_version(merger->set, header_version);
krh@248
    63
	hashtable_init(&merger->table, &merger->set->string_pool);
ali@348
    64
	hashtable_init(&merger->file_table, &merger->set->file_string_pool);
ali@394
    65
	hashtable_init(&merger->details_table,
ali@394
    66
		       &merger->set->details_string_pool);
krh@248
    67
krh@248
    68
	merger->source1.set = set1;
krh@248
    69
	count = set1->properties.size / sizeof (struct razor_property);
krh@248
    70
	size = count * sizeof merger->source1.property_map[0];
krh@248
    71
	merger->source1.property_map = zalloc(size);
krh@248
    72
	count = set1->files.size / sizeof (struct razor_entry);
krh@248
    73
	size = count * sizeof merger->source1.file_map[0];
krh@248
    74
	merger->source1.file_map = zalloc(size);
krh@248
    75
krh@248
    76
	merger->source2.set = set2;
krh@248
    77
	count = set2->properties.size / sizeof (struct razor_property);
krh@248
    78
	size = count * sizeof merger->source2.property_map[0];
krh@248
    79
	merger->source2.property_map = zalloc(size);
krh@248
    80
	count = set2->files.size / sizeof (struct razor_entry);
krh@248
    81
	size = count * sizeof merger->source2.file_map[0];
krh@248
    82
	merger->source2.file_map = zalloc(size);
krh@248
    83
krh@248
    84
	return merger;
krh@248
    85
}
krh@248
    86
krh@248
    87
void
krh@248
    88
razor_merger_add_package(struct razor_merger *merger,
krh@248
    89
			 struct razor_package *package)
krh@248
    90
{
ali@394
    91
	char *pool, *details_pool, *s;
krh@248
    92
	struct list *r;
krh@248
    93
	struct razor_package *p;
krh@248
    94
	struct razor_set *set1;
krh@248
    95
	struct source *source;
ali@372
    96
	uint32_t flags, *prefix;
ali@372
    97
	struct array install_prefixes;
krh@248
    98
ali@369
    99
	assert(merger->committed == 0);
ali@369
   100
krh@248
   101
	set1 = merger->source1.set;
krh@248
   102
	if (set1->packages.data <= (void *) package &&
krh@248
   103
	    (void *) package < set1->packages.data + set1->packages.size) {
krh@248
   104
		source = &merger->source1;
krh@248
   105
		flags = 0;
krh@248
   106
	} else {
krh@248
   107
		source = &merger->source2;
krh@248
   108
		flags = UPSTREAM_SOURCE;
krh@248
   109
	}
krh@248
   110
krh@248
   111
	pool = source->set->string_pool.data;
ali@394
   112
	details_pool = source->set->details_string_pool.data;
krh@248
   113
	p = array_add(&merger->set->packages, sizeof *p);
krh@248
   114
	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
krh@248
   115
	p->flags = flags;
krh@248
   116
	p->version = hashtable_tokenize(&merger->table,
krh@248
   117
					&pool[package->version]);
krh@248
   118
	p->arch = hashtable_tokenize(&merger->table,
krh@248
   119
				     &pool[package->arch]);
ali@395
   120
	if (source->set->details_string_pool.size) {
ali@395
   121
		p->summary = hashtable_tokenize(&merger->details_table,
ali@395
   122
						&details_pool[package->summary]);
ali@395
   123
		p->description = hashtable_tokenize(&merger->details_table,
ali@395
   124
						    &details_pool[package->description]);
ali@395
   125
		p->url = hashtable_tokenize(&merger->details_table,
ali@395
   126
					    &details_pool[package->url]);
ali@395
   127
		p->license = hashtable_tokenize(&merger->details_table,
ali@395
   128
						&details_pool[package->license]);
ali@395
   129
	} else {
ali@395
   130
		p->summary = hashtable_tokenize(&merger->details_table, "");
ali@395
   131
		p->description = hashtable_tokenize(&merger->details_table, "");
ali@395
   132
		p->url = hashtable_tokenize(&merger->details_table, "");
ali@395
   133
		p->license = hashtable_tokenize(&merger->details_table, "");
ali@395
   134
	}
krh@248
   135
krh@248
   136
	p->properties = package->properties;
krh@248
   137
	r = list_first(&package->properties, &source->set->property_pool);
krh@248
   138
	while (r) {
krh@248
   139
		source->property_map[r->data] = 1;
krh@248
   140
		r = list_next(r);
krh@248
   141
	}
krh@248
   142
krh@248
   143
	p->files = package->files;
krh@248
   144
	r = list_first(&package->files, &source->set->file_pool);
krh@248
   145
	while (r) {
krh@248
   146
		source->file_map[r->data] = 1;
krh@248
   147
		r = list_next(r);
krh@248
   148
	}
ali@369
   149
ali@372
   150
	array_init(&install_prefixes);
ali@372
   151
	r = list_first(&package->install_prefixes, &source->set->prefix_pool);
ali@372
   152
	while (r) {
ali@372
   153
		s = (char *)source->set->string_pool.data + r->data;
ali@372
   154
		prefix = array_add(&install_prefixes, sizeof *prefix);
ali@372
   155
		*prefix = hashtable_tokenize(&merger->table, s);
ali@372
   156
		r = list_next(r);
ali@372
   157
	}
ali@372
   158
	list_set_array(&p->install_prefixes, &merger->set->prefix_pool,
ali@372
   159
                       &install_prefixes, 0);
ali@372
   160
	array_release(&install_prefixes);
ali@372
   161
ali@369
   162
	p->preun.program = hashtable_tokenize(&merger->table,
ali@369
   163
					      &pool[package->preun.program]);
ali@369
   164
	p->preun.body = hashtable_tokenize(&merger->table,
ali@369
   165
					   &pool[package->preun.body]);
ali@369
   166
	p->postun.program = hashtable_tokenize(&merger->table,
ali@369
   167
					       &pool[package->postun.program]);
ali@369
   168
	p->postun.body = hashtable_tokenize(&merger->table,
ali@369
   169
					    &pool[package->postun.body]);
krh@248
   170
}
krh@248
   171
krh@248
   172
static uint32_t
krh@248
   173
add_property(struct razor_merger *merger,
krh@248
   174
	     const char *name, uint32_t flags, const char *version)
krh@248
   175
{
krh@248
   176
	struct razor_property *p;
krh@248
   177
krh@248
   178
	p = array_add(&merger->set->properties, sizeof *p);
krh@248
   179
	p->name = hashtable_tokenize(&merger->table, name);
krh@248
   180
	p->flags = flags;
krh@248
   181
	p->version = hashtable_tokenize(&merger->table, version);
krh@248
   182
krh@248
   183
	return p - (struct razor_property *) merger->set->properties.data;
krh@248
   184
}
krh@248
   185
krh@248
   186
static void
krh@248
   187
merge_properties(struct razor_merger *merger)
krh@248
   188
{
krh@248
   189
	struct razor_property *p1, *p2;
krh@248
   190
	struct razor_set *set1, *set2;
krh@248
   191
	uint32_t *map1, *map2;
krh@248
   192
	int i, j, cmp, count1, count2;
krh@248
   193
	char *pool1, *pool2;
krh@248
   194
krh@248
   195
	set1 = merger->source1.set;
krh@248
   196
	set2 = merger->source2.set;
krh@248
   197
	map1 = merger->source1.property_map;
krh@248
   198
	map2 = merger->source2.property_map;
krh@248
   199
krh@248
   200
	i = 0;
krh@248
   201
	j = 0;
krh@248
   202
	pool1 = set1->string_pool.data;
krh@248
   203
	pool2 = set2->string_pool.data;
krh@248
   204
krh@248
   205
	count1 = set1->properties.size / sizeof *p1;
krh@248
   206
	count2 = set2->properties.size / sizeof *p2;
krh@248
   207
	while (i < count1 || j < count2) {
krh@248
   208
		if (i < count1 && map1[i] == 0) {
krh@248
   209
			i++;
krh@248
   210
			continue;
krh@248
   211
		}
krh@248
   212
		if (j < count2 && map2[j] == 0) {
krh@248
   213
			j++;
krh@248
   214
			continue;
krh@248
   215
		}
krh@248
   216
		p1 = (struct razor_property *) set1->properties.data + i;
krh@248
   217
		p2 = (struct razor_property *) set2->properties.data + j;
krh@248
   218
		if (i < count1 && j < count2)
krh@248
   219
			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
krh@248
   220
		else if (i < count1)
krh@248
   221
			cmp = -1;
krh@248
   222
		else
krh@248
   223
			cmp = 1;
krh@248
   224
		if (cmp == 0)
krh@248
   225
			cmp = p1->flags - p2->flags;
krh@248
   226
		if (cmp == 0)
krh@248
   227
			cmp = razor_versioncmp(&pool1[p1->version],
krh@248
   228
					       &pool2[p2->version]);
krh@248
   229
		if (cmp < 0) {
krh@248
   230
			map1[i++] = add_property(merger,
krh@248
   231
						 &pool1[p1->name],
krh@248
   232
						 p1->flags,
krh@248
   233
						 &pool1[p1->version]);
krh@248
   234
		} else if (cmp > 0) {
krh@248
   235
			map2[j++] = add_property(merger,
krh@248
   236
						 &pool2[p2->name],
krh@248
   237
						 p2->flags,
krh@248
   238
						 &pool2[p2->version]);
krh@248
   239
		} else  {
krh@248
   240
			map1[i++] = map2[j++] =
krh@248
   241
				add_property(merger,
krh@248
   242
					     &pool1[p1->name],
krh@248
   243
					     p1->flags,
krh@248
   244
					     &pool1[p1->version]);
krh@248
   245
		}
krh@248
   246
	}
krh@248
   247
}
krh@248
   248
krh@248
   249
static void
krh@248
   250
emit_properties(struct list_head *properties, struct array *source_pool,
krh@248
   251
		uint32_t *map, struct array *pool)
krh@248
   252
{
krh@248
   253
	uint32_t r;
krh@248
   254
	struct list *p, *q;
krh@248
   255
krh@248
   256
	r = pool->size / sizeof *q;
krh@248
   257
	p = list_first(properties, source_pool);
krh@248
   258
	while (p) {
krh@248
   259
		q = array_add(pool, sizeof *q);
krh@248
   260
		q->data = map[p->data];
krh@248
   261
		q->flags = p->flags;
krh@248
   262
		p = list_next(p);
krh@248
   263
	}
krh@248
   264
krh@248
   265
	list_set_ptr(properties, r);
krh@248
   266
}
krh@248
   267
krh@248
   268
static uint32_t
krh@248
   269
add_file(struct razor_merger *merger, const char *name)
krh@248
   270
{
krh@248
   271
	struct razor_entry *e;
krh@248
   272
krh@248
   273
	e = array_add(&merger->set->files, sizeof *e);
ali@348
   274
	e->name = hashtable_tokenize(&merger->file_table, name);
krh@248
   275
	e->flags = 0;
krh@248
   276
	e->start = 0;
krh@248
   277
krh@248
   278
	return e - (struct razor_entry *)merger->set->files.data;
krh@248
   279
}
krh@248
   280
krh@248
   281
/* FIXME. Blah */
krh@248
   282
static int
krh@248
   283
fix_file_map(uint32_t *map,
krh@248
   284
	     struct razor_entry *files,
krh@248
   285
	     struct razor_entry *top)
krh@248
   286
{
krh@248
   287
	uint32_t e;
krh@248
   288
	int found_file = 0;
krh@248
   289
ali@359
   290
	e = top - files;
krh@248
   291
	do {
ali@359
   292
		if (files[e].start &&
ali@359
   293
		    fix_file_map(map, files, &files[files[e].start]))
ali@359
   294
			map[e] = 1;
krh@248
   295
		if (map[e])
krh@248
   296
			found_file = 1;
krh@248
   297
	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
krh@248
   298
krh@248
   299
	return found_file;
krh@248
   300
}
krh@248
   301
krh@248
   302
struct merge_directory {
krh@248
   303
	uint32_t merged, dir1, dir2;
krh@248
   304
};
krh@248
   305
krh@248
   306
static void
krh@248
   307
merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
krh@248
   308
{
krh@248
   309
	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
krh@248
   310
	struct razor_set *set1, *set2;
krh@248
   311
	struct array merge_stack;
krh@248
   312
	struct merge_directory *child_md, *end_md;
krh@248
   313
	uint32_t *map1, *map2, start, last;
krh@248
   314
	int cmp;
krh@248
   315
	char *pool1, *pool2;
krh@248
   316
krh@248
   317
	set1 = merger->source1.set;
krh@248
   318
	set2 = merger->source2.set;
krh@248
   319
	map1 = merger->source1.file_map;
krh@248
   320
	map2 = merger->source2.file_map;
krh@313
   321
	pool1 = set1->file_string_pool.data;
krh@313
   322
	pool2 = set2->file_string_pool.data;
krh@248
   323
	root1 = (struct razor_entry *) set1->files.data;
krh@248
   324
	root2 = (struct razor_entry *) set2->files.data;
krh@248
   325
krh@248
   326
	array_init(&merge_stack);
krh@248
   327
krh@248
   328
	start = merger->set->files.size / sizeof (struct razor_entry);
ali@359
   329
	last = 0xFFFFFFFF;
ali@359
   330
	e1 = md->dir1 != 0xFFFFFFFF ? root1 + md->dir1 : NULL;
ali@359
   331
	e2 = md->dir2 != 0xFFFFFFFF ? root2 + md->dir2 : NULL;
krh@248
   332
	while (e1 || e2) {
krh@248
   333
		if (!e2 && !map1[e1 - root1]) {
krh@248
   334
			if ((e1++)->flags & RAZOR_ENTRY_LAST)
krh@248
   335
				e1 = NULL;
krh@248
   336
			continue;
krh@248
   337
		}
krh@248
   338
		if (!e1 && !map2[e2 - root2]) {
krh@248
   339
			if ((e2++)->flags & RAZOR_ENTRY_LAST)
krh@248
   340
				e2 = NULL;
krh@248
   341
			continue;
krh@248
   342
		}
krh@248
   343
		if (e1 && !map1[e1 - root1] &&
krh@314
   344
		    e2 && !map2[e2 - root2]) {
krh@248
   345
			if ((e1++)->flags & RAZOR_ENTRY_LAST)
krh@248
   346
				e1 = NULL;
krh@248
   347
			if ((e2++)->flags & RAZOR_ENTRY_LAST)
krh@248
   348
				e2 = NULL;
krh@248
   349
			continue;
krh@248
   350
		}
krh@248
   351
krh@248
   352
		if (!e1)
krh@248
   353
			cmp = 1;
krh@248
   354
		else if (!e2)
krh@248
   355
			cmp = -1;
krh@248
   356
		else {
krh@248
   357
			cmp = strcmp (&pool1[e1->name],
krh@248
   358
				      &pool2[e2->name]);
krh@248
   359
		}
krh@248
   360
krh@248
   361
		if (cmp < 0) {
krh@248
   362
			if (map1[e1 - root1]) {
krh@248
   363
				map1[e1 - root1] = last =
krh@248
   364
					add_file(merger, &pool1[e1->name]);
krh@248
   365
				if (e1->start) {
krh@248
   366
					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
krh@248
   367
					child_md->merged = last;
krh@248
   368
					child_md->dir1 = e1->start;
ali@359
   369
					child_md->dir2 = 0xFFFFFFFF;
krh@248
   370
				}
krh@248
   371
			}
krh@248
   372
			if ((e1++)->flags & RAZOR_ENTRY_LAST)
krh@248
   373
				e1 = NULL;
krh@248
   374
		} else if (cmp > 0) {
krh@248
   375
			if (map2[e2 - root2]) {
krh@248
   376
				map2[e2 - root2] = last =
krh@248
   377
					add_file(merger, &pool2[e2->name]);
krh@248
   378
				if (e2->start) {
krh@248
   379
					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
krh@248
   380
					child_md->merged = last;
ali@359
   381
					child_md->dir1 = 0xFFFFFFFF;
krh@248
   382
					child_md->dir2 = e2->start;
krh@248
   383
				}
krh@248
   384
			}
krh@248
   385
			if ((e2++)->flags & RAZOR_ENTRY_LAST)
krh@248
   386
				e2 = NULL;
krh@248
   387
		} else {
krh@248
   388
			map1[e1 - root1] = map2[e2- root2] = last =
krh@248
   389
				add_file(merger, &pool1[e1->name]);
krh@248
   390
			if (e1->start || e2->start) {
krh@248
   391
				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
krh@248
   392
				child_md->merged = last;
ali@359
   393
				child_md->dir1 = e1->start ? e1->start : 0xFFFFFFFF;
ali@359
   394
				child_md->dir2 = e2->start ? e2->start : 0xFFFFFFFF;
krh@248
   395
			}
krh@248
   396
			if ((e1++)->flags & RAZOR_ENTRY_LAST)
krh@248
   397
				e1 = NULL;
krh@248
   398
			if ((e2++)->flags & RAZOR_ENTRY_LAST)
krh@248
   399
				e2 = NULL;
krh@248
   400
		}
krh@248
   401
	}
krh@248
   402
krh@248
   403
	mroot = (struct razor_entry *)merger->set->files.data;
ali@359
   404
	if (last != 0xFFFFFFFF) {
krh@248
   405
		mroot[last].flags = RAZOR_ENTRY_LAST;
krh@248
   406
		mroot[md->merged].start = start;
ali@359
   407
	}
krh@248
   408
krh@248
   409
	end_md = merge_stack.data + merge_stack.size;
krh@248
   410
	for (child_md = merge_stack.data; child_md < end_md; child_md++)
krh@248
   411
		merge_one_directory(merger, child_md);
krh@248
   412
	array_release(&merge_stack);
krh@248
   413
}
krh@248
   414
krh@248
   415
static void
krh@248
   416
merge_files(struct razor_merger *merger)
krh@248
   417
{
krh@248
   418
	struct razor_entry *root;
krh@248
   419
	struct merge_directory md;
krh@248
   420
	uint32_t *map1, *map2;
krh@248
   421
krh@248
   422
	map1 = merger->source1.file_map;
krh@248
   423
	map2 = merger->source2.file_map;
krh@248
   424
krh@248
   425
	md.merged = 0;
krh@248
   426
krh@248
   427
	if (merger->source1.set->files.size) {
krh@248
   428
		root = (struct razor_entry *) merger->source1.set->files.data;
krh@248
   429
		if (root->start)
krh@248
   430
			fix_file_map(map1, root, root);
krh@248
   431
		md.dir1 = 0;
ali@359
   432
	} else {
ali@359
   433
		md.dir1 = 0xFFFFFFFF;
ali@359
   434
	}
krh@248
   435
krh@248
   436
	if (merger->source2.set->files.size) {
krh@248
   437
		root = (struct razor_entry *) merger->source2.set->files.data;
krh@248
   438
		if (root->start)
krh@248
   439
			fix_file_map(map2, root, root);
krh@248
   440
		md.dir2 = 0;
ali@359
   441
	} else {
ali@359
   442
		md.dir2 = 0xFFFFFFFF;
ali@359
   443
	}
ali@359
   444
ali@359
   445
	/* Remove the unnamed root which razor_set_create() added */
ali@359
   446
	array_release(&merger->set->files);
ali@359
   447
	array_init(&merger->set->files);
krh@248
   448
krh@248
   449
	merge_one_directory(merger, &md);
krh@248
   450
}
krh@248
   451
krh@248
   452
static void
krh@248
   453
emit_files(struct list_head *files, struct array *source_pool,
krh@248
   454
	   uint32_t *map, struct array *pool)
krh@248
   455
{
krh@248
   456
	uint32_t r;
krh@248
   457
	struct list *p, *q;
krh@248
   458
krh@248
   459
	r = pool->size / sizeof *q;
krh@248
   460
	p = list_first(files, source_pool);
krh@248
   461
	while (p) {
krh@248
   462
		q = array_add(pool, sizeof *q);
krh@248
   463
		q->data = map[p->data];
krh@248
   464
		q->flags = p->flags;
krh@248
   465
		p = list_next(p);
krh@248
   466
	}
krh@248
   467
krh@248
   468
	list_set_ptr(files, r);
krh@248
   469
}
krh@248
   470
krh@248
   471
/* Rebuild property->packages maps.  We can't just remap these, as a
krh@248
   472
 * property may have lost or gained a number of packages.  Allocate an
krh@248
   473
 * array per property and loop through the packages and add them to
krh@248
   474
 * the arrays for their properties. */
krh@248
   475
static void
krh@248
   476
rebuild_property_package_lists(struct razor_set *set)
krh@248
   477
{
krh@248
   478
	struct array *pkgs, *a;
krh@248
   479
	struct razor_package *pkg, *pkg_end;
krh@248
   480
	struct razor_property *prop, *prop_end;
krh@248
   481
	struct list *r;
krh@248
   482
	uint32_t *q;
krh@248
   483
	int count;
krh@248
   484
krh@248
   485
	count = set->properties.size / sizeof (struct razor_property);
krh@248
   486
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   487
	pkg_end = set->packages.data + set->packages.size;
krh@248
   488
krh@248
   489
	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
krh@248
   490
		r = list_first(&pkg->properties, &set->property_pool);
krh@248
   491
		while (r) {
krh@248
   492
			q = array_add(&pkgs[r->data], sizeof *q);
krh@248
   493
			*q = pkg - (struct razor_package *) set->packages.data;
krh@248
   494
			r = list_next(r);
krh@248
   495
		}
krh@248
   496
	}
krh@248
   497
krh@248
   498
	prop_end = set->properties.data + set->properties.size;
krh@248
   499
	a = pkgs;
krh@248
   500
	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
krh@248
   501
		list_set_array(&prop->packages, &set->package_pool, a, 0);
krh@248
   502
		array_release(a);
krh@248
   503
	}
krh@248
   504
	free(pkgs);
krh@248
   505
}
krh@248
   506
krh@248
   507
static void
krh@248
   508
rebuild_file_package_lists(struct razor_set *set)
krh@248
   509
{
krh@248
   510
	struct array *pkgs, *a;
krh@248
   511
	struct razor_package *pkg, *pkg_end;
krh@248
   512
	struct razor_entry *entry, *entry_end;
krh@248
   513
	struct list *r;
krh@248
   514
	uint32_t *q;
krh@248
   515
	int count;
krh@248
   516
krh@248
   517
	count = set->files.size / sizeof (struct razor_entry);
krh@248
   518
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   519
	pkg_end = set->packages.data + set->packages.size;
krh@248
   520
krh@248
   521
	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
krh@248
   522
		r = list_first(&pkg->files, &set->file_pool);
krh@248
   523
		while (r) {
krh@248
   524
			q = array_add(&pkgs[r->data], sizeof *q);
krh@248
   525
			*q = pkg - (struct razor_package *) set->packages.data;
krh@248
   526
			r = list_next(r);
krh@248
   527
		}
krh@248
   528
	}
krh@248
   529
krh@248
   530
	entry_end = set->files.data + set->files.size;
krh@248
   531
	a = pkgs;
krh@248
   532
	for (entry = set->files.data; entry < entry_end; entry++, a++) {
krh@248
   533
		list_set_array(&entry->packages, &set->package_pool, a, 0);
krh@248
   534
		array_release(a);
krh@248
   535
	}
krh@248
   536
	free(pkgs);
krh@248
   537
}
krh@248
   538
krh@248
   539
struct razor_set *
ali@369
   540
razor_merger_commit(struct razor_merger *merger)
krh@248
   541
{
krh@248
   542
	struct razor_package *p, *pend;
krh@248
   543
krh@248
   544
	/* As we built the package list, we filled out a bitvector of
krh@248
   545
	 * the properties that are referenced by the packages in the
krh@248
   546
	 * new set.  Now we do a parallel loop through the properties
krh@248
   547
	 * and emit those marked in the bit vector to the new set.  In
krh@248
   548
	 * the process, we update the bit vector to actually map from
krh@248
   549
	 * indices in the old property list to indices in the new
krh@248
   550
	 * property list for both sets. */
krh@248
   551
krh@248
   552
	merge_properties(merger);
krh@248
   553
	merge_files(merger);
krh@248
   554
krh@248
   555
	/* Now we loop through the packages again and emit the
krh@248
   556
	 * property lists, remapped to point to the new properties. */
krh@248
   557
krh@248
   558
	pend = merger->set->packages.data + merger->set->packages.size;
krh@248
   559
	for (p = merger->set->packages.data; p < pend; p++) {
krh@248
   560
		struct source *src;
krh@248
   561
krh@248
   562
		if (p->flags & UPSTREAM_SOURCE)
krh@248
   563
			src = &merger->source2;
krh@248
   564
		else
krh@248
   565
			src = &merger->source1;
krh@248
   566
krh@248
   567
		emit_properties(&p->properties,
krh@248
   568
				&src->set->property_pool,
krh@248
   569
				src->property_map,
krh@248
   570
				&merger->set->property_pool);
krh@248
   571
		emit_files(&p->files,
krh@248
   572
			   &src->set->file_pool,
krh@248
   573
			   src->file_map,
krh@248
   574
			   &merger->set->file_pool);
krh@248
   575
		p->flags &= ~UPSTREAM_SOURCE;
krh@248
   576
	}
krh@248
   577
krh@248
   578
	rebuild_property_package_lists(merger->set);
krh@248
   579
	rebuild_file_package_lists(merger->set);
krh@248
   580
ali@369
   581
	merger->committed = 1;
ali@369
   582
ali@369
   583
	return merger->set;
ali@369
   584
}
ali@369
   585
ali@369
   586
void
ali@369
   587
razor_merger_package_add_script(struct razor_merger *merger,
ali@369
   588
				struct razor_package *package,
ali@369
   589
				enum razor_property_flags script,
ali@369
   590
				const char *program, const char *body)
ali@369
   591
{
ali@369
   592
	uint32_t p, b;
ali@369
   593
	char *pool;
ali@369
   594
	struct razor_set *set = merger->set;
ali@369
   595
	assert ((void *)package >= set->packages.data && \
ali@369
   596
	    (void *)package < set->packages.data + set->packages.size);
ali@369
   597
ali@369
   598
	p = hashtable_tokenize(&merger->table, program);
ali@369
   599
	b = hashtable_tokenize(&merger->table, body);
ali@369
   600
ali@369
   601
	pool = merger->set->string_pool.data;
ali@369
   602
ali@369
   603
	switch (script) {
ali@369
   604
	case RAZOR_PROPERTY_PREUN:
ali@403
   605
		if (package->preun.program != p) {
ali@403
   606
			assert(pool[package->preun.program] == '\0');
ali@403
   607
			package->preun.program = p;
ali@403
   608
		}
ali@403
   609
		if (package->preun.body != b) {
ali@403
   610
			assert(pool[package->preun.body] == '\0');
ali@403
   611
			package->preun.body = b;
ali@403
   612
		}
ali@369
   613
		break;
ali@369
   614
	case RAZOR_PROPERTY_POSTUN:
ali@403
   615
		if (package->postun.program != p) {
ali@403
   616
			assert(pool[package->postun.program] == '\0');
ali@403
   617
			package->postun.program = p;
ali@403
   618
		}
ali@403
   619
		if (package->postun.body != b) {
ali@403
   620
			assert(pool[package->postun.body] == '\0');
ali@403
   621
			package->postun.body = b;
ali@403
   622
		}
ali@369
   623
		break;
ali@369
   624
	default:
ali@369
   625
		break;
ali@369
   626
	}
ali@369
   627
}
ali@369
   628
ali@369
   629
void razor_merger_destroy(struct razor_merger *merger)
ali@369
   630
{
krh@248
   631
	hashtable_release(&merger->table);
ali@348
   632
	hashtable_release(&merger->file_table);
ali@394
   633
	hashtable_release(&merger->details_table);
krh@248
   634
	free(merger);
krh@248
   635
}