librazor/transaction.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jun 11 17:56:45 2016 +0100 (2016-06-11)
changeset 473 2e8a0b26d579
parent 446 4277359896dc
child 475 008c75a5e08d
permissions -rw-r--r--
Release 0.6.3
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@446
     4
 * Copyright (C) 2009, 2011, 2012, 2014  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
krh@248
    21
#define _GNU_SOURCE
krh@248
    22
ali@438
    23
#include "config.h"
krh@248
    24
#include <stdlib.h>
krh@248
    25
#include <stddef.h>
krh@248
    26
#include <stdint.h>
krh@248
    27
#include <stdio.h>
krh@248
    28
#include <string.h>
krh@248
    29
#include <sys/types.h>
krh@248
    30
#include <sys/stat.h>
krh@248
    31
#include <unistd.h>
krh@248
    32
#include <fcntl.h>
krh@248
    33
#include <errno.h>
krh@248
    34
#include <ctype.h>
richard@301
    35
#include <assert.h>
krh@248
    36
krh@248
    37
#include "razor-internal.h"
krh@248
    38
#include "razor.h"
krh@248
    39
krh@248
    40
static int
krh@248
    41
provider_satisfies_requirement(struct razor_property *provider,
krh@248
    42
			       const char *provider_strings,
krh@248
    43
			       uint32_t flags,
krh@248
    44
			       const char *required)
krh@248
    45
{
krh@248
    46
	int cmp, len;
krh@248
    47
	const char *provided = &provider_strings[provider->version];
krh@248
    48
krh@248
    49
	if (!*required)
krh@248
    50
		return 1;
krh@248
    51
	if (!*provided) {
krh@248
    52
		if (flags & RAZOR_PROPERTY_LESS)
krh@248
    53
			return 0;
krh@248
    54
		else
krh@248
    55
			return 1;
krh@248
    56
	}
krh@248
    57
krh@248
    58
	cmp = razor_versioncmp(provided, required);
krh@248
    59
krh@248
    60
	switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
krh@248
    61
	case RAZOR_PROPERTY_LESS:
krh@248
    62
		return cmp < 0;
krh@248
    63
krh@248
    64
	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
krh@248
    65
		if (cmp <= 0)
krh@248
    66
			return 1;
krh@248
    67
		/* fall through: FIXME, make sure this is correct */
krh@248
    68
krh@248
    69
	case RAZOR_PROPERTY_EQUAL:
krh@248
    70
		if (cmp == 0)
krh@248
    71
			return 1;
krh@248
    72
krh@248
    73
		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
krh@248
    74
		len = strlen(required);
krh@248
    75
		if (!strncmp(required, provided, len) && provided[len] == '-')
krh@248
    76
			return 1;
krh@248
    77
		return 0;
krh@248
    78
krh@248
    79
	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
krh@248
    80
		return cmp >= 0;
krh@248
    81
krh@248
    82
	case RAZOR_PROPERTY_GREATER:
krh@248
    83
		return cmp > 0;
krh@248
    84
	}
krh@248
    85
krh@248
    86
	/* shouldn't happen */
krh@248
    87
	return 0;
krh@248
    88
}
krh@248
    89
krh@248
    90
#define TRANS_PACKAGE_PRESENT		1
krh@248
    91
#define TRANS_PACKAGE_UPDATE		2
krh@248
    92
#define TRANS_PROPERTY_SATISFIED	0x80000000
krh@248
    93
krh@248
    94
struct transaction_set {
krh@248
    95
	struct razor_set *set;
krh@248
    96
	uint32_t *packages;
krh@248
    97
	uint32_t *properties;
krh@248
    98
};
krh@248
    99
krh@248
   100
struct razor_transaction {
krh@248
   101
	int package_count, errors;
krh@248
   102
	struct transaction_set system, upstream;
krh@248
   103
	int changes;
ali@369
   104
	struct razor_merger *merger;
krh@248
   105
};
krh@248
   106
krh@248
   107
static void
krh@248
   108
transaction_set_init(struct transaction_set *ts, struct razor_set *set)
krh@248
   109
{
krh@248
   110
	int count;
krh@248
   111
ali@403
   112
	ts->set = razor_set_ref(set);
krh@248
   113
	count = set->packages.size / sizeof (struct razor_package);
krh@248
   114
	ts->packages = zalloc(count * sizeof *ts->packages);
krh@248
   115
	count = set->properties.size / sizeof (struct razor_property);
krh@248
   116
	ts->properties = zalloc(count * sizeof *ts->properties);
krh@248
   117
}
krh@248
   118
krh@248
   119
static void
krh@248
   120
transaction_set_release(struct transaction_set *ts)
krh@248
   121
{
ali@403
   122
	razor_set_unref(ts->set);
krh@248
   123
	free(ts->packages);
krh@248
   124
	free(ts->properties);
krh@248
   125
}
krh@248
   126
krh@248
   127
static void
krh@248
   128
transaction_set_install_package(struct transaction_set *ts,
krh@248
   129
				struct razor_package *package)
krh@248
   130
{
krh@248
   131
	struct razor_package *pkgs;
krh@248
   132
	struct list *prop;
krh@248
   133
	int i;
krh@248
   134
krh@248
   135
	pkgs = ts->set->packages.data;
krh@248
   136
	i = package - pkgs;
ali@432
   137
	if (ts->packages[i] & TRANS_PACKAGE_PRESENT)
krh@248
   138
		return;
krh@248
   139
ali@432
   140
	ts->packages[i] |= TRANS_PACKAGE_PRESENT;
krh@248
   141
krh@248
   142
	prop = list_first(&package->properties, &ts->set->property_pool);
krh@248
   143
	while (prop) {
krh@248
   144
		ts->properties[prop->data]++;
krh@248
   145
		prop = list_next(prop);
krh@248
   146
	}
krh@248
   147
}
krh@248
   148
