| 55 |
55 |
|
//! it would answer "where do I set this" with silence, and offering it would
|
| 56 |
56 |
|
//! promise a command that is not there.
|
| 57 |
57 |
|
//!
|
|
58 |
+ |
//! A vocabulary of one closes the row on the same grounds. The single entry is
|
|
59 |
+ |
//! whatever is already in force, so there is nothing to pick between, and the
|
|
60 |
+ |
//! row would be offering a change it cannot make. The shipped image reaches
|
|
61 |
+ |
//! this through the locale row: it carries no langpacks, so `localectl` has one
|
|
62 |
+ |
//! locale to list. The theme row has always read it this way, since a search
|
|
63 |
+ |
//! path that found no themes still leaves `system` behind.
|
|
64 |
+ |
//!
|
| 58 |
65 |
|
//! See wiki note `alloy-privilege`.
|
| 59 |
66 |
|
//!
|
| 60 |
67 |
|
//! <!-- wiki: alloy-settings -->
|
| 199 |
206 |
|
let quiet = !self.host.answered;
|
| 200 |
207 |
|
set(self.field_mut(HOSTNAME), ¬e, quiet);
|
| 201 |
208 |
|
|
|
209 |
+ |
// One locale installed is not a vocabulary, it is the locale already in
|
|
210 |
+ |
// force, and a row offering only what is already set promises a change
|
|
211 |
+ |
// it cannot make. The shipped image is exactly that case: it carries
|
|
212 |
+ |
// `glibc-minimal-langpack` and no langpacks, so `/usr/lib/locale` holds
|
|
213 |
+ |
// `C.utf8` alone and `localectl` has one entry to report. So the row
|
|
214 |
+ |
// names the installed locale and what would add another, rather than
|
|
215 |
+ |
// saying "unavailable" and leaving the cause to be guessed at.
|
|
216 |
+ |
//
|
|
217 |
+ |
// Gating on the count rather than on a langpack probe is what makes it
|
|
218 |
+ |
// reopen by itself: install a langpack and the row is settable with no
|
|
219 |
+ |
// change here. `localectl` reads the archive and `/usr/lib/locale`, so
|
|
220 |
+ |
// it is already reporting what is present rather than what glibc knows.
|
|
221 |
+ |
let installed = self.choices(LOCALE);
|
| 202 |
222 |
|
let (note, closed) = if !self.locale.answered {
|
| 203 |
|
- |
("localectl did not answer.", true)
|
| 204 |
|
- |
} else if self.choices(LOCALE).is_empty() {
|
| 205 |
|
- |
("This machine lists no locales.", true)
|
|
223 |
+ |
("localectl did not answer.".to_string(), true)
|
|
224 |
+ |
} else if installed.is_empty() {
|
|
225 |
+ |
("This machine lists no locales.".to_string(), true)
|
|
226 |
+ |
} else if let [only] = installed {
|
|
227 |
+ |
(
|
|
228 |
+ |
format!(
|
|
229 |
+ |
"Only {} is installed here. Adding a langpack adds a choice.",
|
|
230 |
+ |
only.value
|
|
231 |
+ |
),
|
|
232 |
+ |
true,
|
|
233 |
+ |
)
|
| 206 |
234 |
|
} else {
|
| 207 |
|
- |
("System locale. Applies to new sessions.", false)
|
|
235 |
+ |
("System locale. Applies to new sessions.".to_string(), false)
|
| 208 |
236 |
|
};
|
| 209 |
|
- |
set(self.field_mut(LOCALE), note, closed);
|
|
237 |
+ |
set(self.field_mut(LOCALE), ¬e, closed);
|
| 210 |
238 |
|
|
| 211 |
239 |
|
let (note, closed) = if !self.locale.answered {
|
| 212 |
240 |
|
("localectl did not answer.", true)
|
| 819 |
847 |
|
sections: sections(),
|
| 820 |
848 |
|
fields: rows(
|
| 821 |
849 |
|
Vec::new(),
|
| 822 |
|
- |
parse_list("en_US.UTF-8\n"),
|
|
850 |
+ |
parse_list("en_US.UTF-8\nen_GB.UTF-8\n"),
|
| 823 |
851 |
|
Vec::new(),
|
| 824 |
852 |
|
theme_choices(),
|
| 825 |
853 |
|
),
|
| 837 |
865 |
|
);
|
| 838 |
866 |
|
}
|
| 839 |
867 |
|
|
|
868 |
+ |
/// Build a bind whose locale vocabulary is exactly `locales`.
|
|
869 |
+ |
fn with_locales(locales: &str) -> SystemBind {
|
|
870 |
+ |
let mut bind = SystemBind {
|
|
871 |
+ |
sections: sections(),
|
|
872 |
+ |
fields: rows(
|
|
873 |
+ |
Vec::new(),
|
|
874 |
+ |
parse_list(locales),
|
|
875 |
+ |
parse_list("us\n"),
|
|
876 |
+ |
theme_choices(),
|
|
877 |
+ |
),
|
|
878 |
+ |
time: parse_show(SHOW),
|
|
879 |
+ |
host: parse_host(HOST),
|
|
880 |
+ |
locale: parse_locale(LOCALE_STATUS),
|
|
881 |
+ |
};
|
|
882 |
+ |
bind.annotate();
|
|
883 |
+ |
bind
|
|
884 |
+ |
}
|
|
885 |
+ |
|
|
886 |
+ |
// The shipped image's real state: `glibc-minimal-langpack` and no
|
|
887 |
+ |
// langpacks, so `/usr/lib/locale` holds `C.utf8` alone and `localectl` has
|
|
888 |
+ |
// one locale to report. The row is shown, closed, and names the locale that
|
|
889 |
+ |
// is installed rather than reporting a bare absence.
|
|
890 |
+ |
#[test]
|
|
891 |
+ |
fn one_installed_locale_closes_the_row_and_says_which() {
|
|
892 |
+ |
let mut bind = with_locales("C.UTF-8\n");
|
|
893 |
+ |
|
|
894 |
+ |
assert!(bind.field(LOCALE).unwrap().readonly);
|
|
895 |
+ |
assert!(
|
|
896 |
+ |
help(&bind, LOCALE).contains("Only C.UTF-8 is installed here"),
|
|
897 |
+ |
"{}",
|
|
898 |
+ |
help(&bind, LOCALE),
|
|
899 |
+ |
);
|
|
900 |
+ |
assert!(
|
|
901 |
+ |
bind.commit(LOCALE, Value::String("C.UTF-8".into()))
|
|
902 |
+ |
.is_err(),
|
|
903 |
+ |
"a closed row takes no write"
|
|
904 |
+ |
);
|
|
905 |
+ |
}
|
|
906 |
+ |
|
|
907 |
+ |
// The half that matters for the next reader: the gate is the count, not a
|
|
908 |
+ |
// langpack probe, so installing a langpack reopens the row on its own and
|
|
909 |
+ |
// nothing here needs revisiting.
|
|
910 |
+ |
#[test]
|
|
911 |
+ |
fn a_second_langpack_reopens_the_locale_row() {
|
|
912 |
+ |
let bind = with_locales("C.UTF-8\nen_US.UTF-8\n");
|
|
913 |
+ |
|
|
914 |
+ |
assert!(!bind.field(LOCALE).unwrap().readonly);
|
|
915 |
+ |
assert!(
|
|
916 |
+ |
help(&bind, LOCALE).contains("Applies to new sessions"),
|
|
917 |
+ |
"{}",
|
|
918 |
+ |
help(&bind, LOCALE),
|
|
919 |
+ |
);
|
|
920 |
+ |
}
|
|
921 |
+ |
|
| 840 |
922 |
|
// A machine that has never had /etc/hostname still shows the name it
|
| 841 |
923 |
|
// answers to, and the help line says what setting it would do.
|
| 842 |
924 |
|
#[test]
|