]>
Commit | Line | Data |
---|---|---|
5229b03c LP |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include "analyze.h" | |
4 | #include "analyze-calendar.h" | |
5 | #include "calendarspec.h" | |
6 | #include "format-table.h" | |
7 | #include "terminal-util.h" | |
8 | ||
9 | static int test_calendar_one(usec_t n, const char *p) { | |
10 | _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL; | |
11 | _cleanup_(table_unrefp) Table *table = NULL; | |
12 | _cleanup_free_ char *t = NULL; | |
13 | TableCell *cell; | |
14 | int r; | |
15 | ||
16 | r = calendar_spec_from_string(p, &spec); | |
17 | if (r < 0) { | |
18 | log_error_errno(r, "Failed to parse calendar specification '%s': %m", p); | |
19 | time_parsing_hint(p, /* calendar= */ false, /* timestamp= */ true, /* timespan= */ true); | |
20 | return r; | |
21 | } | |
22 | ||
23 | r = calendar_spec_to_string(spec, &t); | |
24 | if (r < 0) | |
25 | return log_error_errno(r, "Failed to format calendar specification '%s': %m", p); | |
26 | ||
27 | table = table_new("name", "value"); | |
28 | if (!table) | |
29 | return log_oom(); | |
30 | ||
31 | table_set_header(table, false); | |
32 | ||
33 | assert_se(cell = table_get_cell(table, 0, 0)); | |
34 | r = table_set_ellipsize_percent(table, cell, 100); | |
35 | if (r < 0) | |
36 | return r; | |
37 | ||
38 | r = table_set_align_percent(table, cell, 100); | |
39 | if (r < 0) | |
40 | return r; | |
41 | ||
42 | assert_se(cell = table_get_cell(table, 0, 1)); | |
43 | r = table_set_ellipsize_percent(table, cell, 100); | |
44 | if (r < 0) | |
45 | return r; | |
46 | ||
47 | if (!streq(t, p)) { | |
48 | r = table_add_many(table, | |
49 | TABLE_STRING, "Original form:", | |
50 | TABLE_STRING, p); | |
51 | if (r < 0) | |
52 | return table_log_add_error(r); | |
53 | } | |
54 | ||
55 | r = table_add_many(table, | |
56 | TABLE_STRING, "Normalized form:", | |
57 | TABLE_STRING, t); | |
58 | if (r < 0) | |
59 | return table_log_add_error(r); | |
60 | ||
61 | for (unsigned i = 0; i < arg_iterations; i++) { | |
62 | usec_t next; | |
63 | ||
64 | r = calendar_spec_next_usec(spec, n, &next); | |
65 | if (r == -ENOENT) { | |
66 | if (i == 0) { | |
67 | r = table_add_many(table, | |
68 | TABLE_STRING, "Next elapse:", | |
69 | TABLE_STRING, "never", | |
70 | TABLE_SET_COLOR, ansi_highlight_yellow()); | |
71 | if (r < 0) | |
72 | return table_log_add_error(r); | |
73 | } | |
74 | break; | |
75 | } | |
76 | if (r < 0) | |
77 | return log_error_errno(r, "Failed to determine next elapse for '%s': %m", p); | |
78 | ||
79 | if (i == 0) { | |
80 | r = table_add_many(table, | |
81 | TABLE_STRING, "Next elapse:", | |
82 | TABLE_TIMESTAMP, next, | |
83 | TABLE_SET_COLOR, ansi_highlight_blue()); | |
84 | if (r < 0) | |
85 | return table_log_add_error(r); | |
86 | } else { | |
87 | int k = DECIMAL_STR_WIDTH(i + 1); | |
88 | ||
89 | if (k < 8) | |
90 | k = 8 - k; | |
91 | else | |
92 | k = 0; | |
93 | ||
94 | r = table_add_cell_stringf(table, NULL, "Iter. #%u:", i+1); | |
95 | if (r < 0) | |
96 | return table_log_add_error(r); | |
97 | ||
98 | r = table_add_many(table, | |
99 | TABLE_TIMESTAMP, next, | |
100 | TABLE_SET_COLOR, ansi_highlight_blue()); | |
101 | if (r < 0) | |
102 | return table_log_add_error(r); | |
103 | } | |
104 | ||
105 | if (!in_utc_timezone()) { | |
106 | r = table_add_many(table, | |
107 | TABLE_STRING, "(in UTC):", | |
108 | TABLE_TIMESTAMP_UTC, next); | |
109 | if (r < 0) | |
110 | return table_log_add_error(r); | |
111 | } | |
112 | ||
113 | r = table_add_many(table, | |
114 | TABLE_STRING, "From now:", | |
115 | TABLE_TIMESTAMP_RELATIVE, next); | |
116 | if (r < 0) | |
117 | return table_log_add_error(r); | |
118 | ||
119 | n = next; | |
120 | } | |
121 | ||
122 | return table_print(table, NULL); | |
123 | } | |
124 | ||
125 | int test_calendar(int argc, char *argv[], void *userdata) { | |
126 | int ret = 0, r; | |
127 | char **p; | |
128 | usec_t n; | |
129 | ||
130 | if (arg_base_time != USEC_INFINITY) | |
131 | n = arg_base_time; | |
132 | else | |
133 | n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */ | |
134 | ||
135 | STRV_FOREACH(p, strv_skip(argv, 1)) { | |
136 | r = test_calendar_one(n, *p); | |
137 | if (ret == 0 && r < 0) | |
138 | ret = r; | |
139 | ||
140 | if (*(p + 1)) | |
141 | putchar('\n'); | |
142 | } | |
143 | ||
144 | return ret; | |
145 | } |