krh@248
   149
static void
krh@248
   150
transaction_set_remove_package(struct transaction_set *ts,
krh@248
   151
			       struct razor_package *package)
krh@248
   152
{
krh@248
   153
	struct razor_package *pkgs;
krh@248
   154
	struct list *prop;
krh@248
   155
	int i;
krh@248
   156
krh@248
   157
	pkgs = ts->set->packages.data;
krh@248
   158
	i = package - pkgs;
ali@432
   159
	if (!(ts->packages[i] & TRANS_PACKAGE_PRESENT))
krh@248
   160
		return;
krh@248
   161
ali@432
   162
	ts->packages[i] &= ~TRANS_PACKAGE_PRESENT;
krh@248
   163
krh@248
   164
	prop = list_first(&package->properties, &ts->set->property_pool);
krh@248
   165
	while (prop) {
krh@248
   166
		ts->properties[prop->data]--;
krh@248
   167
		prop = list_next(prop);
krh@248
   168
	}
krh@248
   169
}
krh@248
   170
krh@269
   171
RAZOR_EXPORT struct razor_transaction *
krh@248
   172
razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
krh@248
   173
{
krh@248
   174
	struct razor_transaction *trans;
krh@248
   175
	struct razor_package *p, *spkgs, *pend;
krh@248
   176
krh@248
   177
	trans = zalloc(sizeof *trans);
krh@248
   178
	transaction_set_init(&trans->system, system);
krh@248
   179
	transaction_set_init(&trans->upstream, upstream);
krh@248
   180
krh@248
   181
	spkgs = trans->system.set->packages.data;
krh@248
   182
	pend = trans->system.set->packages.data +
krh@248
   183
		trans->system.set->packages.size;
krh@248
   184
	for (p = spkgs; p < pend; p++)
krh@248
   185
		transaction_set_install_package(&trans->system, p);
krh@248
   186
krh@248
   187
	return trans;
krh@248
   188
}
krh@248
   189
krh@269
   190
RAZOR_EXPORT void
krh@248
   191
razor_transaction_install_package(struct razor_transaction *trans,
krh@248
   192
				  struct razor_package *package)
krh@248
   193
{
richard@301
   194
	assert (trans != NULL);
richard@301
   195
	assert (package != NULL);
richard@301
   196
krh@248
   197
	transaction_set_install_package(&trans->upstream, package);
krh@248
   198
	trans->changes++;
krh@248
   199
}
krh@248
   200
krh@269
   201
RAZOR_EXPORT void
krh@248
   202
razor_transaction_remove_package(struct razor_transaction *trans,
krh@248
   203
				 struct razor_package *package)
krh@248
   204
{
richard@301
   205
	assert (trans != NULL);
richard@301
   206
	assert (package != NULL);
richard@301
   207
krh@248
   208
	transaction_set_remove_package(&trans->system, package);
krh@248
   209
	trans->changes++;
krh@248
   210
}
krh@248
   211
krh@269
   212
RAZOR_EXPORT void
krh@248
   213
razor_transaction_update_package(struct razor_transaction *trans,
krh@248
   214
				  struct razor_package *package)
krh@248
   215
{
krh@248
   216
	struct razor_package *spkgs, *upkgs, *end;
krh@248
   217
richard@301
   218
	assert (trans != NULL);
richard@301
   219
	assert (package != NULL);
richard@301
   220
krh@248
   221
	spkgs = trans->system.set->packages.data;
krh@248
   222
	upkgs = trans->upstream.set->packages.data;
krh@248
   223
	end = trans->system.set->packages.data +
krh@248
   224
		trans->system.set->packages.size;
krh@248
   225
	if (spkgs <= package && package < end)
krh@248
   226
		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
krh@248
   227
	else
krh@248
   228
		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
krh@248
   229
}
krh@248
   230
krh@248
   231
struct prop_iter {
krh@248
   232
	struct razor_property *p, *start, *end;
krh@248
   233
	const char *pool;
krh@248
   234
	uint32_t *present;
krh@248
   235
};
krh@248
   236
krh@248
   237
static void
krh@248
   238
prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
krh@248
   239
{
krh@248
   240
	pi->p = ts->set->properties.data;
krh@248
   241
	pi->start = ts->set->properties.data;
krh@248
   242
	pi->end = ts->set->properties.data + ts->set->properties.size;
krh@248
   243
	pi->pool = ts->set->string_pool.data;
krh@248
   244
	pi->present = ts->properties;
krh@248
   245
}
krh@248
   246
krh@248
   247
static int
krh@248
   248
prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
krh@248
   249
{
krh@248
   250
	while (pi->p < pi->end) {
krh@248
   251
		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
krh@248
   252
		    (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
krh@248
   253
			*p = pi->p++;
krh@248
   254
			return 1;
krh@248
   255
		}
krh@248
   256
		pi->p++;
krh@248
   257
	}
krh@248
   258
krh@248
   259
	return 0;
krh@248
   260
}
krh@248
   261
krh@248
   262
static struct razor_property *
krh@248
   263
prop_iter_seek_to(struct prop_iter *pi,
krh@248
   264
		  uint32_t flags, const char *match)
