src/main.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 21:56:43 2008 -0400 (2008-06-20)
changeset 254 ccb1c11968ab
parent 253 338a577cdfd2
child 255 5cd6aa72bbd5
permissions -rw-r--r--
Introduce install/remove iterators.

These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.

Right now, the install order isn't actually implemented, this patch just
implements the API changes and updates the applications.
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
rhughes@241
     4
 *
rhughes@241
     5
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     6
 * it under the terms of the GNU General Public License as published by
rhughes@241
     7
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     8
 * (at your option) any later version.
rhughes@241
     9
 *
rhughes@241
    10
 * This program is distributed in the hope that it will be useful,
rhughes@241
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    13
 * GNU General Public License for more details.
rhughes@241
    14
 *
rhughes@241
    15
 * You should have received a copy of the GNU General Public License along
rhughes@241
    16
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    18
 */
rhughes@241
    19
rhughes@241
    20
#include <stdlib.h>
rhughes@241
    21
#include <stddef.h>
rhughes@241
    22
#include <stdio.h>
rhughes@241
    23
#include <stdint.h>
rhughes@241
    24
#include <string.h>
rhughes@241
    25
#include <sys/stat.h>
rhughes@241
    26
#include <unistd.h>
rhughes@241
    27
#include <fcntl.h>
rhughes@241
    28
#include <dirent.h>
rhughes@241
    29
#include <curl/curl.h>
rhughes@241
    30
#include <fnmatch.h>
rhughes@241
    31
#include <errno.h>
rhughes@241
    32
#include "razor.h"
rhughes@241
    33
rhughes@241
    34
static const char system_repo_filename[] = "system.repo";
rhughes@241
    35
static const char next_repo_filename[] = "system-next.repo";
rhughes@241
    36
static const char rawhide_repo_filename[] = "rawhide.repo";
rhughes@241
    37
static const char updated_repo_filename[] = "system-updated.repo";
rhughes@241
    38
static const char install_root[] = "install";
rhughes@241
    39
static const char *repo_filename = system_repo_filename;
rhughes@241
    40
static const char *yum_url;
rhughes@241
    41
rhughes@241
    42
static int
rhughes@241
    43
command_list(int argc, const char *argv[])
rhughes@241
    44
{
rhughes@241
    45
	struct razor_set *set;
rhughes@241
    46
	struct razor_package_iterator *pi;
rhughes@241
    47
	struct razor_package *package;
rhughes@241
    48
	const char *pattern, *name, *version, *arch;
rhughes@241
    49
	int only_names = 0, i = 0;
rhughes@241
    50
rhughes@241
    51
	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
rhughes@241
    52
		only_names = 1;
rhughes@241
    53
		i++;
rhughes@241
    54
	}
rhughes@241
    55
rhughes@241
    56
	pattern = argv[i];
rhughes@241
    57
	set = razor_set_open(repo_filename);
rhughes@241
    58
	pi = razor_package_iterator_create(set);
rhughes@241
    59
	while (razor_package_iterator_next(pi, &package,
rhughes@241
    60
					   &name, &version, &arch)) {
rhughes@241
    61
		if (pattern && fnmatch(pattern, name, 0) != 0)
rhughes@241
    62
			continue;
rhughes@241
    63
rhughes@241
    64
		if (only_names)
rhughes@241
    65
			printf("%s\n", name);
rhughes@241
    66
		else
rhughes@241
    67
			printf("%s-%s.%s\n", name, version, arch);
rhughes@241
    68
	}
rhughes@241
    69
	razor_package_iterator_destroy(pi);
rhughes@241
    70
	razor_set_destroy(set);
rhughes@241
    71
rhughes@241
    72
	return 0;
rhughes@241
    73
}
rhughes@241
    74
rhughes@241
    75
static int
krh@247
    76
list_properties(const char *package_name, uint32_t type)
rhughes@241
    77
{
rhughes@241
    78
	struct razor_set *set;
rhughes@241
    79
	struct razor_property *property;
rhughes@241
    80
	struct razor_package *package;
rhughes@241
    81
	struct razor_property_iterator *pi;
rhughes@241
    82
	const char *name, *version;
krh@247
    83
	uint32_t flags;
rhughes@241
    84
rhughes@241
    85
	set = razor_set_open(repo_filename);
rhughes@241
    86
	if (package_name)
rhughes@241
    87
		package = razor_set_get_package(set, package_name);
rhughes@241
    88
	else
rhughes@241
    89
		package = NULL;
rhughes@241
    90
rhughes@241
    91
	pi = razor_property_iterator_create(set, package);
rhughes@241
    92
	while (razor_property_iterator_next(pi, &property,
krh@247
    93
					    &name, &flags, &version)) {
krh@247
    94
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
rhughes@241
    95
			continue;
krh@247
    96
		printf("%s", name);
krh@247
    97
		if (version[0] != '\0')
krh@247
    98
			printf(" %s %s",
krh@247
    99
			       razor_property_relation_to_string(property),
krh@247
   100
			       version);
krh@247
   101
krh@247
   102
		if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
krh@247
   103
			printf(" [");
krh@247
   104
			if (flags & RAZOR_PROPERTY_PRE)
krh@247
   105
				printf(" pre");
krh@247
   106
			if (flags & RAZOR_PROPERTY_POST)
krh@247
   107
				printf(" post");
krh@247
   108
			if (flags & RAZOR_PROPERTY_PREUN)
krh@247
   109
				printf(" preun");
krh@247
   110
			if (flags & RAZOR_PROPERTY_POSTUN)
krh@247
   111
				printf(" postun");
krh@247
   112
			printf(" ]");
krh@247
   113
		}
krh@247
   114
		printf("\n");
rhughes@241
   115
	}
