Merge lp:~townsend/libertine/locale-and-language into lp:libertine
- locale-and-language
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Larry Price |
Approved revision: | 373 |
Merged at revision: | 372 |
Proposed branch: | lp:~townsend/libertine/locale-and-language |
Merge into: | lp:libertine |
Diff against target: |
361 lines (+109/-20) 8 files modified
python/libertine/ChrootContainer.py (+6/-2) python/libertine/ContainersConfig.py (+6/-0) python/libertine/HostInfo.py (+12/-0) python/libertine/Libertine.py (+55/-10) python/libertine/LxcContainer.py (+6/-2) python/libertine/LxdContainer.py (+6/-2) tools/libertine-container-manager (+17/-3) tools/libertine-container-manager.1 (+1/-1) |
To merge this branch: | bzr merge lp:~townsend/libertine/locale-and-language |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Larry Price | Approve | ||
Libertine CI Bot | continuous-integration | Approve | |
Review via email: mp+314652@code.launchpad.net |
Commit message
Set container's locale and language based on the host including installing necessary language packs.
Description of the change
Some notes about how this works:
- Locale will be set and necessary language packs installed during container creation to match what the host is set to.
- After a package installed, it will check for any supporting language packs to install based on what the current locale is set *in the container*.
- If a user changes their locale after a container has been created, the only way to update the container is to run 'l-c-m update' on the container.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:370
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 371. By Christopher Townsend
-
Fix mock tests.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:371
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Larry Price (larryprice) wrote : | # |
see inlines
Larry Price (larryprice) : | # |
- 372. By Christopher Townsend
-
Some changes based on review.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:372
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 373. By Christopher Townsend
-
Forgot to add a paramater for ChrootContainer
::update_ packages( )
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:373
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Larry Price (larryprice) wrote : | # |
lgtm - this has the potential to make a lot of users very happy
Preview Diff
1 | === modified file 'python/libertine/ChrootContainer.py' |
2 | --- python/libertine/ChrootContainer.py 2017-01-11 19:35:27 +0000 |
3 | +++ python/libertine/ChrootContainer.py 2017-01-13 18:36:04 +0000 |
4 | @@ -120,6 +120,8 @@ |
5 | |
6 | utils.create_libertine_user_data_dir(self.container_id) |
7 | |
8 | + self.update_locale() |
9 | + |
10 | if multiarch and self.architecture == 'amd64': |
11 | utils.get_logger().info("Adding i386 multiarch support...") |
12 | self.run_in_container("dpkg --add-architecture i386") |
13 | @@ -146,10 +148,12 @@ |
14 | # Check if the container was created as root and chown the user directories as necessary |
15 | chown_recursive_dirs(utils.get_libertine_container_userdata_dir_path(self.container_id)) |
16 | |
17 | + super().create_libertine_container() |
18 | + |
19 | return True |
20 | |
21 | - def update_packages(self): |
22 | - retcode = super().update_packages() |
23 | + def update_packages(self, new_locale=None): |
24 | + retcode = super().update_packages(new_locale) |
25 | self._run_ldconfig() |
26 | return retcode == 0 |
27 | |
28 | |
29 | === modified file 'python/libertine/ContainersConfig.py' |
30 | --- python/libertine/ContainersConfig.py 2016-12-07 21:50:36 +0000 |
31 | +++ python/libertine/ContainersConfig.py 2017-01-13 18:36:04 +0000 |
32 | @@ -296,6 +296,12 @@ |
33 | else: |
34 | return multiarch_support |
35 | |
36 | + def update_container_locale(self, container_id, locale): |
37 | + self._set_value_by_key(container_id, 'locale', locale) |
38 | + |
39 | + def get_container_locale(self, container_id): |
40 | + return self._get_value_by_key(container_id, 'locale') |
41 | + |
42 | """ |
43 | Operations for archive (PPA) maintenance in a Libertine container. |
44 | """ |
45 | |
46 | === modified file 'python/libertine/HostInfo.py' |
47 | --- python/libertine/HostInfo.py 2016-11-21 17:18:55 +0000 |
48 | +++ python/libertine/HostInfo.py 2017-01-13 18:36:04 +0000 |
49 | @@ -12,6 +12,7 @@ |
50 | # You should have received a copy of the GNU General Public License along |
51 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
52 | |
53 | +import locale |
54 | import lsb_release |
55 | import os |
56 | import platform |
57 | @@ -74,3 +75,14 @@ |
58 | def get_host_timezone(self): |
59 | with open(os.path.join('/', 'etc', 'timezone'), 'r') as fd: |
60 | return fd.read().strip('\n') |
61 | + |
62 | + def get_host_locale(self): |
63 | + host_locale = locale.getlocale() |
64 | + full_locale = None |
65 | + |
66 | + if len(host_locale) == 2: |
67 | + full_locale = "{}.{}".format(host_locale[0], host_locale[1]) |
68 | + elif len(host_locale) == 1: |
69 | + full_locale = "{}".format(host_locale[0]) |
70 | + |
71 | + return full_locale |
72 | |
73 | === modified file 'python/libertine/Libertine.py' |
74 | --- python/libertine/Libertine.py 2017-01-03 17:51:30 +0000 |
75 | +++ python/libertine/Libertine.py 2017-01-13 18:36:04 +0000 |
76 | @@ -82,10 +82,15 @@ |
77 | |
78 | :param container_id: The machine-readable container name. |
79 | """ |
80 | - def __init__(self, container_id): |
81 | + def __init__(self, container_id, containers_config=None): |
82 | + if containers_config is None: |
83 | + containers_config = ContainersConfig() |
84 | + |
85 | self.container_type = 'unknown' |
86 | self.container_id = container_id |
87 | self.root_path = libertine.utils.get_libertine_container_rootfs_path(self.container_id) |
88 | + self.locale = containers_config.get_container_locale(container_id) |
89 | + self.language = self._get_language_from_locale() |
90 | self.default_packages = ['matchbox-window-manager', |
91 | 'libnss-extrausers', |
92 | 'humanity-icon-theme', |
93 | @@ -93,8 +98,37 @@ |
94 | 'maliit-inputcontext-gtk3', |
95 | 'maliit-framework'] |
96 | |
97 | + def _get_language_from_locale(self): |
98 | + language = None |
99 | + |
100 | + if self.locale is not None: |
101 | + language = self.locale.split('.')[0] |
102 | + if not language.startswith('zh_'): |
103 | + language = language.split('_')[0] |
104 | + elif language.startswith('zh_CN'): |
105 | + language = 'zh-hans' |
106 | + else: |
107 | + language = 'zh-hant' |
108 | + |
109 | + return language |
110 | + |
111 | + def check_language_support(self): |
112 | + if self.run_in_container("bash -c \"which check-language-support &> /dev/null\"") != 0: |
113 | + self.install_package('language-selector-common', update_cache=False) |
114 | + |
115 | + self.run_in_container("bash -c \"{} install $(check-language-support -l {})\"".format(_apt_command_prefix(), self.language)) |
116 | + |
117 | + def update_locale(self): |
118 | + self.run_in_container("locale-gen {}".format(self.locale)) |
119 | + |
120 | + def install_base_language_packs(self): |
121 | + base_language_packs = ['language-pack-{}', 'language-pack-gnome-{}'] |
122 | + |
123 | + for language_pack in [p.format(self.language) for p in base_language_packs]: |
124 | + self.install_package(language_pack, update_cache=False) |
125 | + |
126 | def create_libertine_container(self, password=None, multiarch=False): |
127 | - pass |
128 | + self.install_base_language_packs() |
129 | |
130 | def destroy_libertine_container(self): |
131 | pass |
132 | @@ -150,11 +184,18 @@ |
133 | """ |
134 | return self.run_in_container(_apt_command_prefix() + 'update') |
135 | |
136 | - def update_packages(self): |
137 | + def update_packages(self, new_locale=None): |
138 | """ |
139 | Updates all packages installed in the container. |
140 | """ |
141 | self.update_apt_cache() |
142 | + |
143 | + if new_locale: |
144 | + self.locale = new_locale |
145 | + self.language = self._get_language_from_locale() |
146 | + self.update_locale() |
147 | + self.install_base_language_packs() |
148 | + |
149 | return self.run_in_container(_apt_command_prefix() + '--force-yes dist-upgrade') == 0 |
150 | |
151 | def install_package(self, package_name, no_dialog=False, update_cache=True): |
152 | @@ -185,7 +226,11 @@ |
153 | else: |
154 | if no_dialog: |
155 | os.environ['DEBIAN_FRONTEND'] = 'teletype' |
156 | - return self.run_in_container(_apt_command_prefix() + " install '" + package_name + "'") == 0 |
157 | + ret = self.run_in_container(_apt_command_prefix() + " install '" + package_name + "'") == 0 |
158 | + |
159 | + self.check_language_support() |
160 | + |
161 | + return ret |
162 | |
163 | def remove_package(self, package_name): |
164 | """ |
165 | @@ -254,8 +299,8 @@ |
166 | """ |
167 | A concrete mock container type. Used for unit testing. |
168 | """ |
169 | - def __init__(self, container_id): |
170 | - super().__init__(container_id) |
171 | + def __init__(self, container_id, containers_config=None): |
172 | + super().__init__(container_id, containers_config) |
173 | self.container_type = "mock" |
174 | |
175 | def create_libertine_container(self, password=None, multiarch=False): |
176 | @@ -264,7 +309,7 @@ |
177 | def destroy_libertine_container(self): |
178 | return True |
179 | |
180 | - def update_packages(self): |
181 | + def update_packages(self, new_locale=None): |
182 | return True |
183 | |
184 | def install_package(self, package_name, no_dialog=False, update_cache=True): |
185 | @@ -328,7 +373,7 @@ |
186 | from libertine.ChrootContainer import LibertineChroot |
187 | self.container = LibertineChroot(container_id) |
188 | elif container_type == "mock": |
189 | - self.container = LibertineMock(container_id) |
190 | + self.container = LibertineMock(container_id, self.containers_config) |
191 | else: |
192 | raise RuntimeError("Unsupported container type %s" % container_type) |
193 | |
194 | @@ -363,13 +408,13 @@ |
195 | |
196 | return self.container.create_libertine_container(password, multiarch) |
197 | |
198 | - def update_libertine_container(self): |
199 | + def update_libertine_container(self, new_locale=None): |
200 | """ |
201 | Updates the contents of the container. |
202 | """ |
203 | try: |
204 | with ContainerRunning(self.container): |
205 | - return self.container.update_packages() |
206 | + return self.container.update_packages(new_locale) |
207 | except RuntimeError as e: |
208 | return handle_runtime_error(e) |
209 | |
210 | |
211 | === modified file 'python/libertine/LxcContainer.py' |
212 | --- python/libertine/LxcContainer.py 2017-01-10 16:04:09 +0000 |
213 | +++ python/libertine/LxcContainer.py 2017-01-13 18:36:04 +0000 |
214 | @@ -189,14 +189,14 @@ |
215 | cmd_args = shlex.split(command_string) |
216 | return self.container.attach_wait(lxc.attach_run_command, cmd_args) |
217 | |
218 | - def update_packages(self): |
219 | + def update_packages(self, update_locale=False): |
220 | if self.timezone_needs_update(): |
221 | self.run_in_container("bash -c \'echo \"{}\" >/etc/timezone\'".format( |
222 | self.host_info.get_host_timezone())) |
223 | self.run_in_container("rm -f /etc/localtime") |
224 | self.run_in_container("dpkg-reconfigure -f noninteractive tzdata") |
225 | |
226 | - return super().update_packages() |
227 | + return super().update_packages(update_locale) |
228 | |
229 | def destroy_libertine_container(self): |
230 | if not self.container.defined: |
231 | @@ -260,6 +260,8 @@ |
232 | self.destroy_libertine_container() |
233 | return False |
234 | |
235 | + self.update_locale() |
236 | + |
237 | self.run_in_container("userdel -r ubuntu") |
238 | self.run_in_container("useradd -u {} -p {} -G sudo {}".format( |
239 | str(user_id), crypt.crypt(password), str(username))) |
240 | @@ -277,6 +279,8 @@ |
241 | self.destroy_libertine_container() |
242 | return False |
243 | |
244 | + super().create_libertine_container() |
245 | + |
246 | utils.get_logger().info("stopping container ...") |
247 | self.stop_container() |
248 | |
249 | |
250 | === modified file 'python/libertine/LxdContainer.py' |
251 | --- python/libertine/LxdContainer.py 2017-01-12 20:02:42 +0000 |
252 | +++ python/libertine/LxdContainer.py 2017-01-13 18:36:04 +0000 |
253 | @@ -269,6 +269,8 @@ |
254 | self.destroy_libertine_container() |
255 | return False |
256 | |
257 | + self.update_locale() |
258 | + |
259 | username = os.environ['USER'] |
260 | uid = str(os.getuid()) |
261 | self.run_in_container("userdel -r ubuntu") |
262 | @@ -294,16 +296,18 @@ |
263 | self.destroy_libertine_container() |
264 | return False |
265 | |
266 | + super().create_libertine_container() |
267 | + |
268 | return True |
269 | |
270 | - def update_packages(self): |
271 | + def update_packages(self, update_locale=False): |
272 | if not self._timezone_in_sync(): |
273 | utils.get_logger().info("Re-syncing timezones") |
274 | self.run_in_container("bash -c 'echo \"%s\" > /etc/timezone'" % self._host_info.get_host_timezone()) |
275 | self.run_in_container("rm -f /etc/localtime") |
276 | self.run_in_container("dpkg-reconfigure -f noninteractive tzdata") |
277 | |
278 | - return super().update_packages() |
279 | + return super().update_packages(update_locale) |
280 | |
281 | def destroy_libertine_container(self): |
282 | if not self._try_get_container(): |
283 | |
284 | === modified file 'tools/libertine-container-manager' |
285 | --- tools/libertine-container-manager 2017-01-12 15:42:03 +0000 |
286 | +++ tools/libertine-container-manager 2017-01-13 18:36:04 +0000 |
287 | @@ -34,6 +34,14 @@ |
288 | self.containers_config = ContainersConfig() |
289 | self.host_info = HostInfo() |
290 | |
291 | + def _get_updated_locale(self, container_id): |
292 | + host_locale = self.host_info.get_host_locale() |
293 | + |
294 | + if host_locale == self.containers_config.get_container_locale(container_id): |
295 | + return None |
296 | + else: |
297 | + return host_locale |
298 | + |
299 | def create(self, args): |
300 | password = None |
301 | |
302 | @@ -88,6 +96,7 @@ |
303 | self.containers_config.update_container_multiarch_support(args.id, multiarch) |
304 | |
305 | try: |
306 | + self.containers_config.update_container_locale(args.id, self.host_info.get_host_locale()) |
307 | container = LibertineContainer(args.id) |
308 | self.containers_config.update_container_install_status(args.id, "installing") |
309 | if not container.create_libertine_container(password, args.multiarch): |
310 | @@ -142,7 +151,7 @@ |
311 | else: |
312 | self.containers_config.add_new_package(container_id, package) |
313 | |
314 | - container = LibertineContainer(container_id) |
315 | + container = LibertineContainer(container_id, self.containers_config) |
316 | |
317 | self.containers_config.update_package_install_status(container_id, package, "installing") |
318 | if not container.install_package(args.package, args.no_dialog): |
319 | @@ -194,14 +203,18 @@ |
320 | |
321 | def update(self, args): |
322 | container_id = self.containers_config.check_container_id(args.id) |
323 | + new_locale = self._get_updated_locale(container_id) |
324 | |
325 | container = LibertineContainer(container_id) |
326 | |
327 | self.containers_config.update_container_install_status(container_id, "updating") |
328 | - if not container.update_libertine_container(): |
329 | + if not container.update_libertine_container(new_locale): |
330 | self.containers_config.update_container_install_status(container_id, "ready") |
331 | sys.exit(1) |
332 | |
333 | + if new_locale: |
334 | + self.containers_config.update_container_locale(container_id, new_locale) |
335 | + |
336 | self.containers_config.update_container_install_status(container_id, "ready") |
337 | |
338 | def list(self, args): |
339 | @@ -457,7 +470,8 @@ |
340 | # Handle the update command and its options |
341 | parser_update = subparsers.add_parser( |
342 | 'update', |
343 | - help=("Update the packages in the Libertine container.")) |
344 | + help=("Update the packages in the Libertine container. Also updates the container's " |
345 | + "locale and installs necessary language packs if the host's locale has changed.")) |
346 | parser_update.add_argument( |
347 | '-i', '--id', |
348 | help=("Container identifier. Default container is used if omitted.")) |
349 | |
350 | === modified file 'tools/libertine-container-manager.1' |
351 | --- tools/libertine-container-manager.1 2016-12-07 21:24:16 +0000 |
352 | +++ tools/libertine-container-manager.1 2017-01-13 18:36:04 +0000 |
353 | @@ -52,7 +52,7 @@ |
354 | Searches the apt cache inside an existing Libertine container for matches based on the given search string. |
355 | .TP |
356 | .B libertine-container-manager update [options] |
357 | -Updates the packages inside an existing Libertine container. |
358 | +Updates the packages inside an existing Libertine container. Also updates the container's locale and installs necessary language packs if the host's locale has changed. |
359 | .TP |
360 | .B libertine-container-manager list [options] |
361 | Lists all existing Libertine containers. |
FAILED: Continuous integration, rev:370 /jenkins. canonical. com/libertine/ job/lp- libertine- ci/318/ /jenkins. canonical. com/libertine/ job/build/ 635/console /jenkins. canonical. com/libertine/ job/build- 0-fetch/ 645 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 626/console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= zesty/626/ console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 626/console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= zesty/626/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/libertine/ job/lp- libertine- ci/318/ rebuild
https:/