1/*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <getopt.h>
8#include <stdio.h>
9#include <string.h>
10
11#include <Entry.h>
12#include <package/PackageInfo.h>
13
14#include "package.h"
15
16
17using namespace BPackageKit;
18
19
20int
21command_info(int argc, const char* const* argv)
22{
23	const char* format = "name: %name%  version: %version%\n";
24
25	while (true) {
26		static struct option sLongOptions[] = {
27			{ "format", required_argument, 0, 'f' },
28			{ "help", no_argument, 0, 'h' },
29			{ 0, 0, 0, 0 }
30		};
31
32		opterr = 0; // don't print errors
33		int c = getopt_long(argc, (char**)argv, "f:h", sLongOptions, NULL);
34		if (c == -1)
35			break;
36
37		switch (c) {
38			case 'f':
39				format = optarg;
40				break;
41
42			default:
43				print_usage_and_exit(true);
44				break;
45		}
46	}
47
48	// One argument should remain -- the package file name.
49	if (optind + 1 != argc)
50		print_usage_and_exit(true);
51
52	const char* fileName = argv[optind++];
53
54	// Read the package info from the package file. If it doesn't look like a
55	// package file, assume it is a package info file.
56	BPackageInfo info;
57	if (BString(fileName).EndsWith(".hpkg")) {
58		status_t error = info.ReadFromPackageFile(fileName);
59		if (error != B_OK) {
60			fprintf(stderr, "Error: Failed to read package file \"%s\": %s\n",
61				fileName, strerror(error));
62			return 1;
63		}
64	} else {
65		status_t error = info.ReadFromConfigFile(BEntry(fileName));
66		if (error != B_OK) {
67			fprintf(stderr, "Error: Failed to read package info file \"%s\": "
68				"%s\n", fileName, strerror(error));
69			return 1;
70		}
71	}
72
73	// parse format string and produce output
74	BString output;
75	while (*format != '\0') {
76		char c = *format++;
77		switch (c) {
78			case '%':
79			{
80				const char* start = format;
81				while (*format != '\0' && *format != '%')
82					format++;
83				if (*format != '%') {
84					fprintf(stderr, "Error: Unexpected at end of the format "
85						"string. Expected \"%%\".\n");
86					return 1;
87				}
88
89				if (format == start) {
90					output << '%';
91				} else {
92					BString variable(start, format - start);
93					if (variable == "fileName") {
94						output << info.CanonicalFileName();
95					} else if (variable == "name") {
96						output << info.Name();
97					} else if (variable == "version") {
98						output << info.Version().ToString();
99					} else {
100						fprintf(stderr, "Error: Unsupported placeholder \"%s\" "
101							"in format string.\n", variable.String());
102						return 1;
103					}
104				}
105
106				format++;
107				break;
108			}
109
110			case '\\':
111				c = *format++;
112				if (c == '\0') {
113					fprintf(stderr, "Error: \"\\\" at the end of the format "
114						"string.\n");
115					return 1;
116				}
117				switch (c) {
118					case 'n':
119						c = '\n';
120						break;
121					case 't':
122						c = '\t';
123						break;
124				}
125				// fall through
126
127			default:
128				output << c;
129				break;
130		}
131	}
132
133	fputs(output.String(), stdout);
134
135	return 0;
136}
137