rhughes@241
   116
	razor_property_iterator_destroy(pi);
rhughes@241
   117
rhughes@241
   118
	razor_set_destroy(set);
rhughes@241
   119
rhughes@241
   120
	return 0;
rhughes@241
   121
}
rhughes@241
   122
rhughes@241
   123
static int
rhughes@241
   124
command_list_requires(int argc, const char *argv[])
rhughes@241
   125
{
rhughes@241
   126
	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
rhughes@241
   127
}
rhughes@241
   128
rhughes@241
   129
static int
rhughes@241
   130
command_list_provides(int argc, const char *argv[])
rhughes@241
   131
{
rhughes@241
   132
	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
rhughes@241
   133
}
rhughes@241
   134
rhughes@241
   135
static int
rhughes@241
   136
command_list_obsoletes(int argc, const char *argv[])
rhughes@241
   137
{
rhughes@241
   138
	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
rhughes@241
   139
}
rhughes@241
   140
rhughes@241
   141
static int
rhughes@241
   142
command_list_conflicts(int argc, const char *argv[])
rhughes@241
   143
{
rhughes@241
   144
	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
rhughes@241
   145
}
rhughes@241
   146
rhughes@241
   147
static int
rhughes@241
   148
command_list_files(int argc, const char *argv[])
rhughes@241
   149
{
rhughes@241
   150
	struct razor_set *set;
rhughes@241
   151
rhughes@241
   152
	set = razor_set_open(repo_filename);
rhughes@241
   153
	if (set == NULL)
rhughes@241
   154
		return 1;
rhughes@241
   155
	razor_set_list_files(set, argv[0]);
rhughes@241
   156
	razor_set_destroy(set);
rhughes@241
   157
rhughes@241
   158
	return 0;
rhughes@241
   159
}
rhughes@241
   160
rhughes@241
   161
static int
rhughes@241
   162
command_list_file_packages(int argc, const char *argv[])
rhughes@241
   163
{
rhughes@241
   164
	struct razor_set *set;
rhughes@241
   165
	struct razor_package_iterator *pi;
rhughes@241
   166
	struct razor_package *package;
rhughes@241
   167
	const char *name, *version, *arch;
rhughes@241
   168
rhughes@241
   169
	set = razor_set_open(repo_filename);
rhughes@241
   170
	if (set == NULL)
rhughes@241
   171
		return 1;
rhughes@241
   172
rhughes@241
   173
	pi = razor_package_iterator_create_for_file(set, argv[0]);
rhughes@241
   174
	while (razor_package_iterator_next(pi, &package,
rhughes@241
   175
					   &name, &version, &arch))
rhughes@241
   176
		printf("%s-%s\n", name, version);
rhughes@241
   177
	razor_package_iterator_destroy(pi);
rhughes@241
   178
rhughes@241
   179
	razor_set_destroy(set);
rhughes@241
   180
rhughes@241
   181
	return 0;
rhughes@241
   182
}
rhughes@241
   183
rhughes@241
   184
static int
rhughes@241
   185
command_list_package_files(int argc, const char *argv[])
rhughes@241
   186
{
rhughes@241
   187
	struct razor_set *set;
rhughes@241
   188
rhughes@241
   189
	set = razor_set_open(repo_filename);
rhughes@241
   190
	if (set == NULL)
rhughes@241
   191
		return 1;
rhughes@241
   192
	razor_set_list_package_files(set, argv[0]);
rhughes@241
   193
	razor_set_destroy(set);
rhughes@241
   194
rhughes@241
   195
	return 0;
rhughes@241
   196
}
rhughes@241
   197
rhughes@241
   198
static void
rhughes@241
   199
list_packages_for_property(struct razor_set *set,
rhughes@241
   200
			   struct razor_property *property)
rhughes@241
   201
{
rhughes@241
   202
	struct razor_package_iterator *pi;
rhughes@241
   203
	struct razor_package *package;
rhughes@241
   204
	const char *name, *version, *arch;
rhughes@241
   205
rhughes@241
   206
	pi = razor_package_iterator_create_for_property(set, property);
rhughes@241
   207
	while (razor_package_iterator_next(pi, &package,
rhughes@241
   208
					   &name, &version, &arch))
rhughes@241
   209
		printf("%s-%s.%s\n", name, version, arch);
rhughes@241
   210
	razor_package_iterator_destroy(pi);
rhughes@241
   211
}
rhughes@241
   212
rhughes@241
   213
