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 <SupportDefs.h>
13
14#include <package/AddRepositoryRequest.h>
15#include <package/Context.h>
16#include <package/RefreshRepositoryRequest.h>
17#include <package/PackageRoster.h>
18
19#include "DecisionProvider.h"
20#include "JobStateListener.h"
21#include "pkgman.h"
22
23
24using namespace BPackageKit;
25
26
27// TODO: internationalization!
28
29
30static const char* kCommandUsage =
31	"Usage: %s add-repo <repo-URL> [<repo-URL> ...]\n"
32	"Adds one or more repositories by downloading them from the given URL(s).\n"
33	"\n"
34;
35
36
37static void
38print_command_usage_and_exit(bool error)
39{
40    fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
41    exit(error ? 1 : 0);
42}
43
44
45int
46command_add_repo(int argc, const char* const* argv)
47{
48	bool asUserRepository = false;
49
50	while (true) {
51		static struct option sLongOptions[] = {
52			{ "help", no_argument, 0, 'h' },
53			{ "user", no_argument, 0, 'u' },
54			{ 0, 0, 0, 0 }
55		};
56
57		opterr = 0; // don't print errors
58		int c = getopt_long(argc, (char**)argv, "hu", sLongOptions, NULL);
59		if (c == -1)
60			break;
61
62		switch (c) {
63			case 'h':
64				print_command_usage_and_exit(false);
65				break;
66
67			case 'u':
68				asUserRepository = true;
69				break;
70
71			default:
72				print_command_usage_and_exit(true);
73				break;
74		}
75	}
76
77	// The remaining arguments are repo URLs, i. e. at least one more argument.
78	if (argc < optind + 1)
79		print_command_usage_and_exit(true);
80
81	const char* const* repoURLs = argv + optind;
82	int urlCount = argc - optind;
83
84	DecisionProvider decisionProvider;
85	JobStateListener listener;
86	BContext context(decisionProvider, listener);
87
88	status_t result;
89	for (int i = 0; i < urlCount; ++i) {
90		AddRepositoryRequest addRequest(context, repoURLs[i], asUserRepository);
91		result = addRequest.InitCheck();
92		if (result != B_OK)
93			DIE(result, "unable to create request for adding repository");
94		result = addRequest.CreateInitialJobs();
95		if (result != B_OK)
96			DIE(result, "unable to create necessary jobs");
97
98		while (BJob* job = addRequest.PopRunnableJob()) {
99			result = job->Run();
100			delete job;
101			if (result == B_CANCELED)
102				return 1;
103		}
104
105		// now refresh the repo-cache of the new repository
106		BString repoName = addRequest.RepositoryName();
107		BPackageRoster roster;
108		BRepositoryConfig repoConfig;
109		roster.GetRepositoryConfig(repoName, &repoConfig);
110		BRefreshRepositoryRequest refreshRequest(context, repoConfig);
111		result = refreshRequest.InitCheck();
112		if (result != B_OK)
113			DIE(result, "unable to create request for refreshing repository");
114		result = refreshRequest.CreateInitialJobs();
115		if (result != B_OK)
116			DIE(result, "unable to create necessary jobs");
117
118		while (BJob* job = refreshRequest.PopRunnableJob()) {
119			result = job->Run();
120			delete job;
121			if (result == B_CANCELED)
122				return 1;
123		}
124	}
125
126	return 0;
127}
128