xref: /haiku/src/bin/pkgman/command_refresh.cpp (revision cbed190f71b8aff814bf95539c39a1bcfb953ed8)
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/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 
23 using namespace BPackageKit;
24 
25 
26 // TODO: internationalization!
27 
28 
29 static const char* kCommandUsage =
30 	"Usage: %s refresh [<repo-name> ...]\n"
31 	"Refreshes all or just the given repositories.\n"
32 	"\n"
33 ;
34 
35 
36 static void
37 print_command_usage_and_exit(bool error)
38 {
39     fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
40     exit(error ? 1 : 0);
41 }
42 
43 
44 int
45 command_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 	BObjectList<BString> repositoryNames(20, true);
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 			BString* repoName = new (std::nothrow) BString(repoArgs[i]);
87 			if (repoName == NULL)
88 				DIE(B_NO_MEMORY, "can't allocate repository name");
89 			repositoryNames.AddItem(repoName);
90 		}
91 	}
92 
93 	status_t result;
94 	for (int i = 0; i < repositoryNames.CountItems(); ++i) {
95 		const BString& repoName = *(repositoryNames.ItemAt(i));
96 		BRepositoryConfig repoConfig;
97 		result = roster.GetRepositoryConfig(repoName, &repoConfig);
98 		if (result != B_OK) {
99 			BPath path;
100 			repoConfig.Entry().GetPath(&path);
101 			WARN(result, "skipping repository-config '%s'", path.Path());
102 			continue;
103 		}
104 		BRefreshRepositoryRequest refreshRequest(context, repoConfig);
105 		result = refreshRequest.InitCheck();
106 		if (result != B_OK)
107 			DIE(result, "unable to create request for refreshing repository");
108 		result = refreshRequest.CreateInitialJobs();
109 		if (result != B_OK)
110 			DIE(result, "unable to create necessary jobs");
111 
112 		while (BJob* job = refreshRequest.PopRunnableJob()) {
113 			result = job->Run();
114 			delete job;
115 			if (result != B_OK)
116 				return 1;
117 		}
118 	}
119 
120 	return 0;
121 }
122