librazor/transaction.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Oct 04 18:12:58 2014 +0100 (2014-10-04)
changeset 454 56ff755c268c
parent 442 c4bcba8023a9
child 458 3f841a46eab5
permissions -rw-r--r--
Only export symbols starting with razor_ in dynamic library.

Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.

Note that under mingw librazor-#.dll still contains undocumented
(private) razor_ symbols but these will do no harm as long as nobody
tries to use them.
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
	}
krh@248
   756
}
krh@248
   757
krh@269
   758
RAZOR_EXPORT int
krh@248
   759
razor_transaction_resolve(struct razor_transaction *trans)
krh@248
   760
{
krh@248
   761
	int last = 0;
krh@248
   762
krh@248
   763
	flush_scheduled_system_updates(trans);
krh@248
   764
	flush_scheduled_upstream_updates(trans);
krh@248
   765
krh@248
   766
	while (last < trans->changes) {
krh@248
   767
		last = trans->changes;
krh@248
   768
		remove_obsoleted_packages(trans);
krh@248
   769
		mark_all_satisfied_requires(trans);
krh@248
   770
		update_unsatisfied_packages(trans);
krh@248
   771
		update_conflicted_packages(trans);
krh@248
   772
		pull_in_all_requirements(trans);
krh@248
   773
		flush_scheduled_system_updates(trans);
krh@248
   774
		flush_scheduled_upstream_updates(trans);
krh@248
   775
	}
krh@248
   776
krh@248
   777
	return trans->changes;
krh@248
   778
}
krh@248
   779
krh@248
   780
static void
ali@446
   781
describe_unsatisfied(struct razor_set *set, struct razor_property *rp,
ali@446
   782
		     razor_unsatisfied_callback_t callback, void *data)
krh@248
   783
{
krh@248
   784
	struct razor_package_iterator pi;
krh@248
   785
	struct razor_package *pkg;
krh@248
   786
	const char *name, *version, *arch, *pool;
ali@446
   787
	const char *requirement;
ali@446
   788
	char *s = NULL;
krh@248
   789
krh@248
   790
	pool = set->string_pool.data;
ali@446
   791
	if (pool[rp->version] == '\0')
ali@446
   792
		requirement = &pool[rp->name];
ali@446
   793
	else {
ali@446
   794
		s = razor_concat(&pool[rp->name], " ",
ali@446
   795
				 razor_property_relation_to_string(rp), " ",
ali@446
   796
				 &pool[rp->version], NULL);
ali@446
   797
		requirement = s;
krh@248
   798
	}
ali@446
   799
ali@446
   800
	razor_package_iterator_init_for_property(&pi, set, rp);
ali@446
   801
	while (razor_package_iterator_next(&pi, &pkg,
ali@446
   802
					   RAZOR_DETAIL_NAME, &name,
ali@446
   803
					   RAZOR_DETAIL_VERSION, &version,
ali@446
   804
					   RAZOR_DETAIL_ARCH, &arch,
ali@446
   805
					   RAZOR_DETAIL_LAST))
ali@446
   806
		callback(requirement, pkg, name, version, arch, data);
ali@446
   807
ali@446
   808
	if (s)
ali@446
   809
		free(s);
krh@248
   810
}
krh@248
   811
krh@269
   812
RAZOR_EXPORT int
ali@446
   813
razor_transaction_unsatisfied(struct razor_transaction *trans,
ali@446
   814
			      razor_unsatisfied_callback_t callback, void *data)
krh@248
   815
{
krh@248
   816
	struct prop_iter rpi;
krh@248
   817
	struct razor_property *rp;
krh@248
   818
	int unsatisfied;
krh@248
   819
krh@248
   820
	flush_scheduled_system_updates(trans);
krh@248
   821
	flush_scheduled_upstream_updates(trans);
krh@248
   822
	mark_all_satisfied_requires(trans);
krh@248
   823
krh@248
   824
	unsatisfied = 0;
krh@248
   825
	prop_iter_init(&rpi, &trans->system);
krh@248
   826
	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   827
		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
ali@446
   828
			if (callback)
ali@446
   829
				describe_unsatisfied(trans->system.set, rp,
ali@446
   830
						     callback, data);
krh@248
   831
		        unsatisfied++;
krh@248
   832
		}
krh@248
   833
	}
krh@248
   834
krh@248
   835
	prop_iter_init(&rpi, &trans->upstream);
krh@248
   836
	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
krh@248
   837
		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
ali@446
   838
			if (callback)
ali@446
   839
				describe_unsatisfied(trans->upstream.set, rp,
ali@446
   840
						     callback, data);
krh@248
   841
			unsatisfied++;
krh@248
   842
		}
krh@248
   843
	}
krh@248
   844
krh@248
   845
	return unsatisfied;
krh@248
   846
}
krh@248
   847
ali@446
   848
static void
ali@446
   849
describe_unsatisfied_callback(const char *requirement,
ali@446
   850
			      struct razor_package *package, const char *name,
ali@446
   851
			      const char *version, const char *arch, void *data)
ali@446
   852
{
ali@446
   853
	FILE *fp = data;
ali@446
   854
ali@446
   855
	fprintf(fp, "%s is needed by %s-%s.%s\n", requirement,
ali@446
   856
		name, version, arch);
ali@446
   857
}
ali@446
   858
ali@446
   859
RAZOR_EXPORT int
ali@446
   860
razor_transaction_describe(struct razor_transaction *trans)
ali@446
   861
{
ali@446
   862
	return razor_transaction_unsatisfied(trans,
ali@446
   863
					     describe_unsatisfied_callback,
ali@446
   864
					     stderr);
ali@446
   865
}
ali@446
   866
