xref: /haiku/src/bin/pkgman/command_add_repo.cpp (revision 323b65468e5836bb27a5e373b14027d902349437)
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 
24 using namespace BPackageKit;
25 
26 
27 // TODO: internationalization!
28 
29 
30 static 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 
37 static void
38 print_command_usage_and_exit(bool error)
39 {
40     fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
41     exit(error ? 1 : 0);
42 }
43 
44 
45 int
46 command_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