krh@248
   265
{
krh@248
   266
	uint32_t name;
krh@248
   267
krh@248
   268
	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
krh@248
   269
		pi->p++;
krh@248
   270
krh@248
   271
	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
krh@248
   272
		return NULL;
krh@248
   273
krh@248
   274
	name = pi->p->name;
krh@248
   275
	while (pi->p < pi->end &&
krh@248
   276
	       pi->p->name == name &&
krh@248
   277
	       (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
krh@248
   278
		pi->p++;
krh@248
   279
krh@248
   280
	if (pi->p == pi->end || pi->p->name != name)
krh@248
   281
		return NULL;
krh@248
   282
krh@248
   283
	return pi->p;
krh@248
   284
}
krh@248
   285
krh@248
   286
/* Remove packages from set that provide any of the matching (same
krh@248
   287
 * name and type) providers from ppi onwards that match the
krh@248
   288
 * requirement that rpi points to. */
krh@248
   289
static void
krh@248
   290
remove_matching_providers(struct razor_transaction *trans,
krh@248
   291
			  struct prop_iter *ppi,
krh@248
   292
			  uint32_t flags,
krh@248
   293
			  const char *version)
krh@248
   294
{
krh@248
   295
	struct razor_property *p;
ali@442
   296
	struct razor_package *pkg;
krh@248
   297
	struct razor_package_iterator pkg_iter;
krh@248
   298
	struct razor_set *set;
richard@302
   299
	const char *n, *v;
krh@248
   300
	uint32_t type;
krh@248
   301
krh@248
   302
	if (ppi->present == trans->system.properties)
krh@248
   303
		set = trans->system.set;
krh@248
   304
	else
krh@248
   305
		set = trans->upstream.set;
krh@248
   306
krh@248
   307
	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
krh@248
   308
	for (p = ppi->p;
krh@248
   309
	     p < ppi->end &&
krh@248
   310
	     p->name == ppi->p->name &&
krh@248
   311
	     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
krh@248
   312
	     p++) {
krh@248
   313
		if (!ppi->present[p - ppi->start])
krh@248
   314
			continue;
krh@248
   315
		if (!provider_satisfies_requirement(p, ppi->pool,
krh@248
   316
						    flags, version))
krh@248
   317
			continue;
krh@248
   318
krh@248
   319
		razor_package_iterator_init_for_property(&pkg_iter, set, p);
richard@302
   320
		while (razor_package_iterator_next(&pkg_iter, &pkg,
richard@302
   321
						   RAZOR_DETAIL_NAME, &n,
richard@307
   322
						   RAZOR_DETAIL_VERSION, &v,
richard@307
   323
						   RAZOR_DETAIL_LAST)) {
ali@403
   324
#if 0
krh@248
   325
			fprintf(stderr, "removing %s-%s\n", n, v);
ali@403
   326
#endif
krh@248
   327
			razor_transaction_remove_package(trans, pkg);
krh@248
   328
		}
krh@248
   329
	}
krh@248
   330
}
krh@248
   331
krh@248
   332
static void
krh@248
   333
flag_matching_providers(struct razor_transaction *trans,
krh@248
   334
			struct prop_iter *ppi,
krh@248
   335
			struct razor_property *r,
krh@248
   336
			struct prop_iter *rpi,
krh@248
   337
			unsigned int flag)
krh@248
   338
{
krh@248
   339
	struct razor_property *p;
krh@248
   340
	struct razor_package *pkg, *pkgs;
krh@248
   341
	struct razor_package_iterator pkg_iter;
krh@248
   342
	struct razor_set *set;
richard@302
   343
	const char *name, *version;
krh@248
   344
	uint32_t *flags, type;
krh@248
   345
krh@248
   346
	if (ppi->present == trans->system.properties) {
krh@248
   347
		set = trans->system.set;
krh@248
   348
		flags = trans->system.packages;
krh@248
   349
	} else {
krh@248
   350
		set = trans->upstream.set;
krh@248
   351
		flags = trans->upstream.packages;
krh@248
   352
	}
krh@248
   353
krh@248
   354
	pkgs = (struct razor_package *) set->packages.data;
krh@248
   355
	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
krh@248
   356
	for (p = ppi->p;
krh@248
   357
	     p < ppi->end &&
krh@248
   358
		     p->name == ppi->p->name &&
krh@248
   359
		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
krh@248
   360
	     p++) {
krh@248
   361
		if (!ppi->present[p - ppi->start])
krh@248
   362
			continue;
krh@248
   363
		if (!provider_satisfies_requirement(p, ppi->pool,
krh@248
   364
						    r->flags,
krh@248
   365
						    &rpi->pool[r->version]))
krh@248
   366
			continue;
krh@248
   367
krh@248
   368
		razor_package_iterator_init_for_property(&pkg_iter, set, p);
krh@248
   369
		while (razor_package_iterator_next(&pkg_iter, &pkg,
richard@302
   370
						   RAZOR_DETAIL_NAME, &name,
richard@307
   371
						   RAZOR_DETAIL_VERSION, &version,
richard@307
   372
						   RAZOR_DETAIL_LAST)) {
krh@248
   373
ali@403
   374
#if 0
krh@248
   375
			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
krh@248
   376
				name, version,
krh@248
   377
				ppi->pool + p->name,
krh@248
   378
				rpi->pool + r->name,
krh@248
   379
				rpi->pool + r->version);
ali@403
   380
#endif
krh@248
   381
			flags[pkg - pkgs] |= flag;
krh@248
   382
		}
krh@248
   383
	}
krh@248
   384
}
krh@248
   385
krh@248
   386
static struct razor_package *
krh@248
   387
pick_matching_provider(struct razor_set *set,
krh@248
   388
		       struct prop_iter *ppi,
krh@248
   389
		       uint32_t flags,
krh@248
   390
		       const char *version)
krh@248
   391
{
krh@248
   392
	struct razor_property *p;
krh@248
   393
	struct razor_package *pkgs;
krh@248
   394
	struct list *i;
krh@248
   395
	uint32_t type;
krh@248
   396
krh@248
   397
	/* This is where we decide which pkgs to pull in to satisfy a
krh@248
   398
	 * requirement.  There may be several different providers
krh@248
   399
	 * (different versions) and each version of a provider may
krh@248
   400
	 * come from a number of packages.  We pick the first package
krh@248
   401
	 * from the first provider that matches. */
krh@248
   402
krh@248
   403
	pkgs = set->packages.data;
krh@248
   404
	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
krh@248
   405
	for (p = ppi->p;
krh@248
   406
	     p < ppi->end &&
krh@248
   407
		     p->name == ppi->p->name &&
krh@248
   408
		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
krh@248
   409
		     ppi->present[p - ppi->start] == 0;
krh@248
   410
	     p++) {
krh@248
   411
		if (!provider_satisfies_requirement(p, ppi->pool,
krh@248
   412
						    flags, version))
krh@248
   413
			continue;
krh@248
   414
krh@248
   415
		i = list_first(&p->packages, &set->package_pool);
krh@248
   416
krh@248
   417
		return &pkgs[i->data];
krh@248
   418
	}
krh@248
   419
krh@248
   420
	return NULL;
krh@248
   421
}
krh@248
   422
krh@248
   423
static void
krh@248
   424
remove_obsoleted_packages(struct razor_transaction *trans)
krh@248
   425
{
krh@248
   426
	struct razor_property *up;
krh@248
   427
	struct prop_iter spi, upi;
krh@248
   428
krh@248
   429
	prop_iter_init(&spi, &trans->system);
krh@248
   430
	prop_iter_init(&upi, &trans->upstream);
krh@248
   431
krh@248
   432
	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
krh@248
   433
		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
krh@248
   434
				       &upi.pool[up->name]))
krh@248
   435
			continue;
krh@248
   436
		remove_matching_providers(trans, &spi, up->flags,
krh@248
   437
					  &upi.pool[up->version]);
krh@248
   438
	}
krh@248
   439
}
krh@248
   440
krh@248
   441
static int
krh@248
   442
any_provider_satisfies_requirement(struct prop_iter *ppi,
krh@248
   443
				   uint32_t flags,
krh@248
   444
				   const char *version)
krh@248
   445
{
krh@248
   446
	struct razor_property *p;
krh@248
   447
	uint32_t type;
krh@248
   448
krh@248
   449
	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
krh@248
   450
	for (p = ppi->p;
krh@248
   451
	     p < ppi->end &&
krh@248
   452
		     p->name == ppi->p->name &&
krh@248
   453
		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
krh@248
   454
	     p++) {
krh@248
   455
		if (ppi->present[p - ppi->start] > 0 &&
krh@248
   456
		    provider_satisfies_requirement(p, ppi->pool,
krh@248
   457
						   flags, version))
krh@248
   458
			return 1;
krh@248
   459
	}
krh@248
   460
krh@248
   461
	return 0;
krh@248
   462
}
krh@248
   463
krh@248
   464
static void
krh@248
   465
clear_requires_flags(struct transaction_set *ts)
krh@248
   466
{
krh@248
   467
	struct razor_property *p;
krh@248
   468
	const char *pool;
krh@248
   469
	int i, count;
ali@368
   470
	char *sub;
krh@248
   471
krh@248
   472
	count = ts->set->properties.size / sizeof *p;
krh@248
   473
	p = ts->set->properties.data;
krh@248
   474
	pool = ts->set->string_pool.data;
krh@248
   475
	for (i = 0; i < count; i++) {
krh@248
   476
		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
ali@368
   477
		sub = strchr(&pool[p[i].name], '(');
ali@368
   478
		if (sub && sub[strlen(sub) - 1] == ')') {
ali@368
   479
			sub = strdup(sub + 1);
ali@368
   480
			sub[strlen(sub) - 1] = '\0';
ali@368
   481
			if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
ali@368
   482
				ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
ali@368
   483
			if (strncmp(&pool[p[i].name], "lua(", 4) == 0 &&
ali@368
   484
			    razor_get_lua_loader(sub) &&
ali@368
   485
			    p[i].flags & RAZOR_PROPERTY_SCRIPT_MASK)
ali@368
   486
				ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
ali@368
   487
			free(sub);
ali@368
   488
		}
krh@248
   489
	}
krh@248
   490
}
krh@248
   491
krh@248
   492
static void
krh@248
   493
mark_satisfied_requires(struct razor_transaction *trans,
krh@248
   494
			struct transaction_set *rts,
krh@248
   495
			struct transaction_set *pts)
krh@248
   496
{
krh@248
   497
	struct prop_iter rpi, ppi;
krh@248
   498
	struct razor_property *rp;
krh@248
   499
krh@248
   500
	prop_iter_init(&rpi, rts);
krh@248
   501
	prop_iter_init(&ppi, pts);
krh@248
   502
krh@248
   503
	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   504
		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
krh@248
   505
				       &rpi.pool[rp->name]))
krh@248
   506
			continue;
krh@248
   507
krh@248
   508
		if (any_provider_satisfies_requirement(&ppi, rp->flags,
krh@248
   509
						       &rpi.pool[rp->version]))
krh@248
   510
			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
krh@248
   511
	}
krh@248
   512
}
krh@248
   513
krh@248
   514
static void
krh@248
   515
mark_all_satisfied_requires(struct razor_transaction *trans)
krh@248
   516
{
krh@248
   517
	clear_requires_flags(&trans->system);
krh@248
   518
	clear_requires_flags(&trans->upstream);
krh@248
   519
	mark_satisfied_requires(trans, &trans->system, &trans->system);
krh@248
   520
	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
krh@248
   521
	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
krh@248
   522
	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
krh@248
   523
}
krh@248
   524
krh@248
   525
static void
krh@248
   526
update_unsatisfied_packages(struct razor_transaction *trans)
krh@248
   527
{
krh@248
   528
	struct razor_package *spkgs, *pkg;
krh@248
   529
	struct razor_property *sp;
krh@248
   530
	struct prop_iter spi;
krh@248
   531
	struct razor_package_iterator pkg_iter;
richard@302
   532
	const char *name;
krh@248
   533
krh@248
   534
	spkgs = trans->system.set->packages.data;
krh@248
   535
	prop_iter_init(&spi, &trans->system);
krh@248
   536
krh@248
   537
	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
krh@248
   538
		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
krh@248
   539
			continue;
krh@248
   540
krh@248
   541
		razor_package_iterator_init_for_property(&pkg_iter,
krh@248
   542
							 trans->system.set,
krh@248
   543
							 sp);
krh@248
   544
		while (razor_package_iterator_next(&pkg_iter, &pkg,
richard@307
   545
						   RAZOR_DETAIL_NAME, &name,
richard@307
   546
						   RAZOR_DETAIL_LAST)) {
ali@432
   547
			if (!(trans->system.packages[pkg - spkgs] & TRANS_PACKAGE_PRESENT))
ali@432
   548
				continue;
ali@432
   549
ali@403
   550
#if 0
krh@248
   551
			fprintf(stderr, "updating %s because %s %s %s "
krh@248
   552
				"isn't satisfied\n",
krh@248
   553
				name, spi.pool + sp->name,
krh@248
   554
				razor_property_relation_to_string(sp),
krh@248
   555
				spi.pool + sp->version);
ali@403
   556
#endif
krh@248
   557
			trans->system.packages[pkg - spkgs] |=
krh@248
   558
				TRANS_PACKAGE_UPDATE;
krh@248
   559
		}
krh@248
   560
	}
krh@248
   561
}
krh@248
   562
krh@269
   563
RAZOR_EXPORT void
krh@248
   564
razor_transaction_update_all(struct razor_transaction *trans)
krh@248
   565
{
krh@248
   566
	struct razor_package *p;
krh@248
   567
	int i, count;
krh@248
   568
richard@301
   569
	assert (trans != NULL);
richard@301
   570
krh@248
   571
	count = trans->system.set->packages.size / sizeof *p;
krh@248
   572
	for (i = 0; i < count; i++)
krh@248
   573
		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
krh@248
   574
}
krh@248
   575
krh@248
   576
static void
krh@248
   577
update_conflicted_packages(struct razor_transaction *trans)
krh@248
   578
{
krh@248
   579
	struct razor_package *pkg, *spkgs;
krh@248
   580
	struct razor_property *up, *sp;
krh@248
   581
	struct prop_iter spi, upi;
krh@248
   582
	struct razor_package_iterator pkg_iter;
richard@302
   583
	const char *name, *version;
krh@248
   584
krh@248
   585
	spkgs = trans->system.set->packages.data;
krh@248
   586
	prop_iter_init(&spi, &trans->system);
krh@248
   587
	prop_iter_init(&upi, &trans->upstream);
krh@248
   588
krh@248
   589
	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
krh@248
   590
		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
krh@248
   591
				       &spi.pool[sp->name]))
krh@248
   592
			continue;
krh@248
   593
krh@248
   594
		if (!any_provider_satisfies_requirement(&upi, sp->flags,
krh@248
   595
							&spi.pool[sp->version]))
krh@248
   596
			continue;
krh@248
   597
krh@248
   598
		razor_package_iterator_init_for_property(&pkg_iter,
krh@248
   599
							 trans->system.set,
krh@248
   600
							 sp);
krh@248
   601
		while (razor_package_iterator_next(&pkg_iter, &pkg,
richard@302
   602
						   RAZOR_DETAIL_NAME, &name,
richard@307
   603
						   RAZOR_DETAIL_VERSION, &version,
richard@307
   604
						   RAZOR_DETAIL_LAST)) {
ali@403
   605
#if 0
jbowes@286
   606
			fprintf(stderr, "updating %s %s because it "
jbowes@286
   607
				"conflicts with %s\n",
krh@248
   608
				name, version, spi.pool + sp->name);
ali@403
   609
#endif
krh@248
   610
			trans->system.packages[pkg - spkgs] |=
krh@248
   611
				TRANS_PACKAGE_UPDATE;
krh@248
   612
		}
krh@248
   613
	}
krh@248
   614
krh@248
   615
	prop_iter_init(&spi, &trans->system);
krh@248
   616
	prop_iter_init(&upi, &trans->upstream);
krh@248
   617
krh@248
   618
	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
krh@248
   619
		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
krh@248
   620
				       &upi.pool[upi.p->name]);
krh@248
   621
krh@248
   622
		if (sp)
krh@248
   623
			flag_matching_providers(trans, &spi, up, &upi,
krh@248
   624
						TRANS_PACKAGE_UPDATE);
krh@248
   625
	}
krh@248
   626
}
krh@248
   627
krh@248
   628
static void
krh@248
   629
pull_in_requirements(struct razor_transaction *trans,
krh@248
   630
		     struct prop_iter *rpi, struct prop_iter *ppi)
krh@248
   631
{
krh@248
   632
	struct razor_property *rp, *pp;
krh@248
   633
	struct razor_package *pkg, *upkgs;
krh@248
   634
krh@248
   635
	upkgs = trans->upstream.set->packages.data;
krh@248
   636
	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   637
		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
krh@248
   638
			continue;
krh@248
   639
krh@248
   640
		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
krh@248
   641
				       &rpi->pool[rp->name]);
krh@248
   642
		if (pp == NULL)
krh@248
   643
			continue;
krh@248
   644
		pkg = pick_matching_provider(trans->upstream.set,
krh@248
   645
					     ppi, rp->flags,
krh@248
   646
					     &rpi->pool[rp->version]);
krh@248
   647
		if (pkg == NULL)
krh@248
   648
			continue;
krh@248
   649
krh@248
   650
		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
krh@248
   651
ali@403
   652
#if 0
krh@257
   653
		fprintf(stderr, "pulling in %s-%s.%s which provides %s %s %s "
krh@248
   654
			"to satisfy %s %s %s\n",
krh@248
   655
			ppi->pool + pkg->name,
krh@257
   656
			ppi->pool + pkg->version,
krh@257
   657
			ppi->pool + pkg->arch,
krh@248
   658
			ppi->pool + pp->name,
krh@248
   659
			razor_property_relation_to_string(pp),
krh@248
   660
			ppi->pool + pp->version,
krh@248
   661
			&rpi->pool[rp->name],
krh@248
   662
			razor_property_relation_to_string(rp),
krh@248
   663
			&rpi->pool[rp->version]);
ali@403
   664
#endif
krh@248
   665
krh@248
   666
		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
krh@248
   667
	}
krh@248
   668
}
krh@248
   669
krh@248
   670
static void
krh@248
   671
pull_in_all_requirements(struct razor_transaction *trans)
krh@248
   672
{
krh@248
   673
	struct prop_iter rpi, ppi;
krh@248
   674
krh@248
   675
	prop_iter_init(&rpi, &trans->system);
krh@248
   676
	prop_iter_init(&ppi, &trans->upstream);
krh@248
   677
	pull_in_requirements(trans, &rpi, &ppi);
krh@248
   678
krh@248
   679
	prop_iter_init(&rpi, &trans->upstream);
krh@248
   680
	prop_iter_init(&ppi, &trans->upstream);
krh@248
   681
	pull_in_requirements(trans, &rpi, &ppi);
krh@248
   682
}
krh@248
   683
krh@248
   684
static void
krh@248
   685
flush_scheduled_system_updates(struct razor_transaction *trans)
krh@248
   686
{
krh@248
   687
 	struct razor_package_iterator *pi;
krh@248
   688
 	struct razor_package *p, *pkg, *spkgs;
krh@248
   689
	struct prop_iter ppi;
richard@302
   690
	const char *name, *version;
krh@248
   691
krh@248
   692
	spkgs = trans->system.set->packages.data;
krh@248
   693
	pi = razor_package_iterator_create(trans->system.set);
krh@248
   694
	prop_iter_init(&ppi, &trans->upstream);
krh@248
   695
richard@302
   696
	while (razor_package_iterator_next(pi, &p,
richard@302
   697
					   RAZOR_DETAIL_NAME, &name,
richard@307
   698
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   699
					   RAZOR_DETAIL_LAST)) {
krh@248
   700
		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
krh@248
   701
			continue;
ali@432
   702
		trans->system.packages[p - spkgs] &= ~TRANS_PACKAGE_UPDATE;
krh@248
   703
krh@248
   704
		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
krh@248
   705
			continue;
krh@248
   706
ali@386
   707
		if (any_provider_satisfies_requirement(&ppi,
ali@386
   708
						       RAZOR_PROPERTY_GREATER,
ali@386
   709
						       version)) {
ali@386
   710
			razor_transaction_remove_package(trans, p);
ali@386
   711
			continue;
ali@386
   712
		}
ali@386
   713
krh@248
   714
		pkg = pick_matching_provider(trans->upstream.set, &ppi,
krh@248
   715
					     RAZOR_PROPERTY_GREATER, version);
krh@248
   716
		if (pkg == NULL)
krh@248
   717
			continue;
krh@248
   718
krh@248
   719
		razor_transaction_remove_package(trans, p);
krh@248
   720
		razor_transaction_install_package(trans, pkg);
krh@248
   721
	}
krh@248
   722
krh@248
   723
	razor_package_iterator_destroy(pi);
krh@248
   724
}
krh@248
   725
krh@248
   726
static void
krh@248
   727
flush_scheduled_upstream_updates(struct razor_transaction *trans)
krh@248
   728
{
krh@248
   729
 	struct razor_package_iterator *pi;
krh@248
   730
 	struct razor_package *p, *upkgs;
krh@248
   731
	struct prop_iter spi;
richard@302
   732
	const char *name, *version;
krh@248
   733
krh@248
   734
	upkgs = trans->upstream.set->packages.data;
krh@248
   735
	pi = razor_package_iterator_create(trans->upstream.set);
krh@248
   736
	prop_iter_init(&spi, &trans->system);
krh@248
   737
richard@302
   738
	while (razor_package_iterator_next(pi, &p,
richard@302
   739
					   RAZOR_DETAIL_NAME, &name,
richard@307
   740
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   741
					   RAZOR_DETAIL_LAST)) {
krh@248
   742
		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
krh@248
   743
			continue;
ali@432
   744
		trans->upstream.packages[p - upkgs] &= ~TRANS_PACKAGE_UPDATE;
krh@248
   745
krh@248
   746
		if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
krh@248
   747
			remove_matching_providers(trans,
krh@248
   748
						  &spi,
krh@248
   749
						  RAZOR_PROPERTY_LESS,
krh@248
   750
						  version);
krh@248
   751
		razor_transaction_install_package(trans, p);
ali@403
   752
#if 0
krh@248
   753
		fprintf(stderr, "installing %s-%s\n", name, version);
ali@403
   754
#endif
krh@248
   755
	}
ali@458
   756
ali@458
   757
	razor_package_iterator_destroy(pi);
krh@248
   758
}
krh@248
   759
krh@269
   760
RAZOR_EXPORT int
krh@248
   761
razor_transaction_resolve(struct razor_transaction *trans)
krh@248
   762
{
krh@248
   763
	int last = 0;
krh@248
   764
krh@248
   765
	flush_scheduled_system_updates(trans);
krh@248
   766
	flush_scheduled_upstream_updates(trans);
krh@248
   767
krh@248
   768
	while (last < trans->changes) {
krh@248
   769
		last = trans->changes;
krh@248
   770
		remove_obsoleted_packages(trans);
krh@248
   771
		mark_all_satisfied_requires(trans);
krh@248
   772
		update_unsatisfied_packages(trans);
krh@248
   773
		update_conflicted_packages(trans);
krh@248
   774
		pull_in_all_requirements(trans);
krh@248
   775
		flush_scheduled_system_updates(trans);
krh@248
   776
		flush_scheduled_upstream_updates(trans);
krh@248
   777
	}
krh@248
   778
krh@248
   779
	return trans->changes;
krh@248
   780
}
krh@248
   781
krh@248
   782
static void
ali@446
   783
describe_unsatisfied(struct razor_set *set, struct razor_property *rp,
ali@446
   784
		     razor_unsatisfied_callback_t callback, void *data)
krh@248
   785
{
krh@248
   786
	struct razor_package_iterator pi;
krh@248
   787
	struct razor_package *pkg;
krh@248
   788
	const char *name, *version, *arch, *pool;
ali@446
   789
	const char *requirement;
ali@446
   790
	char *s = NULL;
krh@248
   791
krh@248
   792
	pool = set->string_pool.data;
ali@446
   793
	if (pool[rp->version] == '\0')
ali@446
   794
		requirement = &pool[rp->name];
ali@446
   795
	else {
ali@446
   796
		s = razor_concat(&pool[rp->name], " ",
ali@446
   797
				 razor_property_relation_to_string(rp), " ",
ali@446
   798
				 &pool[rp->version], NULL);
ali@446
   799
		requirement = s;
krh@248
   800
	}
ali@446
   801
ali@446
   802
	razor_package_iterator_init_for_property(&pi, set, rp);
ali@446
   803
	while (razor_package_iterator_next(&pi, &pkg,
ali@446
   804
					   RAZOR_DETAIL_NAME, &name,
ali@446
   805
					   RAZOR_DETAIL_VERSION, &version,
ali@446
   806
					   RAZOR_DETAIL_ARCH, &arch,
ali@446
   807
					   RAZOR_DETAIL_LAST))
ali@446
   808
		callback(requirement, pkg, name, version, arch, data);
ali@446
   809
ali@446
   810
	if (s)
ali@446
   811
		free(s);
krh@248
   812
}
krh@248
   813
krh@269
   814
RAZOR_EXPORT int
ali@446
   815
razor_transaction_unsatisfied(struct razor_transaction *trans,
ali@446
   816
			      razor_unsatisfied_callback_t callback, void *data)
krh@248
   817
{
krh@248
   818
	struct prop_iter rpi;
krh@248
   819
	struct razor_property *rp;
krh@248
   820
	int unsatisfied;
krh@248
   821
krh@248
   822
	flush_scheduled_system_updates(trans);
krh@248
   823
	flush_scheduled_upstream_updates(trans);
krh@248
   824
	mark_all_satisfied_requires(trans);
krh@248
   825
krh@248
   826
	unsatisfied = 0;
krh@248
   827
	prop_iter_init(&rpi, &trans->system);
krh@248
   828
	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   829
		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
ali@446
   830
			if (callback)
ali@446
   831
				describe_unsatisfied(trans->system.set, rp,
ali@446
   832
						     callback, data);
krh@248
   833
		        unsatisfied++;
krh@248
   834
		}
krh@248
   835
	}
krh@248
   836
krh@248
   837
	prop_iter_init(&rpi, &trans->upstream);
krh@248
   838
	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   839
		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
ali@446
   840
			if (callback)
ali@446
   841
				describe_unsatisfied(trans->upstream.set, rp,
ali@446
   842
						     callback, data);
krh@248
   843
			unsatisfied++;
krh@248
   844
		}
krh@248
   845
	}
krh@248
   846
krh@248
   847
	return unsatisfied;
krh@248
   848
}
krh@248
   849
ali@446
   850
static void
ali@446
   851
describe_unsatisfied_callback(const char *requirement,
ali@446
   852
			      struct razor_package *package, const char *name,
ali@446
   853
			      const char *version, const char *arch, void *data)
ali@446
   854
{
ali@446
   855
	FILE *fp = data;
ali@446
   856
ali@446
   857
	fprintf(fp, "%s is needed by %s-%s.%s\n", requirement,
ali@446
   858
		name, version, arch);
ali@446
   859
}
ali@446
   860
ali@446
   861
RAZOR_EXPORT int
ali@446
   862
razor_transaction_describe(struct razor_transaction *trans)
ali@446
   863
{
ali@446
   864
	return razor_transaction_unsatisfied(trans,
ali@446
   865
					     describe_unsatisfied_callback,
ali@446
   866
					     stderr);
ali@446
   867
}
ali@446
   868