krh@269
   867
RAZOR_EXPORT int
krh@248
   868
razor_transaction_unsatisfied_property(struct razor_transaction *trans,
krh@248
   869
				       const char *name,
krh@248
   870
				       uint32_t flags,
krh@248
   871
				       const char *version)
krh@248
   872
{
krh@248
   873
	struct prop_iter pi;
krh@248
   874
	struct razor_property *p;
krh@248
   875
krh@248
   876
	prop_iter_init(&pi, &trans->system);
jbowes@284
   877
	while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
krh@248
   878
		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
krh@248
   879
		    p->flags == flags &&
krh@248
   880
		    strcmp(&pi.pool[p->name], name) == 0 &&
krh@248
   881
		    strcmp(&pi.pool[p->version], version) == 0)
krh@248
   882
krh@248
   883
			return 1;
krh@248
   884
	}
krh@248
   885
krh@248
   886
	prop_iter_init(&pi, &trans->upstream);
jbowes@284
   887
	while (prop_iter_next(&pi, flags & RAZOR_PROPERTY_TYPE_MASK, &p)) {
krh@248
   888
		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
krh@248
   889
		    p->flags == flags &&
krh@248
   890
		    strcmp(&pi.pool[p->name], name) == 0 &&
krh@248
   891
		    strcmp(&pi.pool[p->version], version) == 0)
krh@248
   892
krh@248
   893
			return 1;
krh@248
   894
	}
krh@248
   895
krh@248
   896
	return 0;
krh@248
   897
}
krh@248
   898
krh@269
   899
RAZOR_EXPORT struct razor_set *
ali@369
   900
razor_transaction_commit(struct razor_transaction *trans)
krh@248
   901
{
krh@248
   902
	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
krh@248
   903
	char *upool, *spool;
krh@248
   904
	int cmp;
krh@248
   905
krh@248
   906
	s = trans->system.set->packages.data;
krh@248
   907
	spkgs = trans->system.set->packages.data;
krh@248
   908
	send = trans->system.set->packages.data +
krh@248
   909
		trans->system.set->packages.size;
krh@248
   910
	spool = trans->system.set->string_pool.data;
krh@248
   911
krh@248
   912
	u = trans->upstream.set->packages.data;
krh@248
   913
	upkgs = trans->upstream.set->packages.data;
krh@248
   914
	uend = trans->upstream.set->packages.data +
krh@248
   915
		trans->upstream.set->packages.size;
krh@248
   916
	upool = trans->upstream.set->string_pool.data;
krh@248
   917
ali@369
   918
	trans->merger = razor_merger_create(trans->system.set,
ali@369
   919
					    trans->upstream.set);
krh@248
   920
	while (s < send || u < uend) {
krh@248
   921
		if (s < send && u < uend)
krh@248
   922
			cmp = strcmp(&spool[s->name], &upool[u->name]);
krh@248
   923
		else if (s < send)
krh@248
   924
			cmp = -1;
krh@248
   925
		else
krh@248
   926
			cmp = 1;
krh@248
   927
krh@248
   928
		if (cmp < 0) {
krh@248
   929
			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   930
				razor_merger_add_package(trans->merger, s);
krh@248
   931
			s++;
krh@248
   932
		} else if (cmp == 0) {
krh@248
   933
			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   934
				razor_merger_add_package(trans->merger, s);
krh@248
   935
			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   936
				razor_merger_add_package(trans->merger, u);
krh@248
   937
krh@248
   938
			s++;
krh@248
   939
			u++;
krh@248
   940
		} else {
krh@248
   941
			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
ali@369
   942
				razor_merger_add_package(trans->merger, u);
krh@248
   943
			u++;
krh@248
   944
		}
krh@248
   945
	}
krh@248
   946
ali@369
   947
	return razor_merger_commit(trans->merger);
ali@369
   948
}
krh@248
   949
ali@369
   950
RAZOR_EXPORT void
ali@369
   951
razor_transaction_fixup_package(struct razor_transaction *trans,
ali@369
   952
				struct razor_package *package,
ali@369
   953
				struct razor_rpm *rpm)
ali@369
   954
{
ali@369
   955
	const char *preunprog, *preun, *postunprog, *postun;
ali@369
   956
ali@369
   957
	razor_rpm_get_details(rpm,
ali@369
   958
			      RAZOR_DETAIL_PREUNPROG, &preunprog,
ali@369
   959
			      RAZOR_DETAIL_PREUN, &preun,
ali@369
   960
			      RAZOR_DETAIL_POSTUNPROG, &postunprog,
ali@369
   961
			      RAZOR_DETAIL_POSTUN, &postun,
ali@369
   962
			      RAZOR_DETAIL_LAST);
ali@369
   963
ali@369
   964
	razor_merger_package_add_script(trans->merger, package,
ali@369
   965
					RAZOR_PROPERTY_PREUN,
ali@369
   966
					preunprog, preun);
ali@369
   967
	razor_merger_package_add_script(trans->merger, package,
ali@369
   968
					RAZOR_PROPERTY_POSTUN,
ali@369
   969
					postunprog, postun);
krh@248
   970
}
krh@248
   971
krh@269
   972
RAZOR_EXPORT void
krh@248
   973
razor_transaction_destroy(struct razor_transaction *trans)
krh@248
   974
{
richard@301
   975
	assert (trans != NULL);
richard@301
   976
ali@369
   977
	if (trans->merger)
ali@369
   978
		razor_merger_destroy(trans->merger);
krh@248
   979
	transaction_set_release(&trans->system);
krh@248
   980
	transaction_set_release(&trans->upstream);
krh@248
   981
	free(trans);
krh@248
   982
}