static int
rhughes@241
   214
list_property_packages(const char *ref_name,
rhughes@241
   215
		       const char *ref_version,
krh@247
   216
		       uint32_t type)
rhughes@241
   217
{
rhughes@241
   218
	struct razor_set *set;
rhughes@241
   219
	struct razor_property *property;
rhughes@241
   220
	struct razor_property_iterator *pi;
rhughes@241
   221
	const char *name, *version;
krh@247
   222
	uint32_t flags;
rhughes@241
   223
rhughes@241
   224
	if (ref_name == NULL)
rhughes@241
   225
		return 0;
rhughes@241
   226
rhughes@241
   227
	set = razor_set_open(repo_filename);
rhughes@241
   228
	if (set == NULL)
rhughes@241
   229
		return 1;
rhughes@241
   230
rhughes@241
   231
	pi = razor_property_iterator_create(set, NULL);
rhughes@241
   232
	while (razor_property_iterator_next(pi, &property,
krh@247
   233
					    &name, &flags, &version)) {
rhughes@241
   234
		if (strcmp(ref_name, name) != 0)
rhughes@241
   235
			continue;
krh@247
   236
		if (ref_version &&
krh@247
   237
		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
rhughes@241
   238
		    strcmp(ref_version, version) != 0)
rhughes@241
   239
			continue;
krh@247
   240
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
rhughes@241
   241
			continue;
rhughes@241
   242
rhughes@241
   243
		list_packages_for_property(set, property);
rhughes@241
   244
	}
rhughes@241
   245
	razor_property_iterator_destroy(pi);
rhughes@241
   246
rhughes@241
   247
	return 0;
rhughes@241
   248
}
rhughes@241
   249
rhughes@241
   250
static int
rhughes@241
   251
command_what_requires(int argc, const char *argv[])
rhughes@241
   252
{
rhughes@241
   253
	return list_property_packages(argv[0], argv[1],
rhughes@241
   254
				      RAZOR_PROPERTY_REQUIRES);
rhughes@241
   255
}
rhughes@241
   256
rhughes@241
   257
static int
rhughes@241
   258
command_what_provides(int argc, const char *argv[])
rhughes@241
   259
{
rhughes@241
   260
	return list_property_packages(argv[0], argv[1],
rhughes@241
   261
				      RAZOR_PROPERTY_PROVIDES);
rhughes@241
   262
}
rhughes@241
   263
rhughes@241
   264
static int
rhughes@241
   265
show_progress(void *clientp,
rhughes@241
   266
	      double dltotal, double dlnow, double ultotal, double ulnow)
rhughes@241
   267
{
rhughes@241
   268
	const char *file = clientp;
rhughes@241
   269
rhughes@241
   270
	if (!dlnow < dltotal)
rhughes@241
   271
		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
rhughes@241
   272
			file, (int) dlnow / 1024, (int) dltotal / 1024);
rhughes@241
   273
rhughes@241
   274
	return 0;
rhughes@241
   275
}
rhughes@241
   276
rhughes@241
   277
static int
rhughes@241
   278
download_if_missing(const char *url, const char *file)
rhughes@241
   279
{
rhughes@241
   280
	CURL *curl;
rhughes@241
   281
	struct stat buf;
rhughes@241
   282
	char error[256];
rhughes@241
   283
	FILE *fp;
rhughes@241
   284
	CURLcode res;
rhughes@241
   285
	long response;
rhughes@241
   286
rhughes@241
   287
	curl = curl_easy_init();
rhughes@241
   288
	if (curl == NULL)
rhughes@241
   289
		return 1;
rhughes@241
   290
rhughes@241
   291
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
rhughes@241
   292
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
rhughes@241
   293
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
rhughes@241
   294
	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
rhughes@241
   295
rhughes@241
   296
	if (stat(file, &buf) < 0) {
rhughes@241
   297
		fp = fopen(file, "w");
rhughes@241
   298
		if (fp == NULL) {
rhughes@241
   299
			fprintf(stderr,
rhughes@241
   300
				"failed to open %s for writing\n", file);
rhughes@241
   301
			return -1;
rhughes@241
   302
		}
rhughes@241
   303
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
rhughes@241
   304
		curl_easy_setopt(curl, CURLOPT_URL, url);
rhughes@241
   305
		res = curl_easy_perform(curl);
rhughes@241
   306
		fclose(fp);
rhughes@241
   307
		if (res != CURLE_OK) {
rhughes@241
   308
			fprintf(stderr, "curl error: %s\n", error);
rhughes@241
   309
			unlink(file);
rhughes@241
   310
			return -1;
rhughes@241
   311
		}
rhughes@241
   312
		res = curl_easy_getinfo(curl,
rhughes@241
   313
					CURLINFO_RESPONSE_CODE, &response);
rhughes@241
   314
		if (res != CURLE_OK) {
rhughes@241
   315
			fprintf(stderr, "curl error: %s\n", error);
rhughes@241
   316
                        unlink(file);
rhughes@241
   317
                        return -1;
rhughes@241
   318
		}
rhughes@241
   319
		if (response != 200) {
rhughes@241
   320
			fprintf(stderr, " - failed %ld\n", response);
rhughes@241
   321
                        unlink(file);
rhughes@241
   322
                        return -1;
rhughes@241
   323
		}
rhughes@241
   324
		fprintf(stderr, "\n");
rhughes@241
   325
	}
rhughes@241
   326
rhughes@241
   327
	curl_easy_cleanup(curl);
rhughes@241
   328
rhughes@241
   329
	return 0;
rhughes@241
   330
}
rhughes@241
   331
rhughes@241
   332
#define YUM_URL "http://download.fedora.redhat.com" \
rhughes@241
   333
	"/pub/fedora/linux/development/i386/os"
rhughes@241
   334
rhughes@241
   335
static int
rhughes@241
   336
command_import_yum(int argc, const char *argv[])
rhughes@241
   337
{
rhughes@241
   338
	struct razor_set *set;
rhughes@241
   339
	char buffer[512];
rhughes@241
   340
rhughes@241
   341
	printf("downloading from %s.\n", yum_url);
rhughes@241
   342
	snprintf(buffer, sizeof buffer,
rhughes@241
   343
		 "%s/repodata/primary.xml.gz", yum_url);
rhughes@241
   344
	if (download_if_missing(buffer, "primary.xml.gz") < 0)
rhughes@241
   345
		return -1;
rhughes@241
   346
	snprintf(buffer, sizeof buffer,
rhughes@241
   347
		 "%s/repodata/filelists.xml.gz", yum_url);
rhughes@241
   348
	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
rhughes@241
   349
		return -1;
rhughes@241
   350
rhughes@241
   351
	set = razor_set_create_from_yum();
rhughes@241
   352
	if (set == NULL)
rhughes@241
   353
		return 1;
rhughes@241
   354
	razor_set_write(set, rawhide_repo_filename);
rhughes@241
   355
	razor_set_destroy(set);
rhughes@241
   356
	printf("wrote %s\n", rawhide_repo_filename);
rhughes@241
   357
rhughes@241
   358
	return 0;
rhughes@241
   359
}
rhughes@241
   360
rhughes@241
   361
static int
rhughes@241
   362
command_import_rpmdb(int argc, const char *argv[])
rhughes@241
   363
{
rhughes@241
   364
	struct razor_set *set;
rhughes@241
   365
rhughes@241
   366
	set = razor_set_create_from_rpmdb();
rhughes@241
   367
	if (set == NULL)
rhughes@241
   368
		return 1;
rhughes@241
   369
	razor_set_write(set, repo_filename);
rhughes@241
   370
	razor_set_destroy(set);
rhughes@241
   371
	printf("wrote %s\n", repo_filename);
rhughes@241
   372
rhughes@241
   373
	return 0;
rhughes@241
   374
}
rhughes@241
   375
rhughes@241
   376
static int
rhughes@241
   377
mark_packages_for_update(struct razor_transaction *trans,
rhughes@241
   378
			 struct razor_set *set, const char *pattern)
rhughes@241
   379
{
rhughes@241
   380
	struct razor_package_iterator *pi;
rhughes@241
   381
	struct razor_package *package;
rhughes@241
   382
	const char *name, *version, *arch;
rhughes@241
   383
	int matches = 0;
rhughes@241
   384
rhughes@241
   385
	pi = razor_package_iterator_create(set);
rhughes@241
   386
	while (razor_package_iterator_next(pi, &package,
rhughes@241
   387
					   &name, &version, &arch)) {
rhughes@241
   388
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   389
			razor_transaction_update_package(trans, package);
rhughes@241
   390
			matches++;
rhughes@241
   391
		}
rhughes@241
   392
	}
rhughes@241
   393
	razor_package_iterator_destroy(pi);
rhughes@241
   394
rhughes@241
   395
	return matches;
rhughes@241
   396
}
rhughes@241
   397
rhughes@241
   398
static int
rhughes@241
   399
mark_packages_for_removal(struct razor_transaction *trans,
rhughes@241
   400
			  struct razor_set *set, const char *pattern)
rhughes@241
   401
{
rhughes@241
   402
	struct razor_package_iterator *pi;
rhughes@241
   403
	struct razor_package *package;
rhughes@241
   404
	const char *name, *version, *arch;
rhughes@241
   405
	int matches = 0;
rhughes@241
   406
rhughes@241
   407
	pi = razor_package_iterator_create(set);
rhughes@241
   408
	while (razor_package_iterator_next(pi, &package,
rhughes@241
   409
					   &name, &version, &arch)) {
rhughes@241
   410
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   411
			razor_transaction_remove_package(trans, package);
rhughes@241
   412
			matches++;
rhughes@241
   413
		}
rhughes@241
   414
	}
rhughes@241
   415
	razor_package_iterator_destroy(pi);
rhughes@241
   416
rhughes@241
   417
	return matches;
rhughes@241
   418
}
rhughes@241
   419
rhughes@241
   420
static int
rhughes@241
   421