krh@269
   869
RAZOR_EXPORT int
krh@248
   870
razor_transaction_unsatisfied_property(struct razor_transaction *trans,
krh@248
   871
				       const char *name,
krh@248
   872
				       uint32_t flags,
krh@248
   873
				       const char *version)
krh@248
   874
{
krh@248
   875
	struct prop_iter pi;
krh@248
   876
	struct razor_property *p;
krh@248
   877
krh@248
   878
	prop_iter_init(&pi, &trans->system);
jbowes@284
   879
	while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
krh@248
   880
		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
krh@248
   881
		    p->flags == flags &&
krh@248
   882
		    strcmp(&pi.pool[p->name], name) == 0 &&
krh@248
   883
		    strcmp(&pi.pool[p->version], version) == 0)
krh@248
   884
krh@248
   885
			return 1;
krh@248
   886
	}
krh@248
   887
krh@248
   888
	prop_iter_init(&pi, &trans->upstream);
jbowes@284
   889
	while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
krh@248
   890
		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
krh@248
   891
		    p->flags == flags &&
krh@248
   892
		    strcmp(&pi.pool[p->name], name) == 0 &&
krh@248
   893
		    strcmp(&pi.pool[p->version], version) == 0)
krh@248
   894
krh@248
   895
			return 1;
krh@248
   896
	}
krh@248
   897
krh@248
   898
	return 0;
krh@248
   899
}
krh@248
   900
krh@269
   901
RAZOR_EXPORT struct razor_set *
ali@369
   902
razor_transaction_commit(struct razor_transaction *trans)
krh@248
   903
{
krh@248
   904
	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
krh@248
   905
	char *upool, *spool;
krh@248
   906
	int cmp;
krh@248
   907
krh@248
   908
	s = trans->system.set->packages.data;
krh@248
   909
	spkgs = trans->system.set->packages.data;
krh@248
   910
	send = trans->system.set->packages.data +
krh@248
   911
		trans->system.set->packages.size;
krh@248
   912
	spool = trans->system.set->string_pool.data;
krh@248
   913
krh@248
   914
	u = trans->upstream.set->packages.data;
krh@248
   915
	upkgs = trans->upstream.set->packages.data;
krh@248
   916
	uend = trans->upstream.set->packages.data +
krh@248
   917
		trans->upstream.set->packages.size;
krh@248
   918
	upool = trans->upstream.set->string_pool.data;
krh@248
   919
ali@369
   920
	trans->merger = razor_merger_create(trans->system.set,
ali@369
   921
					    trans->upstream.set);
krh@248
   922
	while (s < send || u < uend) {
krh@248
   923
		if (s < send && u < uend)
krh@248
   924
			cmp = strcmp(&spool[s->name], &upool[u->name]);
krh@248
   925
		else if (s < send)
krh@248
   926
			cmp = -1;
krh@248
   927
		else
krh@248
   928
			cmp = 1;
krh@248
   929
krh@248
   930
		if (cmp < 0) {
krh@248
   931
			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   932
				razor_merger_add_package(trans->merger, s);
krh@248
   933
			s++;
krh@248
   934
		} else if (cmp == 0) {
krh@248
   935
			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   936
				razor_merger_add_package(trans->merger, s);
krh@248
   937
			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   938
				razor_merger_add_package(trans->merger, u);
krh@248
   939
krh@248
   940
			s++;
krh@248
   941
			u++;
krh@248
   942
		} else {
krh@248
   943
			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   944
				razor_merger_add_package(trans->merger, u);
krh@248
   945
			u++;
krh@248
   946
		}
krh@248
   947
	}
krh@248
   948
ali@369
   949
	return razor_merger_commit(trans->merger);
ali@369
   950
}
krh@248
   951
ali@369
   952
RAZOR_EXPORT void
ali@369
   953
razor_transaction_fixup_package(struct razor_transaction *trans,
ali@369
   954
				struct razor_package *package,
ali@369
   955
				struct razor_rpm *rpm)
ali@369
   956
{
ali@369
   957
	const char *preunprog, *preun, *postunprog, *postun;
ali@369
   958
ali@369
   959
	razor_rpm_get_details(rpm,
ali@369
   960
			      RAZOR_DETAIL_PREUNPROG, &preunprog,
ali@369
   961
			      RAZOR_DETAIL_PREUN, &preun,
ali@369
   962
			      RAZOR_DETAIL_POSTUNPROG, &postunprog,
ali@369
   963
			      RAZOR_DETAIL_POSTUN, &postun,
ali@369
   964
			      RAZOR_DETAIL_LAST);
ali@369
   965
ali@369
   966
	razor_merger_package_add_script(trans->merger, package,
ali@369
   967
					RAZOR_PROPERTY_PREUN,
ali@369
   968
					preunprog, preun);
ali@369
   969
	razor_merger_package_add_script(trans->merger, package,
ali@369
   970
					RAZOR_PROPERTY_POSTUN,
ali@369
   971
					postunprog, postun);
krh@248
   972
}
krh@248
   973
krh@269
   974
RAZOR_EXPORT void
krh@248
   975
razor_transaction_destroy(struct razor_transaction *trans)
krh@248
   976
{
richard@301
   977
	assert (trans != NULL);
richard@301
   978
ali@369
   979
	if (trans->merger)
ali@369
   980
		razor_merger_destroy(trans->merger);
krh@248
   981
	transaction_set_release(&trans->system);
krh@248
   982
	transaction_set_release(&trans->upstream);
krh@248
   983
	free(trans);
krh@248
   984
}