Merge lp:click/devel into lp:click

Proposed by Michael Vogt
Status: Merged
Approved by: Michael Vogt
Approved revision: 557
Merged at revision: 452
Proposed branch: lp:click/devel
Merge into: lp:click
Diff against target: 747 lines (+318/-153)
10 files modified
click/build.py (+4/-1)
click/chroot.py (+174/-128)
click/commands/install.py (+5/-1)
click/install.py (+17/-6)
click/tests/test_build.py (+2/-0)
click/tests/test_chroot.py (+14/-5)
click/tests/test_install.py (+5/-11)
debian/changelog (+30/-0)
debian/click.postinst (+3/-1)
lib/click/user.vala (+64/-0)
To merge this branch: bzr merge lp:click/devel
Reviewer Review Type Date Requested Status
Michael Vogt Approve
Review via email: mp+249631@code.launchpad.net

Commit message

Click 0.4.37 (skipping 0.4.36 to workaround version conflicts in PPAs): bugfixes, geoip based chroot mirror selection

Description of the change

  [ Michael Vogt ]
  * lp:~mvo/click/no-error-no-missing-systemctl:
    - fix a spurious error message on systems without systemctl
  * lp:~mvo/click/do-not-crash-in-build-on-broken-symlinks:
    - do not crash when building a click package that contains broken
      symlinks
  * lp:~mvo/click/dpkg-less-verbose:
    - do not show dpkg output on install unless --verbose is used
  * lp:~mvo/click/lp1394256-run-user-hooks:
    - ensures that click user hooks are run for all logged in users when
      click is used with "--all-users".
  * lp:~mvo/click/qt5-qmake-cross-armhf:
    - add qt5-qmake-arm-linux-gnueabihf to chroot (LP: #1393698)
  * lp:~mvo/click/chroot-15.04-multiarch:
    - add ubuntu-sdk-libs-tools and oxide-codecs-extra to the chroot
  * lp:~mvo/click/lp1394256-run-user-hooks-on-remove-too:
    - Run the click remove user hooks for all logged in users.
  * click/chroot.py:
    - use string.format() for chroot TARGET selection
  * skip 0.4.36 version and go straight to 0.4.37 (LP: #1418086)

  [ Zoltan Balogh ]
  * lp:~bzoltan/click/vivid-transition_mirrors:
    - use geoip to guess the most suitable country mirror when creating
      the click chroot

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'click/build.py'
--- click/build.py 2014-05-05 13:10:19 +0000
+++ click/build.py 2015-02-13 12:37:00 +0000
@@ -274,7 +274,10 @@
274 with open(md5sums_path, "w") as md5sums:274 with open(md5sums_path, "w") as md5sums:
275 for path in sorted(self.list_files(root_path)):275 for path in sorted(self.list_files(root_path)):
276 md5 = hashlib.md5()276 md5 = hashlib.md5()
277 with open(os.path.join(root_path, path), "rb") as f:277 p = os.path.join(root_path, path)
278 if not os.path.exists(p):
279 continue
280 with open(p, "rb") as f:
278 while True:281 while True:
279 buf = f.read(16384)282 buf = f.read(16384)
280 if not buf:283 if not buf:
281284
=== modified file 'click/chroot.py'
--- click/chroot.py 2014-11-13 10:20:37 +0000
+++ click/chroot.py 2015-02-13 12:37:00 +0000
@@ -26,6 +26,8 @@
26 "ClickChrootDoesNotExistException",26 "ClickChrootDoesNotExistException",
27 ]27 ]
2828
29import urllib
30import urllib.request
29import os31import os
30import pwd32import pwd
31import re33import re
@@ -34,6 +36,7 @@
34import subprocess36import subprocess
35import sys37import sys
36from textwrap import dedent38from textwrap import dedent
39from xml.etree import ElementTree
3740
3841
39framework_base = {42framework_base = {
@@ -67,114 +70,121 @@
67# Please keep the lists of package names sorted.70# Please keep the lists of package names sorted.
68extra_packages = {71extra_packages = {
69 "ubuntu-sdk-13.10": [72 "ubuntu-sdk-13.10": [
70 "libqt5opengl5-dev:TARGET",73 "libqt5opengl5-dev:{TARGET}",
71 "libqt5svg5-dev:TARGET",74 "libqt5svg5-dev:{TARGET}",
72 "libqt5v8-5-dev:TARGET",75 "libqt5v8-5-dev:{TARGET}",
73 "libqt5webkit5-dev:TARGET",76 "libqt5webkit5-dev:{TARGET}",
74 "libqt5xmlpatterns5-dev:TARGET",77 "libqt5xmlpatterns5-dev:{TARGET}",
75 "qmlscene:TARGET",78 "qmlscene:{TARGET}",
76 "qt3d5-dev:TARGET",79 "qt3d5-dev:{TARGET}",
77 "qt5-default:TARGET",80 "qt5-default:{TARGET}",
78 "qt5-qmake:TARGET",81 "qt5-qmake:{TARGET}",
79 "qtbase5-dev:TARGET",82 "qtbase5-dev:{TARGET}",
80 "qtdeclarative5-dev:TARGET",83 "qtdeclarative5-dev:{TARGET}",
81 "qtmultimedia5-dev:TARGET",84 "qtmultimedia5-dev:{TARGET}",
82 "qtquick1-5-dev:TARGET",85 "qtquick1-5-dev:{TARGET}",
83 "qtscript5-dev:TARGET",86 "qtscript5-dev:{TARGET}",
84 "qtsensors5-dev:TARGET",87 "qtsensors5-dev:{TARGET}",
85 "qttools5-dev:TARGET",88 "qttools5-dev:{TARGET}",
86 "ubuntu-ui-toolkit-doc",89 "ubuntu-ui-toolkit-doc",
87 ],90 ],
88 "ubuntu-sdk-14.04": [91 "ubuntu-sdk-14.04": [
89 "cmake",92 "cmake",
90 "google-mock:TARGET",93 "google-mock:{TARGET}",
91 "intltool",94 "intltool",
92 "libboost1.54-dev:TARGET",95 "libboost1.54-dev:{TARGET}",
93 "libjsoncpp-dev:TARGET",96 "libjsoncpp-dev:{TARGET}",
94 "libprocess-cpp-dev:TARGET",97 "libprocess-cpp-dev:{TARGET}",
95 "libproperties-cpp-dev:TARGET",98 "libproperties-cpp-dev:{TARGET}",
96 "libqt5svg5-dev:TARGET",99 "libqt5svg5-dev:{TARGET}",
97 "libqt5webkit5-dev:TARGET",100 "libqt5webkit5-dev:{TARGET}",
98 "libqt5xmlpatterns5-dev:TARGET",101 "libqt5xmlpatterns5-dev:{TARGET}",
99 "libunity-scopes-dev:TARGET",102 "libunity-scopes-dev:{TARGET}",
100 # bug #1316930, needed for autopilot103 # bug #1316930, needed for autopilot
101 "python3",104 "python3",
102 "qmlscene:TARGET",105 "qmlscene:{TARGET}",
103 "qt3d5-dev:TARGET",106 "qt3d5-dev:{TARGET}",
104 "qt5-default:TARGET",107 "qt5-default:{TARGET}",
105 "qtbase5-dev:TARGET",108 "qtbase5-dev:{TARGET}",
106 "qtdeclarative5-dev:TARGET",109 "qtdeclarative5-dev:{TARGET}",
107 "qtdeclarative5-dev-tools",110 "qtdeclarative5-dev-tools",
108 "qtlocation5-dev:TARGET",111 "qtlocation5-dev:{TARGET}",
109 "qtmultimedia5-dev:TARGET",112 "qtmultimedia5-dev:{TARGET}",
110 "qtscript5-dev:TARGET",113 "qtscript5-dev:{TARGET}",
111 "qtsensors5-dev:TARGET",114 "qtsensors5-dev:{TARGET}",
112 "qttools5-dev:TARGET",115 "qttools5-dev:{TARGET}",
113 "qttools5-dev-tools:TARGET",116 "qttools5-dev-tools:{TARGET}",
114 "ubuntu-ui-toolkit-doc",117 "ubuntu-ui-toolkit-doc",
115 ],118 ],
116 "ubuntu-sdk-14.10": [119 "ubuntu-sdk-14.10": [
117 "cmake",120 "cmake",
118 "cmake-extras",121 "cmake-extras",
119 "google-mock:TARGET",122 "google-mock:{TARGET}",
120 "intltool",123 "intltool",
121 "libboost1.55-dev:TARGET",124 "libboost1.55-dev:{TARGET}",
122 "libcontent-hub-dev:TARGET",125 "libcontent-hub-dev:{TARGET}",
123 "libjsoncpp-dev:TARGET",126 "libjsoncpp-dev:{TARGET}",
124 "libnet-cpp-dev:TARGET",127 "libnet-cpp-dev:{TARGET}",
125 "libprocess-cpp-dev:TARGET",128 "libprocess-cpp-dev:{TARGET}",
126 "libproperties-cpp-dev:TARGET",129 "libproperties-cpp-dev:{TARGET}",
127 "libqt5keychain0:TARGET",130 "libqt5keychain0:{TARGET}",
128 "libqt5sensors5-dev:TARGET",131 "libqt5sensors5-dev:{TARGET}",
129 "libqt5svg5-dev:TARGET",132 "libqt5svg5-dev:{TARGET}",
130 "libqt5webkit5-dev:TARGET",133 "libqt5webkit5-dev:{TARGET}",
131 "libqt5xmlpatterns5-dev:TARGET",134 "libqt5xmlpatterns5-dev:{TARGET}",
132 "libunity-scopes-dev:TARGET",135 "libunity-scopes-dev:{TARGET}",
133 # bug #1316930, needed for autopilot136 # bug #1316930, needed for autopilot
134 "python3",137 "python3",
135 "qml-module-qt-labs-settings:TARGET",138 "qml-module-qt-labs-settings:{TARGET}",
136 "qml-module-qtmultimedia:TARGET",139 "qml-module-qtmultimedia:{TARGET}",
137 "qml-module-qtquick-layouts:TARGET",140 "qml-module-qtquick-layouts:{TARGET}",
138 "qml-module-qtsensors:TARGET",141 "qml-module-qtsensors:{TARGET}",
139 "qml-module-qtwebkit:TARGET",142 "qml-module-qtwebkit:{TARGET}",
140 "qmlscene:TARGET",143 "qmlscene:{TARGET}",
141 "qt3d5-dev:TARGET",144 "qt3d5-dev:{TARGET}",
142 "qt5-default:TARGET",145 "qt5-default:{TARGET}",
143 "qtdeclarative5-accounts-plugin:TARGET",146 "qtdeclarative5-accounts-plugin:{TARGET}",
144 "qtdeclarative5-dev-tools",147 "qtdeclarative5-dev-tools",
145 "qtdeclarative5-folderlistmodel-plugin:TARGET",148 "qtdeclarative5-folderlistmodel-plugin:{TARGET}",
146 "qtdeclarative5-localstorage-plugin:TARGET",149 "qtdeclarative5-localstorage-plugin:{TARGET}",
147 "qtdeclarative5-online-accounts-client0.1:TARGET",150 "qtdeclarative5-online-accounts-client0.1:{TARGET}",
148 "qtdeclarative5-particles-plugin:TARGET",151 "qtdeclarative5-particles-plugin:{TARGET}",
149 "qtdeclarative5-poppler1.0:TARGET",152 "qtdeclarative5-poppler1.0:{TARGET}",
150 "qtdeclarative5-qtlocation-plugin:TARGET",153 "qtdeclarative5-qtlocation-plugin:{TARGET}",
151 "qtdeclarative5-qtorganizer-plugin:TARGET",154 "qtdeclarative5-qtorganizer-plugin:{TARGET}",
152 "qtdeclarative5-qtpositioning-plugin:TARGET",155 "qtdeclarative5-qtpositioning-plugin:{TARGET}",
153 "qtdeclarative5-u1db1.0:TARGET",156 "qtdeclarative5-u1db1.0:{TARGET}",
154 "qtdeclarative5-ubuntu-content0.1:TARGET",157 "qtdeclarative5-ubuntu-content0.1:{TARGET}",
155 "qtdeclarative5-ubuntu-download-manager0.1:TARGET",158 "qtdeclarative5-ubuntu-download-manager0.1:{TARGET}",
156 "qtdeclarative5-ubuntu-mediascanner0.1:TARGET",159 "qtdeclarative5-ubuntu-mediascanner0.1:{TARGET}",
157 "qtdeclarative5-ubuntu-syncmonitor0.1:TARGET",160 "qtdeclarative5-ubuntu-syncmonitor0.1:{TARGET}",
158 "qtdeclarative5-ubuntu-telephony-phonenumber0.1:TARGET",161 "qtdeclarative5-ubuntu-telephony-phonenumber0.1:{TARGET}",
159 "qtdeclarative5-ubuntu-ui-toolkit-plugin:TARGET",162 "qtdeclarative5-ubuntu-ui-toolkit-plugin:{TARGET}",
160 "qtdeclarative5-usermetrics0.1:TARGET",163 "qtdeclarative5-usermetrics0.1:{TARGET}",
161 "qtdeclarative5-xmllistmodel-plugin:TARGET",164 "qtdeclarative5-xmllistmodel-plugin:{TARGET}",
162 "qtlocation5-dev:TARGET",165 "qtlocation5-dev:{TARGET}",
163 "qtmultimedia5-dev:TARGET",166 "qtmultimedia5-dev:{TARGET}",
164 "qtscript5-dev:TARGET",167 "qtscript5-dev:{TARGET}",
165 "qttools5-dev:TARGET",168 "qttools5-dev:{TARGET}",
166 "qttools5-dev-tools:TARGET",169 "qttools5-dev-tools:{TARGET}",
167 "ubuntu-html5-theme:TARGET",170 "ubuntu-html5-theme:{TARGET}",
168 "ubuntu-ui-toolkit-doc",171 "ubuntu-ui-toolkit-doc",
169 ],172 ],
170 "ubuntu-sdk-15.04": [173 "ubuntu-sdk-15.04": [
171 # the sdk libs174 # the sdk libs
172 "ubuntu-sdk-libs:TARGET",175 "ubuntu-sdk-libs:{TARGET}",
173 "ubuntu-sdk-libs-dev:TARGET",176 "ubuntu-sdk-libs-dev:{TARGET}",
177 # the native build tools
178 "ubuntu-sdk-libs-tools",
179 # FIXME: see
180 # http://pad.lv/~mvo/oxide/crossbuild-friendly/+merge/234093
181 # we help the apt resolver here until the
182 # oxideqt-codecs/oxidec-codecs-extras is sorted
183 "oxideqt-codecs-extra",
174 ],184 ],
175 "ubuntu-core-15.04-dev1": [185 "ubuntu-core-15.04-dev1": [
176 "ubuntu-core-libs:TARGET",186 "ubuntu-core-libs:{TARGET}",
177 "ubuntu-core-libs-dev:TARGET",187 "ubuntu-core-libs-dev:{TARGET}",
178 ],188 ],
179 }189 }
180190
@@ -185,6 +195,56 @@
185non_meta_re = re.compile(r'^[a-zA-Z0-9+,./:=@_-]+$')195non_meta_re = re.compile(r'^[a-zA-Z0-9+,./:=@_-]+$')
186196
187197
198GEOIP_SERVER = "http://geoip.ubuntu.com/lookup"
199
200
201def get_geoip_country_code_prefix():
202 click_no_local_mirror = os.environ.get('CLICK_NO_LOCAL_MIRROR', 'auto')
203 if click_no_local_mirror == '1':
204 return ""
205 try:
206 with urllib.request.urlopen(GEOIP_SERVER) as f:
207 xml_data = f.read()
208 et = ElementTree.fromstring(xml_data)
209 return et.find("CountryCode").text.lower()+"."
210 except (ElementTree.ParseError, urllib.error.URLError):
211 pass
212 return ""
213
214def generate_sources(series, native_arch, target_arch,
215 archive_mirror, ports_mirror, components):
216 """Generate a list of strings for apts sources.list.
217 Arguments:
218 series -- the distro series (e.g. vivid)
219 native_arch -- the native architecture (e.g. amd64)
220 target_arch -- the target architecture (e.g. armhf)
221 archive_mirror -- main mirror, e.g. http://archive.ubuntu.com/ubuntu
222 ports_mirror -- ports mirror, e.g. http://ports.ubuntu.com/ubuntu-ports
223 components -- the components as string, e.g. "main restricted universe"
224 """
225 pockets = ['%s' % series]
226 for pocket in ['updates', 'security']:
227 pockets.append('%s-%s' % (series, pocket))
228 sources = []
229 # write binary lines
230 arches = [target_arch]
231 if native_arch != target_arch:
232 arches.append(native_arch)
233 for arch in arches:
234 if arch not in primary_arches:
235 mirror = ports_mirror
236 else:
237 mirror = archive_mirror
238 for pocket in pockets:
239 sources.append("deb [arch=%s] %s %s %s" %
240 (arch, mirror, pocket, components))
241 # write source lines
242 for pocket in pockets:
243 sources.append("deb-src %s %s %s" %
244 (archive_mirror, pocket, components))
245 return sources
246
247
188def shell_escape(command):248def shell_escape(command):
189 escaped = []249 escaped = []
190 for arg in command:250 for arg in command:
@@ -247,11 +307,7 @@
247 if chroots_dir is None:307 if chroots_dir is None:
248 chroots_dir = "/var/lib/schroot/chroots"308 chroots_dir = "/var/lib/schroot/chroots"
249 self.chroots_dir = chroots_dir309 self.chroots_dir = chroots_dir
250 # this doesn't work because we are running this under sudo310
251 if 'DEBOOTSTRAP_MIRROR' in os.environ:
252 self.archive = os.environ['DEBOOTSTRAP_MIRROR']
253 else:
254 self.archive = "http://archive.ubuntu.com/ubuntu"
255 if "SUDO_USER" in os.environ:311 if "SUDO_USER" in os.environ:
256 self.user = os.environ["SUDO_USER"]312 self.user = os.environ["SUDO_USER"]
257 elif "PKEXEC_UID" in os.environ:313 elif "PKEXEC_UID" in os.environ:
@@ -330,31 +386,6 @@
330 users="\n".join(users),386 users="\n".join(users),
331 mount=mount))387 mount=mount))
332388
333 def _generate_sources(self, series, native_arch, target_arch, components):
334 ports_mirror = "http://ports.ubuntu.com/ubuntu-ports"
335 pockets = ['%s' % series]
336 for pocket in ['updates', 'security']:
337 pockets.append('%s-%s' % (series, pocket))
338 sources = []
339 # write binary lines
340 arches = [target_arch]
341 if native_arch != target_arch:
342 arches.append(native_arch)
343 for arch in arches:
344 if arch not in primary_arches:
345 mirror = ports_mirror
346 else:
347 mirror = self.archive
348 for pocket in pockets:
349 sources.append("deb [arch=%s] %s %s %s" %
350 (arch, mirror, pocket, components))
351 # write source lines
352 for pocket in pockets:
353 sources.append("deb-src %s %s %s" %
354 (self.archive, pocket, components))
355
356 return sources
357
358 def _generate_daemon_policy(self, mount):389 def _generate_daemon_policy(self, mount):
359 daemon_policy = "%s/usr/sbin/policy-rc.d" % mount390 daemon_policy = "%s/usr/sbin/policy-rc.d" % mount
360 with open(daemon_policy, "w") as policy:391 with open(daemon_policy, "w") as policy:
@@ -409,7 +440,7 @@
409 build_pkgs=' '.join(build_pkgs)))440 build_pkgs=' '.join(build_pkgs)))
410 return finish_script441 return finish_script
411442
412 def _debootstrap(self, components, mount):443 def _debootstrap(self, components, mount, archive):
413 subprocess.check_call([444 subprocess.check_call([
414 "debootstrap",445 "debootstrap",
415 "--arch", self.native_arch,446 "--arch", self.native_arch,
@@ -417,7 +448,7 @@
417 "--components=%s" % ','.join(components),448 "--components=%s" % ','.join(components),
418 self.series,449 self.series,
419 mount,450 mount,
420 self.archive451 archive
421 ])452 ])
422453
423 @property454 @property
@@ -467,22 +498,37 @@
467 proxy = os.environ["http_proxy"]498 proxy = os.environ["http_proxy"]
468 if not proxy:499 if not proxy:
469 proxy = subprocess.check_output(500 proxy = subprocess.check_output(
470 'unset x; eval "$(apt-config shell x Acquire::HTTP::Proxy)"; echo "$x"',501 'unset x; eval "$(apt-config shell x Acquire::HTTP::Proxy)"; \
502 echo "$x"',
471 shell=True, universal_newlines=True).strip()503 shell=True, universal_newlines=True).strip()
472 build_pkgs = [504 build_pkgs = [
473 "build-essential", "fakeroot",505 # sort alphabetically
474 "apt-utils", self._make_cross_package("g++"),506 "apt-utils",
475 self._make_cross_package("pkg-config"), "cmake",507 "build-essential",
476 "dpkg-cross", "libc-dev:%s" % self.target_arch508 "cmake",
477 ]509 "dpkg-cross",
510 "fakeroot",
511 "libc-dev:%s" % self.target_arch,
512 # build pkg names dynamically
513 self._make_cross_package("g++"),
514 self._make_cross_package("pkg-config"),
515 ]
478 for package in extra_packages.get(self.framework_base, []):516 for package in extra_packages.get(self.framework_base, []):
479 package = package.replace(":TARGET", ":%s" % self.target_arch)517 package = package.format(TARGET=self.target_arch)
480 build_pkgs.append(package)518 build_pkgs.append(package)
481 os.makedirs(mount)519 os.makedirs(mount)
482 self._debootstrap(components, mount)520
483 sources = self._generate_sources(self.series, self.native_arch,521 country_code = get_geoip_country_code_prefix()
484 self.target_arch,522 archive = "http://%sarchive.ubuntu.com/ubuntu" % country_code
485 ' '.join(components))523 ports_mirror = "http://%sports.ubuntu.com/ubuntu-ports" % country_code
524 # this doesn't work because we are running this under sudo
525 if 'DEBOOTSTRAP_MIRROR' in os.environ:
526 archive = os.environ['DEBOOTSTRAP_MIRROR']
527 self._debootstrap(components, mount, archive)
528 sources = generate_sources(self.series, self.native_arch,
529 self.target_arch,
530 archive, ports_mirror,
531 ' '.join(components))
486 with open("%s/etc/apt/sources.list" % mount, "w") as sources_list:532 with open("%s/etc/apt/sources.list" % mount, "w") as sources_list:
487 for line in sources:533 for line in sources:
488 print(line, file=sources_list)534 print(line, file=sources_list)
489535
=== modified file 'click/commands/install.py'
--- click/commands/install.py 2014-09-10 12:28:49 +0000
+++ click/commands/install.py 2015-02-13 12:37:00 +0000
@@ -46,6 +46,9 @@
46 parser.add_option(46 parser.add_option(
47 "--allow-unauthenticated", default=False, action="store_true",47 "--allow-unauthenticated", default=False, action="store_true",
48 help="allow installing packages with no signatures")48 help="allow installing packages with no signatures")
49 parser.add_option(
50 "--verbose", default=False, action="store_true",
51 help="be more verbose on install")
49 options, args = parser.parse_args(argv)52 options, args = parser.parse_args(argv)
50 if len(args) < 1:53 if len(args) < 1:
51 parser.error("need package file name")54 parser.error("need package file name")
@@ -59,7 +62,8 @@
59 allow_unauthenticated=options.allow_unauthenticated)62 allow_unauthenticated=options.allow_unauthenticated)
60 try:63 try:
61 installer.install(64 installer.install(
62 package_path, user=options.user, all_users=options.all_users)65 package_path, user=options.user, all_users=options.all_users,
66 quiet=not options.verbose)
63 except ClickInstallerError as e:67 except ClickInstallerError as e:
64 print("Cannot install %s: %s" % (package_path, e), file=sys.stderr)68 print("Cannot install %s: %s" % (package_path, e), file=sys.stderr)
65 return 169 return 1
6670
=== modified file 'click/install.py'
--- click/install.py 2014-09-10 11:50:18 +0000
+++ click/install.py 2015-02-13 12:37:00 +0000
@@ -347,7 +347,7 @@
347 os.mkdir(os.path.join(admin_dir, "updates"))347 os.mkdir(os.path.join(admin_dir, "updates"))
348 os.mkdir(os.path.join(admin_dir, "triggers"))348 os.mkdir(os.path.join(admin_dir, "triggers"))
349349
350 def _unpack(self, path, user=None, all_users=False):350 def _unpack(self, path, user=None, all_users=False, quiet=True):
351 package_name, package_version = self.audit(path, check_arch=True)351 package_name, package_version = self.audit(path, check_arch=True)
352352
353 # Is this package already unpacked in an underlay (non-topmost)353 # Is this package already unpacked in an underlay (non-topmost)
@@ -401,9 +401,20 @@
401 kwargs = {}401 kwargs = {}
402 if sys.version >= "3.2":402 if sys.version >= "3.2":
403 kwargs["pass_fds"] = (fd.fileno(),)403 kwargs["pass_fds"] = (fd.fileno(),)
404 subprocess.check_call(404 if quiet:
405 command, preexec_fn=partial(self._install_preexec, inst_dir),405 fn = subprocess.check_output
406 env=env, **kwargs)406 kwargs["stderr"] = subprocess.STDOUT
407 else:
408 fn = subprocess.check_call
409 try:
410 fn(command,
411 preexec_fn=partial(self._install_preexec, inst_dir),
412 env=env, universal_newlines=True,
413 **kwargs)
414 except subprocess.CalledProcessError as e:
415 logging.error("%s failed with exit_code %s:\n%s" % (
416 command, e.returncode, e.output))
417 raise
407 for dirpath, dirnames, filenames in os.walk(inst_dir):418 for dirpath, dirnames, filenames in os.walk(inst_dir):
408 for entry in dirnames + filenames:419 for entry in dirnames + filenames:
409 entry_path = os.path.join(dirpath, entry)420 entry_path = os.path.join(dirpath, entry)
@@ -441,9 +452,9 @@
441452
442 return package_name, package_version, old_version453 return package_name, package_version, old_version
443454
444 def install(self, path, user=None, all_users=False):455 def install(self, path, user=None, all_users=False, quiet=True):
445 package_name, package_version, old_version = self._unpack(456 package_name, package_version, old_version = self._unpack(
446 path, user=user, all_users=all_users)457 path, user=user, all_users=all_users, quiet=quiet)
447458
448 if user is not None or all_users:459 if user is not None or all_users:
449 if all_users:460 if all_users:
450461
=== modified file 'click/tests/test_build.py'
--- click/tests/test_build.py 2014-09-04 13:41:30 +0000
+++ click/tests/test_build.py 2015-02-13 12:37:00 +0000
@@ -134,6 +134,8 @@
134 touch(os.path.join(scratch, ".git", "config"))134 touch(os.path.join(scratch, ".git", "config"))
135 with mkfile(os.path.join(scratch, "toplevel")) as f:135 with mkfile(os.path.join(scratch, "toplevel")) as f:
136 f.write("test /toplevel\n")136 f.write("test /toplevel\n")
137 os.symlink(
138 "file-does-not-exist", os.path.join(scratch, "broken-symlink"))
137 with mkfile(os.path.join(scratch, "manifest.json")) as f:139 with mkfile(os.path.join(scratch, "manifest.json")) as f:
138 json.dump({140 json.dump({
139 "name": "com.example.test",141 "name": "com.example.test",
140142
=== modified file 'click/tests/test_chroot.py'
--- click/tests/test_chroot.py 2014-07-02 09:07:13 +0000
+++ click/tests/test_chroot.py 2015-02-13 12:37:00 +0000
@@ -28,6 +28,7 @@
2828
29from click.chroot import (29from click.chroot import (
30 ClickChroot,30 ClickChroot,
31 generate_sources,
31 strip_dev_series_from_framework,32 strip_dev_series_from_framework,
32)33)
33from click.tests.helpers import TestCase, mock34from click.tests.helpers import TestCase, mock
@@ -48,7 +49,7 @@
48 self._maint_kwargs = kwargs49 self._maint_kwargs = kwargs
49 return 050 return 0
5051
51 def _debootstrap(self, components, mount):52 def _debootstrap(self, components, mount, archive_server):
52 os.makedirs(os.path.join(mount, "etc", "apt"))53 os.makedirs(os.path.join(mount, "etc", "apt"))
53 os.makedirs(os.path.join(mount, "usr", "sbin"))54 os.makedirs(os.path.join(mount, "usr", "sbin"))
54 os.makedirs(os.path.join(mount, "sbin"))55 os.makedirs(os.path.join(mount, "sbin"))
@@ -110,8 +111,10 @@
110 def test_gen_sources_archive_only(self):111 def test_gen_sources_archive_only(self):
111 chroot = ClickChroot("amd64", "ubuntu-sdk-13.10", series="trusty")112 chroot = ClickChroot("amd64", "ubuntu-sdk-13.10", series="trusty")
112 chroot.native_arch = "i386"113 chroot.native_arch = "i386"
113 sources = chroot._generate_sources(114 sources = generate_sources(
114 chroot.series, chroot.native_arch, chroot.target_arch,115 chroot.series, chroot.native_arch, chroot.target_arch,
116 "http://archive.ubuntu.com/ubuntu",
117 "http://ports.ubuntu.com/ubuntu-ports",
115 "main")118 "main")
116 self.assertEqual([119 self.assertEqual([
117 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu trusty main',120 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu trusty main',
@@ -128,8 +131,10 @@
128 def test_gen_sources_mixed_archive_ports(self):131 def test_gen_sources_mixed_archive_ports(self):
129 chroot = ClickChroot("armhf", "ubuntu-sdk-13.10", series="trusty")132 chroot = ClickChroot("armhf", "ubuntu-sdk-13.10", series="trusty")
130 chroot.native_arch = "i386"133 chroot.native_arch = "i386"
131 sources = chroot._generate_sources(134 sources = generate_sources(
132 chroot.series, chroot.native_arch, chroot.target_arch,135 chroot.series, chroot.native_arch, chroot.target_arch,
136 "http://archive.ubuntu.com/ubuntu",
137 "http://ports.ubuntu.com/ubuntu-ports",
133 "main")138 "main")
134 self.assertEqual([139 self.assertEqual([
135 'deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports trusty main',140 'deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports trusty main',
@@ -146,8 +151,10 @@
146 def test_gen_sources_ports_only(self):151 def test_gen_sources_ports_only(self):
147 chroot = ClickChroot("armhf", "ubuntu-sdk-13.10", series="trusty")152 chroot = ClickChroot("armhf", "ubuntu-sdk-13.10", series="trusty")
148 chroot.native_arch = "armel"153 chroot.native_arch = "armel"
149 sources = chroot._generate_sources(154 sources = generate_sources(
150 chroot.series, chroot.native_arch, chroot.target_arch,155 chroot.series, chroot.native_arch, chroot.target_arch,
156 "http://archive.ubuntu.com/ubuntu",
157 "http://ports.ubuntu.com/ubuntu-ports",
151 "main")158 "main")
152 self.assertEqual([159 self.assertEqual([
153 'deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports trusty main',160 'deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports trusty main',
@@ -164,8 +171,10 @@
164 def test_gen_sources_native(self):171 def test_gen_sources_native(self):
165 chroot = ClickChroot("i386", "ubuntu-sdk-14.04", series="trusty")172 chroot = ClickChroot("i386", "ubuntu-sdk-14.04", series="trusty")
166 chroot.native_arch = "i386"173 chroot.native_arch = "i386"
167 sources = chroot._generate_sources(174 sources = generate_sources(
168 chroot.series, chroot.native_arch, chroot.target_arch,175 chroot.series, chroot.native_arch, chroot.target_arch,
176 "http://archive.ubuntu.com/ubuntu",
177 "http://ports.ubuntu.com/ubuntu-ports",
169 "main")178 "main")
170 self.assertEqual([179 self.assertEqual([
171 'deb [arch=i386] http://archive.ubuntu.com/ubuntu trusty main',180 'deb [arch=i386] http://archive.ubuntu.com/ubuntu trusty main',
172181
=== modified file 'click/tests/test_install.py'
--- click/tests/test_install.py 2014-08-19 06:32:16 +0000
+++ click/tests/test_install.py 2015-02-13 12:37:00 +0000
@@ -456,18 +456,12 @@
456 with self.run_in_subprocess(456 with self.run_in_subprocess(
457 "click_get_frameworks_dir") as (enter, preloads):457 "click_get_frameworks_dir") as (enter, preloads):
458 enter()458 enter()
459 original_call = subprocess.call459 original_call = subprocess.check_output
460460
461 def call_side_effect(*args, **kwargs):461 def call_side_effect(*args, **kwargs):
462 if "TEST_VERBOSE" in os.environ:462 return original_call(
463 return original_call(463 ["touch", os.path.join(self.temp_dir, "sentinel")],
464 ["touch", os.path.join(self.temp_dir, "sentinel")],464 **kwargs)
465 **kwargs)
466 else:
467 with open("/dev/null", "w") as devnull:
468 return original_call(
469 ["touch", os.path.join(self.temp_dir, "sentinel")],
470 stdout=devnull, stderr=devnull, **kwargs)
471465
472 path = self.make_fake_package(466 path = self.make_fake_package(
473 control_fields={467 control_fields={
@@ -490,7 +484,7 @@
490 db.add(root)484 db.add(root)
491 installer = ClickInstaller(db)485 installer = ClickInstaller(db)
492 self._setup_frameworks(preloads, frameworks=["ubuntu-sdk-13.10"])486 self._setup_frameworks(preloads, frameworks=["ubuntu-sdk-13.10"])
493 with mock.patch("subprocess.call") as mock_call:487 with mock.patch("subprocess.check_output") as mock_call:
494 mock_call.side_effect = call_side_effect488 mock_call.side_effect = call_side_effect
495 self.assertRaises(489 self.assertRaises(
496 subprocess.CalledProcessError, installer.install, path)490 subprocess.CalledProcessError, installer.install, path)
497491
=== modified file 'debian/changelog'
--- debian/changelog 2014-11-14 12:29:14 +0000
+++ debian/changelog 2015-02-13 12:37:00 +0000
@@ -1,3 +1,33 @@
1click (0.4.37) UNRELEASED; urgency=low
2
3 [ Michael Vogt ]
4 * lp:~mvo/click/no-error-no-missing-systemctl:
5 - fix a spurious error message on systems without systemctl
6 * lp:~mvo/click/do-not-crash-in-build-on-broken-symlinks:
7 - do not crash when building a click package that contains broken
8 symlinks
9 * lp:~mvo/click/dpkg-less-verbose:
10 - do not show dpkg output on install unless --verbose is used
11 * lp:~mvo/click/lp1394256-run-user-hooks:
12 - ensures that click user hooks are run for all logged in users when
13 click is used with "--all-users".
14 * lp:~mvo/click/qt5-qmake-cross-armhf:
15 - add qt5-qmake-arm-linux-gnueabihf to chroot (LP: #1393698)
16 * lp:~mvo/click/chroot-15.04-multiarch:
17 - add ubuntu-sdk-libs-tools and oxide-codecs-extra to the chroot
18 * lp:~mvo/click/lp1394256-run-user-hooks-on-remove-too:
19 - Run the click remove user hooks for all logged in users.
20 * click/chroot.py:
21 - use string.format() for chroot TARGET selection
22 * skip 0.4.36 version and go straight to 0.4.37 (LP: #1418086)
23
24 [ Zoltan Balogh ]
25 * lp:~bzoltan/click/vivid-transition_mirrors:
26 - use geoip to guess the most suitable country mirror when creating
27 the click chroot
28
29 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 14 Nov 2014 12:29:14 +0000
30
1click (0.4.35) vivid; urgency=low31click (0.4.35) vivid; urgency=low
232
3 [ Michael Vogt ]33 [ Michael Vogt ]
434
=== modified file 'debian/click.postinst'
--- debian/click.postinst 2014-10-14 09:47:48 +0000
+++ debian/click.postinst 2015-02-13 12:37:00 +0000
@@ -13,7 +13,9 @@
1313
14 # dh-systemd has no support yet for user systemd units14 # dh-systemd has no support yet for user systemd units
15 # so we need to do this manually here15 # so we need to do this manually here
16 systemctl --global enable click-user-hooks.service || true16 if which systemctl >/dev/null 2>&1; then
17 systemctl --global enable click-user-hooks.service || true
18 fi
17fi19fi
1820
19#DEBHELPER#21#DEBHELPER#
2022
=== modified file 'lib/click/user.vala'
--- lib/click/user.vala 2014-09-29 13:23:12 +0000
+++ lib/click/user.vala 2015-02-13 12:37:00 +0000
@@ -33,8 +33,21 @@
33 * symlinks per user.33 * symlinks per user.
34 */34 */
3535
36
36namespace Click {37namespace Click {
3738
39 struct LogindUser {
40 uint32 uid;
41 string name;
42 string ObjectPath;
43 }
44
45 /* the logind dbus interface */
46 [DBus (name = "org.freedesktop.login1.Manager")]
47 interface LogindManager : Object {
48 public abstract LogindUser[] ListUsers () throws IOError;
49 }
50
38/* Pseudo-usernames selected to be invalid as a real username, and alluding51/* Pseudo-usernames selected to be invalid as a real username, and alluding
39 * to group syntaxes used in other systems.52 * to group syntaxes used in other systems.
40 */53 */
@@ -596,6 +609,53 @@
596 if (! is_pseudo_user)609 if (! is_pseudo_user)
597 package_install_hooks (db, package,610 package_install_hooks (db, package,
598 old_version, version, name);611 old_version, version, name);
612
613 // run user hooks for all logged in users
614 if (name == ALL_USERS)
615 run_user_install_hooks_for_all_logged_in_users (package, old_version, version);
616 }
617
618 private string[]
619 get_logged_in_users()
620 {
621 string[] logged_in_users = {};
622 try {
623 LogindManager logind = Bus.get_proxy_sync (
624 BusType.SYSTEM,
625 "org.freedesktop.login1",
626 "/org/freedesktop/login1");
627 var users = logind.ListUsers();
628 foreach (LogindUser user in users)
629 {
630 // FIXME: ideally we would read from /etc/adduser.conf
631 if(user.uid >= 1000 && user.uid <= 30000)
632 {
633 logged_in_users += user.name;
634 }
635 }
636 } catch (Error e) {
637 warning ("Can not connect to logind");
638 }
639 return logged_in_users;
640 }
641
642 private void
643 run_user_install_hooks_for_all_logged_in_users (string package,
644 string? old_version,
645 string version) throws IOError
646 {
647 foreach (string username in get_logged_in_users())
648 package_install_hooks (db, package,
649 old_version, version, username);
650 }
651
652 private void
653 run_user_remove_hooks_for_all_logged_in_users (string package,
654 string old_version) throws IOError
655 {
656 foreach (string username in get_logged_in_users())
657 package_remove_hooks (db, package,
658 old_version, username);
599 }659 }
600660
601 private bool661 private bool
@@ -688,6 +748,10 @@
688748
689 if (! is_pseudo_user)749 if (! is_pseudo_user)
690 package_remove_hooks (db, package, old_version, name);750 package_remove_hooks (db, package, old_version, name);
751
752 // run user hooks for all logged in users
753 if (name == ALL_USERS)
754 run_user_remove_hooks_for_all_logged_in_users (package, old_version);
691 }755 }
692756
693 /**757 /**

Subscribers

People subscribed via source and target branches

to all changes: