1/*
2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefere.de>
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <getopt.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11#include <Errors.h>
12#include <StringList.h>
13
14#include <package/Context.h>
15#include <package/RefreshRepositoryRequest.h>
16#include <package/PackageRoster.h>
17
18#include "DecisionProvider.h"
19#include "JobStateListener.h"
20#include "pkgman.h"
21
22
23using namespace BPackageKit;
24
25
26// TODO: internationalization!
27
28
29static const char* kCommandUsage =
30	"Usage: %s refresh [<repo-name> ...]\n"
31	"Refreshes all or just the given repositories.\n"
32	"\n"
33;
34
35
36static void
37print_command_usage_and_exit(bool error)
38{
39    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
40    exit(error ? 1 : 0);
41}
42
43
44int
45command_refresh(int argc, const char* const* argv)
46{
47	while (true) {
48		static struct option sLongOptions[] = {
49			{ "help", no_argument, 0, 'h' },
50			{ 0, 0, 0, 0 }
51		};
52
53		opterr = 0; // don't print errors
54		int c = getopt_long(argc, (char**)argv, "hu", sLongOptions, NULL);
55		if (c == -1)
56			break;
57
58		switch (c) {
59			case 'h':
60				print_command_usage_and_exit(false);
61				break;
62
63			default:
64				print_command_usage_and_exit(true);
65				break;
66		}
67	}
68
69	// The remaining arguments are repo names.
70	const char* const* repoArgs = argv + optind;
71	int nameCount = argc - optind;
72
73	DecisionProvider decisionProvider;
74	JobStateListener listener;
75	BContext context(decisionProvider, listener);
76
77	BStringList repositoryNames(20);
78
79	BPackageRoster roster;
80	if (nameCount == 0) {
81		status_t result = roster.GetRepositoryNames(repositoryNames);
82		if (result != B_OK)
83			DIE(result, "can't collect repository names");
84	} else {
85		for (int i = 0; i < nameCount; ++i) {
86			if (!repositoryNames.Add(repoArgs[i]))
87				DIE(B_NO_MEMORY, "can't allocate repository name");
88		}
89	}
90
91	status_t result;
92	for (int i = 0; i < repositoryNames.CountStrings(); ++i) {
93		const BString& repoName = repositoryNames.StringAt(i);
94		BRepositoryConfig repoConfig;
95		result = roster.GetRepositoryConfig(repoName, &repoConfig);
96		if (result != B_OK) {
97			BPath path;
98			repoConfig.Entry().GetPath(&path);
99			WARN(result, "skipping repository-config '%s'", path.Path());
100			continue;
101		}
102		BRefreshRepositoryRequest refreshRequest(context, repoConfig);
103		result = refreshRequest.InitCheck();
104		if (result != B_OK)
105			DIE(result, "unable to create request for refreshing repository");
106		result = refreshRequest.CreateInitialJobs();
107		if (result != B_OK)
108			DIE(result, "unable to create necessary jobs");
109
110		while (BJob* job = refreshRequest.PopRunnableJob()) {
111			result = job->Run();
112			delete job;
113			if (result != B_OK)
114				return 1;
115		}
116	}
117
118	return 0;
119}
120