command_update(int argc, const char *argv[])
rhughes@241
   422
{
rhughes@241
   423
	struct razor_set *set, *upstream;
rhughes@241
   424
	struct razor_transaction *trans;
rhughes@241
   425
	int i, errors;
rhughes@241
   426
rhughes@241
   427
	set = razor_set_open(repo_filename);
rhughes@241
   428
	upstream = razor_set_open(rawhide_repo_filename);
rhughes@241
   429
	if (set == NULL || upstream == NULL)
rhughes@241
   430
		return 1;
rhughes@241
   431
rhughes@241
   432
	trans = razor_transaction_create(set, upstream);
rhughes@241
   433
	if (argc == 0)
rhughes@241
   434
		razor_transaction_update_all(trans);
rhughes@241
   435
	for (i = 0; i < argc; i++) {
rhughes@241
   436
		if (mark_packages_for_update(trans, set, argv[i]) == 0) {
rhughes@241
   437
			fprintf(stderr, "no match for %s\n", argv[i]);
rhughes@241
   438
			return 1;
rhughes@241
   439
		}
rhughes@241
   440
	}
rhughes@241
   441
krh@252
   442
	razor_transaction_resolve(trans);
krh@252
   443
	errors = razor_transaction_describe(trans);
krh@252
   444
	if (errors) {
krh@252
   445
		fprintf(stderr, "unresolved dependencies\n");
rhughes@241
   446
		return 1;
krh@252
   447
	}
rhughes@241
   448
rhughes@241
   449
	set = razor_transaction_finish(trans);
rhughes@241
   450
	razor_set_write(set, updated_repo_filename);
rhughes@241
   451
	razor_set_destroy(set);
rhughes@241
   452
	razor_set_destroy(upstream);
rhughes@241
   453
	printf("wrote system-updated.repo\n");
rhughes@241
   454
rhughes@241
   455
	return 0;
rhughes@241
   456
}
rhughes@241
   457
rhughes@241
   458
static int
rhughes@241
   459
command_remove(int argc, const char *argv[])
rhughes@241
   460
{
rhughes@241
   461
	struct razor_set *set, *upstream;
rhughes@241
   462
	struct razor_transaction *trans;
rhughes@241
   463
	int i, errors;
rhughes@241
   464
rhughes@241
   465
	set = razor_set_open(repo_filename);
rhughes@241
   466
	if (set == NULL)
rhughes@241
   467
		return 1;
rhughes@241
   468
rhughes@241
   469
	upstream = razor_set_create();
rhughes@241
   470
	trans = razor_transaction_create(set, upstream);
rhughes@241
   471
	for (i = 0; i < argc; i++) {
rhughes@241
   472
		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
rhughes@241
   473
			fprintf(stderr, "no match for %s\n", argv[i]);
rhughes@241
   474
			return 1;
rhughes@241
   475
		}
rhughes@241
   476
	}
rhughes@241
   477
rhughes@241
   478
	errors = razor_transaction_resolve(trans);
rhughes@241
   479
	if (errors)
rhughes@241
   480
		return 1;
rhughes@241
   481
rhughes@241
   482
	set = razor_transaction_finish(trans);
rhughes@241
   483
	razor_set_write(set, updated_repo_filename);
rhughes@241
   484
	razor_set_destroy(set);
rhughes@241
   485
	razor_set_destroy(upstream);
rhughes@241
   486
	printf("wrote system-updated.repo\n");
rhughes@241
   487
rhughes@241
   488
	return 0;
rhughes@241
   489
}
rhughes@241
   490
rhughes@241
   491
static void
krh@253
   492
print_diff(enum razor_diff_action action,
krh@253
   493
	   struct razor_package *package,
krh@253
   494
	   const char *name,
krh@253
   495
	   const char *version,
krh@253
   496
	   const char *arch,
rhughes@241
   497
	   void *data)
rhughes@241
   498
{
krh@253
   499
	if (action == RAZOR_DIFF_ACTION_ADD)
krh@253
   500
		printf("install %s-%s.%s\n", name, version, arch);
krh@253
   501
	if (action == RAZOR_DIFF_ACTION_REMOVE)
krh@253
   502
		printf("remove %s-%s.%s\n", name, version, arch);
rhughes@241
   503
}
rhughes@241
   504
rhughes@241
   505
static int
rhughes@241
   506
command_diff(int argc, const char *argv[])
rhughes@241
   507
{
rhughes@241
   508
	struct razor_set *set, *updated;
rhughes@241
   509
rhughes@241
   510
	set = razor_set_open(repo_filename);
rhughes@241
   511
	updated = razor_set_open(updated_repo_filename);
rhughes@241
   512
	if (set == NULL || updated == NULL)
rhughes@241
   513
		return 1;
rhughes@241
   514
rhughes@241
   515
	razor_set_diff(set, updated, print_diff, NULL);
rhughes@241
   516
rhughes@241
   517
	razor_set_destroy(set);
rhughes@241
   518
	razor_set_destroy(updated);
rhughes@241
   519
rhughes@241
   520
	return 0;
rhughes@241
   521
}
rhughes@241
   522
rhughes@241
   523
static int
rhughes@241
   524
command_import_rpms(int argc, const char *argv[])
rhughes@241
   525
{
rhughes@241
   526
	DIR *dir;
rhughes@241
   527
	struct dirent *de;
rhughes@241
   528
	struct razor_importer *importer;
rhughes@241
   529
	struct razor_set *set;
rhughes@241
   530
	struct razor_rpm *rpm;
rhughes@241
   531
	int len;
rhughes@241
   532
	char filename[256];
rhughes@241
   533
	const char *dirname = argv[0];
rhughes@241
   534
rhughes@241
   535
	if (dirname == NULL) {
rhughes@241
   536
		fprintf(stderr, "usage: razor import-rpms DIR\n");
rhughes@241
   537
		return -1;
rhughes@241
   538
	}
rhughes@241
   539
rhughes@241
   540
	dir = opendir(dirname);
rhughes@241
   541
	if (dir == NULL) {
rhughes@241
   542
		fprintf(stderr, "couldn't read dir %s\n", dirname);
rhughes@241
   543
		return -1;
rhughes@241
   544
	}
rhughes@241
   545
krh@249
   546
	importer = razor_importer_create();
rhughes@241
   547
rhughes@241
   548
	while (de = readdir(dir), de != NULL) {
rhughes@241
   549
		len = strlen(de->d_name);
rhughes@241
   550
		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
rhughes@241
   551
		    continue;
rhughes@241
   552
		snprintf(filename, sizeof filename,
rhughes@241
   553
			 "%s/%s", dirname, de->d_name);
rhughes@241
   554
		rpm = razor_rpm_open(filename);
rhughes@241
   555
		if (rpm == NULL) {
rhughes@241
   556
			fprintf(stderr,
rhughes@241
   557
				"failed to open rpm \"%s\"\n", filename);
rhughes@241
   558
			continue;
rhughes@241
   559
		}
rhughes@241
   560
		if (razor_importer_add_rpm(importer, rpm)) {
rhughes@241
   561
			fprintf(stderr, "couldn't import %s\n", filename);
rhughes@241
   562
			break;
rhughes@241
   563
		}
rhughes@241
   564
		razor_rpm_close(rpm);
rhughes@241
   565
	}
rhughes@241
   566
rhughes@241
   567
	if (de != NULL) {
rhughes@241
   568
		razor_importer_destroy(importer);
rhughes@241
   569
		return -1;
rhughes@241
   570
	}
rhughes@241
   571
rhughes@241
   572
	set = razor_importer_finish(importer);
rhughes@241
   573
rhughes@241
   574
	razor_set_write(set, repo_filename);
rhughes@241
   575
	razor_set_destroy(set);
rhughes@241
   576
	printf("wrote %s\n", repo_filename);
rhughes@241
   577
rhughes@241
   578
	return 0;
rhughes@241
   579
}
rhughes@241
   580
krh@254
   581
static const char *
krh@254
   582
rpm_filename(const char *name, const char *version, const char *arch)
rhughes@241
   583
{
krh@254
   584
	static char file[PATH_MAX];
krh@254
   585
 	const char *v;
krh@254
   586
 
krh@254
   587
 	/* Skip epoch */
krh@253
   588
	v = strchr(version, ':');
krh@254
   589
 	if (v != NULL)
krh@254
   590
 		v = v + 1;
krh@254
   591
 	else
krh@253
   592
		v = version;
rhughes@241
   593
krh@254
   594
	snprintf(file, sizeof file, "%s-%s.%s.rpm", name, v, arch);
krh@254
   595
krh@254
   596
	return file;
rhughes@241
   597
}
rhughes@241
   598
krh@254
   599
static int
krh@254
   600
download_packages(struct razor_set *system, struct razor_set *next)
rhughes@241
   601
{
krh@254
   602
	struct razor_package_iterator *pi;
krh@254
   603
	struct razor_package *package;
krh@254
   604
	const char *name, *version, *arch;
krh@254
   605
	char file[PATH_MAX], url[256];
krh@254
   606
	int errors;
krh@254
   607
 
krh@254
   608
	pi = razor_set_create_install_iterator(system, next);
krh@254
   609
	errors = 0;
krh@254
   610
	while (razor_package_iterator_next(pi, &package,
krh@254
   611
					   &name, &version, &arch)) {
krh@254
   612
		snprintf(url, sizeof url,
krh@254
   613
			 "%s/Packages/%s",
krh@254
   614
			 yum_url, rpm_filename(name, version, arch));
krh@254
   615
		snprintf(file, sizeof file,
krh@254
   616
			 "rpms/%s", rpm_filename(name, version, arch));
krh@254
   617
		if (download_if_missing(url, file) < 0)
krh@254
   618
			errors++;
krh@254
   619
	}
krh@254
   620
	razor_package_iterator_destroy(pi);
krh@254
   621
krh@254
   622
	if (errors > 0) {
krh@254
   623
		fprintf(stderr, "failed to download %d packages\n", errors);
krh@254
   624
                return -1;
krh@254
   625
        }
krh@254
   626
krh@254
   627
	return 0;
krh@254
   628
}
krh@254
   629
krh@254
   630
static int
krh@254
   631
install_packages(struct razor_set *system, struct razor_set *next)
krh@254
   632
{
krh@254
   633
	struct razor_package_iterator *pi;
krh@254
   634
	struct razor_package *package;
krh@254
   635
	struct razor_rpm *rpm;
krh@254
   636
	const char *name, *version, *arch;
rhughes@241
   637
	char file[PATH_MAX];
rhughes@241
   638
krh@254
   639
	pi = razor_set_create_install_iterator(system, next);
krh@254
   640
	while (razor_package_iterator_next(pi, &package,
krh@254
   641
					   &name, &version, &arch)) {
krh@254
   642
		printf("install %s-%s\n", name, version);
krh@254
   643
krh@254
   644
		snprintf(file, sizeof file,
krh@254
   645
			 "rpms/%s", rpm_filename(name, version, arch));
krh@254
   646
		rpm = razor_rpm_open(file);
krh@254
   647
		if (rpm == NULL) {
krh@254
   648
			fprintf(stderr, "failed to open rpm %s\n", file);
krh@254
   649
			return -1;
krh@254
   650
		}
krh@254
   651
		if (razor_rpm_install(rpm, install_root) < 0) {
krh@254
   652
			fprintf(stderr,
krh@254
   653
				"failed to install rpm %s\n", file);
krh@254
   654
			return -1;
krh@254
   655
		}
krh@254
   656
		razor_rpm_close(rpm);
rhughes@241
   657
	}
krh@254
   658
	razor_package_iterator_destroy(pi);
rhughes@241
   659
krh@254
   660
	return 0;
rhughes@241
   661
}
rhughes@241
   662
rhughes@241
   663
static int
rhughes@241
   664
command_install(int argc, const char *argv[])
rhughes@241
   665
{
rhughes@241
   666
	struct razor_root *root;
krh@250
   667
	struct razor_set *system, *upstream, *next;
rhughes@241
   668
	struct razor_transaction *trans;
rhughes@241
   669
	int i = 0, errors, dependencies = 1;
rhughes@241
   670
rhughes@241
   671
	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
rhughes@241
   672
		dependencies = 0;
rhughes@241
   673
		i++;
rhughes@241
   674
	}
rhughes@241
   675
krh@250
   676
	root = razor_root_open(install_root);
krh@250
   677
	system = razor_root_get_system_set(root);
rhughes@241
   678
	upstream = razor_set_open(rawhide_repo_filename);
krh@250
   679
	trans = razor_transaction_create(system, upstream);
rhughes@241
   680
rhughes@241
   681
	for (; i < argc; i++) {
rhughes@241
   682
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
rhughes@241
   683
			fprintf(stderr, "no package matched %s\n", argv[i]);
rhughes@241
   684
			razor_root_close(root);
rhughes@241
   685
			return 1;
rhughes@241
   686
		}
rhughes@241
   687
	}
rhughes@241
   688
rhughes@241
   689
	if (dependencies) {
krh@245
   690
		razor_transaction_resolve(trans);
krh@245
   691
		if (razor_transaction_describe(trans) > 0) {
rhughes@241
   692
			razor_root_close(root);
rhughes@241
   693
			return 1;
rhughes@241
   694
		}
rhughes@241
   695
	}
rhughes@241
   696
rhughes@241
   697
	next = razor_transaction_finish(trans);
rhughes@241
   698
rhughes@241
   699
	razor_root_update(root, next);
rhughes@241
   700
rhughes@241
   701
	if (mkdir("rpms", 0777) && errno != EEXIST) {
rhughes@241
   702
		fprintf(stderr, "failed to create rpms directory.\n");
rhughes@241
   703
		razor_root_close(root);
rhughes@241
   704
		return 1;
rhughes@241
   705
	}
rhughes@241
   706
krh@254
   707
	if (download_packages(system, next) < 0) {
rhughes@241
   708
		razor_root_close(root);
rhughes@241
   709
                return 1;
rhughes@241
   710
        }
rhughes@241
   711
krh@254
   712
	install_packages(system, next);
rhughes@241
   713
rhughes@241
   714
	razor_set_destroy(next);
rhughes@241
   715
	razor_set_destroy(upstream);
rhughes@241
   716
rhughes@241
   717
	return razor_root_commit(root);
rhughes@241
   718
}
rhughes@241
   719
rhughes@241
   720
static int
rhughes@241
   721
command_init(int argc, const char *argv[])
rhughes@241
   722
{
rhughes@241
   723
	return razor_root_create(install_root);
rhughes@241
   724
}
rhughes@241
   725
rhughes@241
   726
static int
rhughes@241
   727
command_download(int argc, const char *argv[])
rhughes@241
   728
{
rhughes@241
   729
	struct razor_set *set;
rhughes@241
   730
	struct razor_package_iterator *pi;
rhughes@241
   731
	struct razor_package *package;
rhughes@241
   732
	const char *pattern = argv[0], *name, *version, *arch;
rhughes@241
   733
	char url[256], file[256];
rhughes@241
   734
	int matches = 0;
rhughes@241
   735
rhughes@241
   736
	if (mkdir("rpms", 0777) && errno != EEXIST) {
rhughes@241
   737
		fprintf(stderr, "failed to create rpms directory.\n");
rhughes@241
   738
		return 1;
rhughes@241
   739
	}
rhughes@241
   740
rhughes@241
   741
	set = razor_set_open(rawhide_repo_filename);
rhughes@241
   742
	pi = razor_package_iterator_create(set);
rhughes@241
   743
	while (razor_package_iterator_next(pi, &package,
rhughes@241
   744
					   &name, &version, &arch)) {
rhughes@241
   745
		if (pattern && fnmatch(pattern, name, 0) != 0)
rhughes@241
   746
			continue;
rhughes@241
   747
rhughes@241
   748
		matches++;
rhughes@241
   749
		snprintf(url, sizeof url,
rhughes@241
   750
			 "%s/Packages/%s-%s.%s.rpm",
rhughes@241
   751
			 yum_url, name, version, arch);
rhughes@241
   752
		snprintf(file, sizeof file,
rhughes@241
   753
			 "rpms/%s-%s.%s.rpm", name, version, arch);
rhughes@241
   754
		download_if_missing(url, file);
rhughes@241
   755
	}
rhughes@241
   756
	razor_package_iterator_destroy(pi);
rhughes@241
   757
	razor_set_destroy(set);
rhughes@241
   758
rhughes@241
   759
	if (matches == 0)
rhughes@241
   760
		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
rhughes@241
   761
	else if (matches == 1)
rhughes@241
   762
		fprintf(stderr, "downloaded 1 package\n");
rhughes@241
   763
	else
rhughes@241
   764
		fprintf(stderr, "downloaded %d packages\n", matches);
rhughes@241
   765
rhughes@241
   766
	return 0;
rhughes@241
   767
}
rhughes@241
   768
rhughes@241
   769
static struct {
rhughes@241
   770
	const char *name;
rhughes@241
   771
	const char *description;
rhughes@241
   772
	int (*func)(int argc, const char *argv[]);
rhughes@241
   773
} razor_commands[] = {
rhughes@241
   774
	{ "list", "list all packages", command_list },
rhughes@241
   775
	{ "list-requires", "list all requires for the given package", command_list_requires },
rhughes@241
   776
	{ "list-provides", "list all provides for the given package", command_list_provides },
rhughes@241
   777
	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
rhughes@241
   778
	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
rhughes@241
   779
	{ "list-files", "list files for package set", command_list_files },
rhughes@241
   780
	{ "list-file-packages", "list packages owning file", command_list_file_packages },
rhughes@241
   781
	{ "list-package-files", "list files in package", command_list_package_files },
rhughes@241
   782
	{ "what-requires", "list the packages that have the given requires", command_what_requires },
rhughes@241
   783
	{ "what-provides", "list the packages that have the given provides", command_what_provides },
rhughes@241
   784
	{ "import-yum", "import yum metadata files", command_import_yum },
rhughes@241
   785
	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
rhughes@241
   786
	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
rhughes@241
   787
	{ "update", "update all or specified packages", command_update },
rhughes@241
   788
	{ "remove", "remove specified packages", command_remove },
rhughes@241
   789
	{ "diff", "show diff between two package sets", command_diff },
rhughes@241
   790
	{ "install", "install rpm", command_install },
rhughes@241
   791
	{ "init", "init razor root", command_init },
rhughes@241
   792
	{ "download", "download packages", command_download }
rhughes@241
   793
};
rhughes@241
   794
rhughes@241
   795
static int
rhughes@241
   796
usage(void)
rhughes@241
   797
{
rhughes@241
   798
	int i;
rhughes@241
   799
rhughes@241
   800
	printf("usage:\n");
rhughes@241
   801
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
rhughes@241
   802
		printf("  %-20s%s\n",
rhughes@241
   803
		       razor_commands[i].name, razor_commands[i].description);
rhughes@241
   804
rhughes@241
   805
	return 1;
rhughes@241
   806
}
rhughes@241
   807
rhughes@241
   808
int
rhughes@241
   809
main(int argc, const char *argv[])
rhughes@241
   810
{
rhughes@241
   811
	char *repo;
rhughes@241
   812
	int i;
rhughes@241
   813
rhughes@241
   814
	repo = getenv("RAZOR_REPO");
rhughes@241
   815
	if (repo != NULL)
rhughes@241
   816
		repo_filename = repo;
rhughes@241
   817
rhughes@241
   818
	yum_url = getenv("YUM_URL");
rhughes@241
   819
	if (yum_url == NULL)
rhughes@241
   820
		yum_url = YUM_URL;
rhughes@241
   821
rhughes@241
   822
	if (argc < 2)
rhughes@241
   823
		return usage();
rhughes@241
   824
rhughes@241
   825
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
rhughes@241
   826
		if (strcmp(razor_commands[i].name, argv[1]) == 0)
rhughes@241
   827
			return razor_commands[i].func(argc - 2, argv + 2);
rhughes@241
   828
rhughes@241
   829
	return usage();
rhughes@241
   830
}