<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Colin Watson's blog</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/" rel="alternate"/><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/feeds/all.atom.xml" rel="self"/><id>https://www.chiark.greenend.org.uk/~cjwatson/blog/</id><updated>2026-03-09T12:22:42+00:00</updated><entry><title>Free software activity in February 2026</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2026-02.html" rel="alternate"/><published>2026-03-09T12:22:42+00:00</published><updated>2026-03-09T12:22:42+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2026-03-09:/~cjwatson/blog/activity-2026-02.html</id><summary type="html">&lt;p&gt;Even more pkg_resources wrangling, minor OpenSSH security updates, and a &lt;span class="caps"&gt;BTS&lt;/span&gt; mail-handling&amp;nbsp;tweak.&lt;/p&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all &lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via &lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122765"&gt;openssh: Please remove/replace usage of&amp;nbsp;dh_movetousr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I released bookworm and trixie fixes for &lt;a href="https://bugs.debian.org/1117529"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-61984&lt;/a&gt; and &lt;a href="https://bugs.debian.org/1117530"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-61985&lt;/a&gt;, both allowing code execution via &lt;code&gt;ProxyCommand&lt;/code&gt; in some cases.  The trixie update also included a fix for &lt;a href="https://bugs.debian.org/1080350"&gt;openssh-server: refuses further connections after having handled PerSourceMaxStartups connections&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;bugs.debian.org&amp;nbsp;administration&lt;/h2&gt;
&lt;p&gt;Gioele Barabucci &lt;a href="https://bugs.debian.org/1126848"&gt;reported&lt;/a&gt; that some messages to the bug tracking system generated by the &lt;code&gt;bts&lt;/code&gt; command were being discarded.  While the regression here was on the client side, I found and fixed a typo in our SpamAssassin configuration that was failing to apply a bonus specifically to &lt;code&gt;forwarded&lt;/code&gt; commands, mitigating the&amp;nbsp;problem.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;New upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aiosmtplib&lt;/li&gt;
&lt;li&gt;bitstruct&lt;/li&gt;
&lt;li&gt;diff-cover&lt;/li&gt;
&lt;li&gt;django-q&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;multipart&lt;/li&gt;
&lt;li&gt;poetry (&lt;a href="https://bugs.debian.org/1127062"&gt;adding support for Dulwich &amp;gt;= 0.25&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;poetry-core&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;python-build&lt;/li&gt;
&lt;li&gt;python-certifi&lt;/li&gt;
&lt;li&gt;python-datamodel-code-generator&lt;/li&gt;
&lt;li&gt;python-flatdict&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-maggma&lt;/li&gt;
&lt;li&gt;python-pytokens&lt;/li&gt;
&lt;li&gt;python-scruffy&lt;/li&gt;
&lt;li&gt;python-urllib3 (fixing &lt;a href="https://bugs.debian.org/1122029"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-66471&lt;/a&gt; and a &lt;a href="https://bugs.debian.org/1122743"&gt;chunked decoding bug&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;responses&lt;/li&gt;
&lt;li&gt;yarsync&lt;/li&gt;
&lt;li&gt;zope.component&lt;/li&gt;
&lt;li&gt;zope.deferredimport&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Porting away from the &lt;a href="https://github.com/pypa/setuptools/issues/3085"&gt;deprecated&lt;/a&gt; (and now removed from upstream setuptools) &lt;code&gt;pkg_resources&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083413"&gt;genshi&lt;/a&gt; (&lt;a href="https://github.com/edgewall/genshi/pull/97"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083414"&gt;germinate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083483"&gt;mopidy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083509"&gt;nose2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083553"&gt;pokrok&lt;/a&gt; (&lt;a href="https://github.com/jdidion/pokrok/pull/5"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125854"&gt;pylama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125850"&gt;python-flask-seeder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125819"&gt;python-maggma&lt;/a&gt; (&lt;a href="https://github.com/materialsproject/maggma/pull/1067"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125851"&gt;python-pybadges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083705"&gt;python-scruffy&lt;/a&gt; (&lt;a href="https://github.com/snare/scruffy/pull/33"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125840"&gt;thumbor&lt;/a&gt; (&lt;a href="https://github.com/thumbor/thumbor/pull/1789"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084009"&gt;zope.deprecation&lt;/a&gt; (&lt;a href="https://github.com/zopefoundation/zope.deprecation/pull/27"&gt;contributed upstream&lt;/a&gt; a while ago, but there hasn&amp;#8217;t been an upstream release&amp;nbsp;yet)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1129112"&gt;flask-dance: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: No module named &amp;#8216;pkg_resources&amp;#8217;&lt;/a&gt; (actually fixed by adding a missing dependency to&amp;nbsp;python3-sphinxcontrib.seqdiag)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1127663"&gt;paramiko: autopkgtest regression on i386&lt;/a&gt; (&lt;a href="https://github.com/paramiko/paramiko/pull/2577"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1128776"&gt;poetry: autopkgtest regression on&amp;nbsp;i386&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123190"&gt;python-argh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1127525"&gt;python-django-celery-beat: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: &lt;span class="caps"&gt;FAILED&lt;/span&gt;&amp;nbsp;t/unit/test_models.py::HumanReadableTestCase::test_long_name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126157"&gt;python-maturin: rust-itertools&amp;nbsp;update&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1127528"&gt;python-msrest: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: &lt;span class="caps"&gt;FAILED&lt;/span&gt; tests/asynctests/test_async_client.py::TestServiceClient::test_client_send&lt;/a&gt; (&lt;a href="https://github.com/Azure/msrest-for-python/pull/268"&gt;contributed upstream&lt;/a&gt;, though not very&amp;nbsp;successfully)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123326"&gt;python-typing-inspect&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125283"&gt;opentelemetry-proto: Stop building python3-opentelemetry-proto, taken over by the python-opentelemetry source&amp;nbsp;package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1129211"&gt;python-datamodel-code-generator: Depends: python3-isort (&amp;lt; 8) but 8.0.0-1 is to be installed&lt;/a&gt; (&lt;a href="https://github.com/koxudaxi/datamodel-code-generator/pull/3011"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125025"&gt;python-typeguard: Mark python3-typeguard Multi-Arch:&amp;nbsp;foreign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124771"&gt;wheel: Mark python3-wheel Multi-Arch:&amp;nbsp;foreign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123664"&gt;zope.deferredimport: Please make the build reproducible&lt;/a&gt; (&lt;a href="https://github.com/zopefoundation/zope.deferredimport/pull/19"&gt;contributed upstream&lt;/a&gt;, with a &lt;a href="https://github.com/zopefoundation/zope.deferredimport/pull/22"&gt;follow-up fix&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I added a &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/83"&gt;manual page symlink&lt;/a&gt; to make the documentation for &lt;code&gt;Testsuite: autopkgtest-pkg-pybuild&lt;/code&gt; easier to&amp;nbsp;find.&lt;/p&gt;
&lt;p&gt;I backported python-pytest-unmagic, a more recent version of pytest-django, and a more recent version of django-cte to trixie for use in&amp;nbsp;Debusine.&lt;/p&gt;
&lt;h2&gt;Rust&amp;nbsp;packaging&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124553"&gt;librust-pyo3-ffi-dev: Cannot be installed for foreign&amp;nbsp;architectures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also packaged rust-garde and rust-garde-derive, which are part of the pile of work needed to get the ruff packaging back in shape (which is a project I haven&amp;#8217;t decided if I&amp;#8217;m going to take on for real, but I thought I&amp;#8217;d at least chip away at a bit of&amp;nbsp;it).&lt;/p&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126132"&gt;arch-test: Remove build dependency on binutils-mips64el-linux-gnuabi64&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/pkg-debconf/debconf/-/merge_requests/23"&gt;debconf: Add &lt;span class="caps"&gt;BMP&lt;/span&gt; version of debian-logo&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/20"&gt;openssh: Reorder pam_selinux(7) usage&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/37"&gt;openssh-client: use sysusers.d, drop superflous dependencies&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/38"&gt;openssh: Stop deleting system user on remove/purge&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1128399"&gt;openssh: Do not link against libcrypt on &lt;span class="caps"&gt;GNU&lt;/span&gt;/Hurd&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/installer-team/partman-prep/-/merge_requests/2"&gt;partman-prep: Align PReP descriptions with other partition types&lt;/a&gt;&amp;nbsp;(merged)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124754"&gt;python-better-exceptions&lt;/a&gt; (sponsored upload for Seyed Mohamad Amin&amp;nbsp;Modaresi)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/></entry><entry><title>Free software activity in January 2026</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2026-01.html" rel="alternate"/><published>2026-02-08T19:30:11+00:00</published><updated>2026-02-08T19:30:11+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2026-02-08:/~cjwatson/blog/activity-2026-01.html</id><summary type="html">&lt;p&gt;More Python 3.14 and pkg_resources&amp;nbsp;wrangling.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 80% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian, as well as one direct donation via &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt; (thanks!).  If you
appreciate this sort of work and are at a company that uses Debian, have a
look to see whether you can pay for any of
&lt;a href="https://www.freexian.com/"&gt;Freexian&lt;/a&gt;&amp;#8216;s services; as well as the direct
benefits, that revenue stream helps to keep Debian development sustainable
for me and &lt;a href="https://www.freexian.com/about/team/"&gt;several other lovely
people&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;New upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;django-macaddress (fixing &lt;a href="https://bugs.debian.org/1083367"&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;fsspec (fixing a &lt;a href="https://bugs.debian.org/1123386"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ipyparallel&lt;/li&gt;
&lt;li&gt;pycodestyle&lt;/li&gt;
&lt;li&gt;pyflakes (fixing a &lt;a href="https://bugs.debian.org/1123170"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pyroma&lt;/li&gt;
&lt;li&gt;pytest-golden (fixing a &lt;a href="https://bugs.debian.org/1123149"&gt;regression that broke markdown-callouts&lt;/a&gt;, which I &lt;a href="https://github.com/oprypin/pytest-golden/issues/9"&gt;reported upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1021329"&gt;pytest-runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-auditwheel&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120980"&gt;python-b2sdk&lt;/a&gt; (fixing a &lt;a href="https://bugs.debian.org/1123197"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-certifi&lt;/li&gt;
&lt;li&gt;python-django-imagekit (fixing a &lt;a href="https://bugs.debian.org/1123218"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-flake8 (fixing a &lt;a href="https://bugs.debian.org/1125154"&gt;build failure with a new pyflakes version&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-ibm-cloud-sdk-core (&lt;a href="https://github.com/IBM/python-sdk-core/pull/229"&gt;contributed supporting fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-openapi-core (fixing a &lt;a href="https://bugs.debian.org/1123278"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pdoc (fixing a &lt;a href="https://bugs.debian.org/1123286"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pyfunceble&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-pytokens&lt;/li&gt;
&lt;li&gt;python-weblogo (fixing &lt;a href="https://bugs.debian.org/1083722"&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-wheezy.template&lt;/li&gt;
&lt;li&gt;smart-open&lt;/li&gt;
&lt;li&gt;sphinx-togglebutton&lt;/li&gt;
&lt;li&gt;sqlobject&lt;/li&gt;
&lt;li&gt;supervisor (fixing &lt;a href="https://bugs.debian.org/1083790"&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;vcr.py (fixing a &lt;a href="https://bugs.debian.org/1123365"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.interface (including a fix for a &lt;a href="https://bugs.debian.org/1123258"&gt;Python 3.14 failure in python-klein&lt;/a&gt;, which I &lt;a href="https://github.com/zopefoundation/zope.interface/pull/351"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.testrunner (fixing a &lt;a href="https://bugs.debian.org/1123371"&gt;build failure with Python 3.14&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fixes for Python&amp;nbsp;3.14:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123158"&gt;pdfposter&lt;/a&gt; (&lt;a href="https://gitlab.com/pdftools/pdfposter/-/merge_requests/10"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123159"&gt;pexpect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123162"&gt;poetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123171"&gt;pyhamcrest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122458"&gt;pylint-gitlab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123191"&gt;python-astor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123235"&gt;python-easydev&lt;/a&gt; (&lt;a href="https://github.com/cokelaer/easydev/pull/40"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125124"&gt;python-forbiddenfruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123255"&gt;python-ibm-cloud-sdk-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123527"&gt;python-iniparse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123262"&gt;python-libusb1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123265"&gt;python-marshmallow-dataclass&lt;/a&gt; (&lt;a href="https://github.com/lovasoa/marshmallow_dataclass/pull/286"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123267"&gt;python-marshmallow&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123279"&gt;python-opentracing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123280"&gt;python-opt-einsum-fx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122265"&gt;python-spdx-tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123317"&gt;python-stopit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123335"&gt;rich&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;, also requiring an &lt;a href="https://bugs.debian.org/1125310"&gt;&lt;span class="caps"&gt;NMU&lt;/span&gt; of textual&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123340"&gt;scikit-build-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125127"&gt;seqdiag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123362"&gt;uncertainties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123367"&gt;yarsync&lt;/a&gt; (&lt;a href="https://github.com/ynikitenko/yarsync/pull/19"&gt;contributed upstream&lt;/a&gt;, along with a &lt;a href="https://github.com/ynikitenko/yarsync/pull/20"&gt;supporting fix&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fixes for pytest&amp;nbsp;9:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123169"&gt;pyee&lt;/a&gt; (&lt;a href="https://github.com/jfhbrook/pyee/pull/192"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122936"&gt;python-django-celery-beat&lt;/a&gt; (&lt;a href="https://github.com/celery/django-celery-beat/pull/986"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123282"&gt;python-overrides&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Porting away from the &lt;a href="https://github.com/pypa/setuptools/issues/3085"&gt;deprecated&lt;/a&gt; &lt;code&gt;pkg_resources&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125832"&gt;beaker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125834"&gt;coreapi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125828"&gt;cppy&lt;/a&gt; (no-change rebuild to remove a spurious&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083356"&gt;depthcharge-tools&lt;/a&gt; (&lt;a href="https://github.com/alpernebbi/depthcharge-tools/pull/13"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083380"&gt;errbot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083405"&gt;gajim-antispam&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083406"&gt;gajim-lengthnotifier&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083407"&gt;gajim-openpgp&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083409"&gt;gajim-pgp&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083410"&gt;gajim-triggers&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083426"&gt;grapefruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083436"&gt;impacket&lt;/a&gt; (&lt;a href="https://github.com/fortra/impacket/pull/2102"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083447"&gt;jupyter-packaging&lt;/a&gt; (no-change rebuild to remove a spurious&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083452"&gt;khal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083545"&gt;pipenv&lt;/a&gt; (no-change rebuild to remove a spurious&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083585"&gt;pyroma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083591"&gt;pytest-runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083590"&gt;pytest-tornado&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083596"&gt;python-airr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083595"&gt;python-aptly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083632"&gt;python-docxcompose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083647"&gt;python-hatch-mypyc&lt;/a&gt; (no-change rebuild to remove a spurious&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083692"&gt;python-pyfunceble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083713"&gt;python-stopit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125822"&gt;python-ttfautohint-py&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083770"&gt;setuptools-scm&lt;/a&gt; (no-change rebuild to remove a spurious&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083773"&gt;slimit&lt;/a&gt; (removed unused&amp;nbsp;dependency)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125786"&gt;sphinx-togglebutton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083805"&gt;topplot&lt;/a&gt; (&lt;a href="https://gitlab.com/eBardie/topplot/-/merge_requests/26"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1083981"&gt;valinor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126195"&gt;audioop-lts: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: ValueError: major component is&amp;nbsp;required&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125984"&gt;basemap: Tries to access Internet during&amp;nbsp;build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126198"&gt;celery: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: &lt;span class="caps"&gt;FAILED&lt;/span&gt; t/unit/backends/test_mongodb.py::test_MongoBackend::test_store_result&lt;/a&gt; (&lt;a href="https://github.com/celery/celery/pull/10074"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124154"&gt;django-allauth: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: AttributeError: module &amp;#8216;fido2.features&amp;#8217; has no attribute&amp;nbsp;&amp;#8216;webauthn_json_mapping&amp;#8217;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/django-tastypie/-/commit/fd99cddda3a775ddeaf6633720527f5d05f36f92"&gt;django-tastypie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123830"&gt;m2crypto: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; on armhf: AssertionError: 64 !=&amp;nbsp;32&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/magicgui/-/commit/6f650f9d8f1c8ac06f724635a945bd4418dd1eb4"&gt;magicgui&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123434"&gt;pytest-mypy-testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-asttokens/-/commit/2e704d507d71e88efba01cb8ef6595f48775834f"&gt;python-asttokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126227"&gt;python-distutils-extra: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dpkg-buildpackage: error: debian/rules binary subprocess failed with exit status&amp;nbsp;2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126229"&gt;python-django-extensions: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: &lt;span class="caps"&gt;FAILED&lt;/span&gt;&amp;nbsp;tests/templatetags/test_highlighting.py::HighlightTagTests::test_should_highlight_python_syntax_with_name&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1126231"&gt;python-gmpy2: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: ModuleNotFoundError: No module named&amp;nbsp;&amp;#8216;gmpy2&amp;#8217;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123832"&gt;python-jpype: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; on i386, armhf: test/jpypetest/test_buffer.py:394: TypeError&lt;/a&gt; (&lt;a href="https://github.com/jpype-project/jpype/pull/1336"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124629"&gt;python-maturin: Upcoming target-lexicon&amp;nbsp;update&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123363"&gt;traitlets&lt;/a&gt; (&lt;a href="https://github.com/ipython/traitlets/pull/931"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125393"&gt;unattended-upgrades: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: F824 &lt;code&gt;global logged_msgs&lt;/code&gt; is unused: name is never assigned in scope&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I investigated several more build failures and suggested removing the packages in&amp;nbsp;question:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123093"&gt;aiozmq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123152"&gt;mkdocstrings-python-legacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123231"&gt;python-djantic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122673"&gt;magicgui: Directly Depends and Build-Depends on&amp;nbsp;dbus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1125092"&gt;python3-netsnmpagent: Rebuild for&amp;nbsp;libsnmp45&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;p&gt;Alejandro Colomar reported that &lt;code&gt;man(1)&lt;/code&gt; ignored the &lt;code&gt;MANWIDTH&lt;/code&gt; environment variable in some circumstances.  I investigated this and &lt;a href="https://gitlab.com/man-db/man-db/-/commit/6a0b49f1cd5cf30539882dbc77436e12f6697809"&gt;fixed it upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I contributed an &lt;a href="https://code.launchpad.net/~cjwatson/ubuntu-dev-tools/+git/ubuntu-dev-tools/+merge/497980"&gt;ubuntu-dev-tools patch to stop recommending &lt;code&gt;sudo&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://salsa.debian.org/salsa-ci-team/pipeline/-/merge_requests/697"&gt;added forky support&lt;/a&gt; to the images used in Salsa &lt;span class="caps"&gt;CI&lt;/span&gt;&amp;nbsp;pipelines.&lt;/p&gt;
&lt;p&gt;I began working on getting a release candidate of groff 1.24.0 into experimental, though haven&amp;#8217;t finished that&amp;nbsp;yet.&lt;/p&gt;
&lt;p&gt;I worked on some lower-priority security updates for&amp;nbsp;OpenSSH.&lt;/p&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/installer-team/netcfg/-/merge_requests/20"&gt;netcfg: Support SSIDs with /, write correct wifi to /etc/network/interfaces&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124970"&gt;openssh: [&lt;span class="caps"&gt;INTL&lt;/span&gt;:zh] Chinese debconf templates translations&lt;/a&gt;&amp;nbsp;(merged)&lt;/li&gt;
&lt;li&gt;pymongo (sponsored upload for Aryan&amp;nbsp;Karamtoth)&lt;/li&gt;
&lt;li&gt;python-streamz (sponsored upload for Aryan&amp;nbsp;Karamtoth)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120121"&gt;smart-open: Please make the build reproducible&lt;/a&gt; (fixed in a different&amp;nbsp;way)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124510"&gt;uvloop: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; on riscv64 with Python 3.14 as supported&lt;/a&gt;&amp;nbsp;(uploaded)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/></entry><entry><title>Free software activity in December 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-12.html" rel="alternate"/><published>2026-01-05T13:08:53+00:00</published><updated>2026-01-05T13:08:53+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2026-01-05:/~cjwatson/blog/activity-2025-12.html</id><summary type="html">&lt;p&gt;Mostly chasing Python 3.14&amp;nbsp;problems.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 95% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aiosmtplib&lt;/li&gt;
&lt;li&gt;astroid (fixing a &lt;a href="https://bugs.debian.org/1123098"&gt;build failure with Python
  3.14&lt;/a&gt;, as I wrote about recently in
  &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debusine-transitions.html"&gt;Preparing a transition in Debusine&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;billiard (fixing a &lt;a href="https://bugs.debian.org/1121668"&gt;syntax warning with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;celery (&lt;a href="https://github.com/celery/celery/pull/10033"&gt;contributed follow-up fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;cloudpickle (fixing a &lt;a href="https://bugs.debian.org/1121743"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;csvkit&lt;/li&gt;
&lt;li&gt;deepdiff (fixing a &lt;a href="https://bugs.debian.org/1123114"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;django-auditlog&lt;/li&gt;
&lt;li&gt;django-phonenumber-field&lt;/li&gt;
&lt;li&gt;flake8-builtins&lt;/li&gt;
&lt;li&gt;flufl.lock&lt;/li&gt;
&lt;li&gt;kombu&lt;/li&gt;
&lt;li&gt;peewee&lt;/li&gt;
&lt;li&gt;psycopg2&lt;/li&gt;
&lt;li&gt;pydantic-extra-types&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117224"&gt;pygments&lt;/a&gt; (prepared transition in
  Debusine with diff-cover, pydata-sphinx-theme, pymdown-extensions,
  python-readme-renderer, and python-stack-data; &lt;a href="https://github.com/alexmojaki/stack_data/pull/63"&gt;contributed
  python-stack-data fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pylint (fixing a &lt;a href="https://bugs.debian.org/1123172"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pymdown-extensions&lt;/li&gt;
&lt;li&gt;python-aiojobs (fixing a &lt;a href="https://bugs.debian.org/1114291"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-aiostream&lt;/li&gt;
&lt;li&gt;python-asttokens (fixing a &lt;a href="https://bugs.debian.org/1124194"&gt;build failure with astroid
  4&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-auditwheel&lt;/li&gt;
&lt;li&gt;python-blockbuster&lt;/li&gt;
&lt;li&gt;python-boolean.py&lt;/li&gt;
&lt;li&gt;python-confluent-kafka&lt;/li&gt;
&lt;li&gt;python-django-crispy-forms&lt;/li&gt;
&lt;li&gt;python-django-pgbulk&lt;/li&gt;
&lt;li&gt;python-django-pgtransaction&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger (fixing a &lt;a href="https://bugs.debian.org/1122461"&gt;build failure with
  mkdocstrings-python-handlers &amp;gt;= 2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-evalidate&lt;/li&gt;
&lt;li&gt;python-exchangelib (fixing a &lt;a href="https://bugs.debian.org/1123237"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-lsp-server&lt;/li&gt;
&lt;li&gt;python-lz4&lt;/li&gt;
&lt;li&gt;python-mashumaro (fixing many build failures in other packages with Python&amp;nbsp;3.14)&lt;/li&gt;
&lt;li&gt;python-moto&lt;/li&gt;
&lt;li&gt;python-persistent&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-roman&lt;/li&gt;
&lt;li&gt;python-rx (fixing a &lt;a href="https://bugs.debian.org/1123306"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-telethon&lt;/li&gt;
&lt;li&gt;python-uvicorn (fixing a &lt;a href="https://bugs.debian.org/1122099"&gt;test failure with current
  uvloop&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-wheezy.template&lt;/li&gt;
&lt;li&gt;python-wslink&lt;/li&gt;
&lt;li&gt;rpds-py&lt;/li&gt;
&lt;li&gt;sphinx-autoapi&lt;/li&gt;
&lt;li&gt;sqlparse&lt;/li&gt;
&lt;li&gt;zope.testing (fixing a &lt;a href="https://bugs.debian.org/1123370"&gt;build failure with Python
  3.14&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python 3.14 is now a supported version in unstable, and we&amp;#8217;re working to get
that into testing.  As usual this is a pretty arduous effort because it
requires going round and fixing lots of odds and ends across the whole
ecosystem.  We can deal with a fair number of problems by keeping up with
upstream (see above), but there tends to be a long tail of packages whose
upstreams are less active and where we need to chase them, or where problems
only show up in Debian for one reason or another.  I spent a lot of time
working on&amp;nbsp;this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/actdiag/-/commit/f566f601862a54b96c92d66874da9440351bf2a4"&gt;actdiag&amp;#8217;s autopkgtests failed when there are multiple supported Python&amp;nbsp;versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123143"&gt;khard: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dh_auto_test: error: pybuild &amp;#8212;test -i python{version} -p
  &amp;#8220;3.14 3.13&amp;#8221; returned exit code 13&lt;/a&gt;
  (&lt;a href="https://github.com/lucc/khard/pull/348"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123433"&gt;pydantic-settings: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: example.py: error: unrecognized arguments:
  &amp;#8212;bad-arg&lt;/a&gt; (&lt;a href="https://github.com/pydantic/pydantic-settings/issues/733"&gt;forwarded
  upstream&lt;/a&gt; and
  cherry-picked their&amp;nbsp;fix)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123166"&gt;pydantic: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dh_auto_test: error: pybuild &amp;#8212;test &amp;#8212;test-pytest -i
  python{version} -p &amp;#8220;3.14 3.13&amp;#8221; returned exit code&amp;nbsp;13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121999"&gt;pygame: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with Python 3.14: sys.getrefcount()&amp;nbsp;AssertionError&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123194"&gt;python-auditwheel: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dh_auto_test: error: pybuild &amp;#8212;test
  &amp;#8212;test-pytest -i python{version} -p &amp;#8220;3.14 3.13&amp;#8221; returned exit code
  13&lt;/a&gt; (&lt;a href="https://github.com/pypa/auditwheel/pull/661"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121820"&gt;python-charset-normalizer could silently build without support for some
  supported Python&amp;nbsp;versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117901"&gt;python-confluent-kafka: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with Python 3.14: Segmentation fault in
  test_create_topics_api&lt;/a&gt; (&lt;a href="https://github.com/confluentinc/confluent-kafka-python/issues/2146"&gt;forwarded
  upstream&lt;/a&gt;
  and
  &lt;a href="https://github.com/confluentinc/confluent-kafka-python/pull/2151"&gt;fixed&lt;/a&gt;
  after a debugging hint from&amp;nbsp;them)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122185"&gt;python-django: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with Python 3.14&lt;/a&gt;
  (also fixing many build failures in other&amp;nbsp;packages)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122076"&gt;python-memray: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with Python 3.14: Segmentation
  fault&lt;/a&gt; (some initial debugging; &lt;a href="https://github.com/bloomberg/memray/issues/863"&gt;upstream
  has since got a lot
  further&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123319"&gt;python-telethon: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dh_auto_test: error: pybuild &amp;#8212;test
  &amp;#8212;test-pytest -i python{version} -p &amp;#8220;3.14 3.13&amp;#8221; returned exit code
  13&lt;/a&gt; (&lt;a href="https://github.com/LonamiWebs/Telethon/pull/4722"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123325"&gt;python-typing-extensions: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: dh_auto_test: error: pybuild &amp;#8212;test -i
  python{version} -p &amp;#8220;3.14 3.13&amp;#8221; returned exit code&amp;nbsp;13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122023"&gt;python-wheezy.template: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with Python
  3.14&lt;/a&gt; (&lt;a href="https://github.com/akornatskyy/wheezy.template/pull/117"&gt;contributed
  upstream&lt;/a&gt;,
  although they opted for doing it a bit&amp;nbsp;differently)&lt;/li&gt;
&lt;li&gt;storm (&lt;a href="https://launchpad.net/storm/trunk/1.1"&gt;made an upstream release with Python 3.14
  support&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122044"&gt;twisted: Autopkgtests fail with Python 3.14: builtins.RuntimeError: There
  is no current event loop in thread
  &amp;#8216;MainThread&amp;#8217;&lt;/a&gt; (&lt;a href="https://github.com/twisted/twisted/issues/12549"&gt;forwarded
  upstream&lt;/a&gt; and
  cherry-picked their&amp;nbsp;fix)&lt;/li&gt;
&lt;li&gt;zope.proxy and zope.security had a bootstrapping loop when adding new
  supported Python versions; I &lt;a href="https://salsa.debian.org/python-team/packages/zope.proxy/-/commit/6b8071330546d58da5465a75deb2a152172cf13f"&gt;broke this
  loop&lt;/a&gt;
  so it shouldn&amp;#8217;t bother us again in the&amp;nbsp;future.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fixes for pytest&amp;nbsp;9:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123105"&gt;celery&lt;/a&gt; (&lt;a href="https://github.com/celery/celery/pull/10032"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122932"&gt;pytest-pylint&lt;/a&gt; (&lt;a href="https://github.com/carsongee/pytest-pylint/pull/196"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123239"&gt;python-expandvars&lt;/a&gt; (&lt;a href="https://github.com/sayanarijit/expandvars/pull/74"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124083"&gt;python-inline-snapshot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I filed &lt;a href="https://bugs.debian.org/1121735"&gt;lintian: Report Python egg-info
files/directories&lt;/a&gt; to help us track the
&lt;a href="https://wiki.debian.org/Python/PybuildPluginPyproject"&gt;migration to
pybuild-plugin-pyproject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I did some work on dh-python: &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/64"&gt;Normalize names in pydist
lookups&lt;/a&gt;
and &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/65"&gt;pyproject plugin: Support
headers&lt;/a&gt;
(the latter of which allowed converting python-persistent and zope.proxy to
pybuild-plugin-pyproject, although it needed a &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/66"&gt;follow-up
fix&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix several other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122304"&gt;dpath-python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120247"&gt;flask-bcrypt: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: E ValueError: password cannot be longer than 72
  bytes, truncate manually if necessary (e.g.&amp;nbsp;my_password[:72])&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123187"&gt;python-aiosmtpd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122302"&gt;python-aiostream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-auditwheel on i386 (&lt;a href="https://github.com/pypa/auditwheel/pull/640"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-auditwheel on riscv64 (&lt;a href="https://github.com/pypa/auditwheel/pull/662"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-bcrypt: &lt;a href="https://salsa.debian.org/python-team/packages/python-bcrypt/-/commit/4a2bdbde672889c6cddacd49cd6569d0c372e780"&gt;Accept pyo3&amp;nbsp;0.27&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123215"&gt;python-django-crum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123217"&gt;python-django-guid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123449"&gt;python-inline-snapshot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123260"&gt;python-laspy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123270"&gt;python-mnemonic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-ncls on 32-bit architectures (&lt;a href="https://github.com/pyranges/ncls/pull/67"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122323"&gt;python-papermill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124201"&gt;python-phonenumbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123290"&gt;python-pluggy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-pycddl: &lt;a href="https://salsa.debian.org/python-team/packages/python-pycddl/-/commit/a80f0ccb611998b7b8a3c0cee94b0184cfba4ab8"&gt;Accept pyo3&amp;nbsp;0.27&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-sphinx-autodoc2 (&lt;a href="https://github.com/sphinx-extensions2/sphinx-autodoc2/pull/93"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123318"&gt;python-structlog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1124205"&gt;python-wikkid: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: AttributeError: &amp;#8216;TestBaseParent&amp;#8217; object has no
  attribute &amp;#8216;assertEquals&amp;#8217;&lt;/a&gt; (&lt;a href="https://github.com/wikkid-team/wikkid/pull/59"&gt;contributed
  follow-up fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122311"&gt;python-wslink&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122147"&gt;python-bcrypt: ValueError: password cannot be longer than 72 bytes,
  truncate manually if&amp;nbsp;necessary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122703"&gt;python-notify2: Directly Build-Depends on&amp;nbsp;dbus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122261"&gt;python-packaging: Mark python3-packaging Multi-Arch:&amp;nbsp;foreign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115482"&gt;python-pyproject-parser: python3-pyproject-parser needs a dependency on&amp;nbsp;python3-consolekit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1123782"&gt;sphinx: Please backport upstream&amp;#8217;s fix on&amp;nbsp;roman-numerals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122798"&gt;db1-compat: Please remove/replace usage of&amp;nbsp;dh_movetousr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debian/debmirror/-/commit/fe4e902c90b637b1b91d33d9d246ae44bde65e85"&gt;debmirror: Refresh mirror_size&amp;nbsp;documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121570"&gt;groff: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;&amp;nbsp;randomly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3900"&gt;openssh: Misleading verbose output for local-to-local or standard
  remote-to-remote
  copies&lt;/a&gt; (upstreamed an
  improved version of a patch we&amp;#8217;ve been carrying since&amp;nbsp;2008)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1122768"&gt;pcmciautils: Please remove/replace usage of&amp;nbsp;dh_movetousr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/36"&gt;openssh: Fix binary name in
  ssh-askpass-gnome.desktop&lt;/a&gt;
  (still in&amp;nbsp;discussion)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-lsp-server/-/merge_requests/1"&gt;python-lsp-server: Increase tests timeout&amp;nbsp;further&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/rope/-/merge_requests/4"&gt;rope: New upstream version
  1.14.0&lt;/a&gt;
  (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debian/trn4/-/merge_requests/4"&gt;trn4: Update/add Catalan po-debconf
  translation&lt;/a&gt;&amp;nbsp;(merged)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/></entry><entry><title>Preparing a transition in Debusine</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debusine-transitions.html" rel="alternate"/><published>2025-12-18T13:21:19+00:00</published><updated>2025-12-18T13:21:19+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-12-18:/~cjwatson/blog/debusine-transitions.html</id><summary type="html">&lt;p&gt;A walk-through of preparing changes to multiple packages using&amp;nbsp;Debusine.&lt;/p&gt;</summary><content type="html">&lt;p&gt;We announced a public beta of
&lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;Debusine&lt;/a&gt; repositories
recently (&lt;a href="https://www.freexian.com/blog/debusine-repositories-beta/"&gt;Freexian
blog&lt;/a&gt;,
&lt;a href="https://lists.debian.org/debian-devel-announce/2025/12/msg00003.html"&gt;debian-devel-announce&lt;/a&gt;).
One thing I&amp;#8217;m very keen on is being able to use these to prepare
&amp;#8220;transitions&amp;#8221;: changes to multiple packages that need to be prepared
together in order to land in testing.  As I said in my &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-398-using-debusine-to-pre-test-your-unstable-uploads.av1.webm"&gt;DebConf25
talk&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have distribution-wide &lt;span class="caps"&gt;CI&lt;/span&gt; in unstable, but there&amp;#8217;s only one of it and
it&amp;#8217;s shared between all of us.  As a result it&amp;#8217;s very possible to get into
tangles when multiple people are working on related things at the same
time, and we only avoid that as much as we do by careful coordination such
as transition bugs.  Experimental helps, but again, there&amp;#8217;s only one of it
and setting up another one is far from&amp;nbsp;trivial.&lt;/p&gt;
&lt;p&gt;So, what we want is a system where you can run experiments on possible
Debian changes at a large scale without a high setup cost and without fear
of breaking things for other people.  And then, if it all works, push the
whole lot into&amp;nbsp;Debian.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Time to practice what I&amp;nbsp;preach.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;The setup process is documented on the &lt;a href="https://wiki.debian.org/DebusineDebianNet#Repositories"&gt;Debian
wiki&lt;/a&gt;.  You need to
decide whether you&amp;#8217;re working on a short-lived experiment, in which case
you&amp;#8217;ll run the &lt;code&gt;create-experiment&lt;/code&gt; workflow and your workspace will expire
after 60 days of inactivity, or something that you expect to keep around for
longer, in which case you&amp;#8217;ll run the &lt;code&gt;create-repository&lt;/code&gt; workflow.  Either
one of those will create a new workspace for you.  Then, in that workspace,
you run &lt;code&gt;debusine archive suite create&lt;/code&gt; for whichever suites you want to
use.  For the case of a transition that you plan to land in unstable, you&amp;#8217;ll
most likely use &lt;code&gt;create-experiment&lt;/code&gt; and then create a single suite with the
pattern &lt;code&gt;sid-&amp;lt;name&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The situation I was dealing with here was moving to
&lt;a href="https://pylint.readthedocs.io/en/stable/"&gt;Pylint&lt;/a&gt; 4.  Tests showed that we
needed this as part of adding Python 3.14 as a supported Python version, and
I knew that I was going to need newer upstream versions of the &lt;code&gt;astroid&lt;/code&gt; and
&lt;code&gt;pylint&lt;/code&gt; packages.  However, I wasn&amp;#8217;t quite sure what the fallout of a new
major version of &lt;code&gt;pylint&lt;/code&gt; was going to be.  Fortunately, the Debian Python
ecosystem has pretty good autopkgtest coverage, so I thought I&amp;#8217;d see what
Debusine said about it.  I created an experiment called &lt;code&gt;cjwatson-pylint&lt;/code&gt;
(resulting in
&lt;code&gt;https://debusine.debian.net/debian/developers-cjwatson-pylint/&lt;/code&gt; - I&amp;#8217;m not
making that a proper link since it will expire in a couple of months) and a
&lt;code&gt;sid-pylint&lt;/code&gt; suite in&amp;nbsp;it.&lt;/p&gt;
&lt;h2&gt;Iteration&lt;/h2&gt;
&lt;p&gt;From this starting point, the basic cycle involved uploading each package
like this for each package I&amp;#8217;d&amp;nbsp;prepared:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;dput&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;debusine_workspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;developers-cjwatson-pylint&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;debusine_workflow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;publish-to-sid-pylint&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;debusine.debian.net&lt;span class="w"&gt; &lt;/span&gt;foo.changes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I could have made a new &lt;code&gt;dput-ng&lt;/code&gt; profile to cut down on typing, but it
wasn&amp;#8217;t worth it&amp;nbsp;here.&lt;/p&gt;
&lt;p&gt;Then I looked at the workflow results, figured out which other packages I
needed to fix based on those, and repeated until the whole set looked
coherent.  Debusine automatically built each upload against whatever else
was currently in the repository, as you&amp;#8217;d&amp;nbsp;expect.&lt;/p&gt;
&lt;p&gt;I should probably have used version numbers with tilde suffixes (e.g.
&lt;code&gt;4.0.2-1~test1&lt;/code&gt;) in case I needed to correct anything, but fortunately that
was mostly unnecessary.  I did at least run initial test-builds locally of
just the individual packages I was directly changing to make sure that they
weren&amp;#8217;t too egregiously broken, just because I usually find it quicker to
iterate that&amp;nbsp;way.&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t take screenshots as I was going along, but here&amp;#8217;s what the list of
top-level
&lt;a href="https://freexian-team.pages.debian.net/debusine/explanation/concepts.html#workflows"&gt;workflows&lt;/a&gt;
in my workspace looked like by the&amp;nbsp;end:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Workflows" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/debusine-transitions-workflows.png"&gt;&lt;/p&gt;
&lt;p&gt;You can see that not all of the workflows are successful.  This is because
we currently just show everything in every workflow; we don&amp;#8217;t consider
whether a task was retried and succeeded on the second try, or whether
there&amp;#8217;s now a newer version of a reverse-dependency so tests of the older
version should be disregarded, and so on.  More fundamentally, you have to
look through each individual workflow, which is a bit of a pain: we plan to
add a dashboard that shows you the current state of a suite as a whole
rather than the current workflow-oriented view, but we haven&amp;#8217;t started on
that&amp;nbsp;yet.&lt;/p&gt;
&lt;p&gt;Drilling down into one of these workflows, it looks something like&amp;nbsp;this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="astroid workflow" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/debusine-transitions-astroid.png"&gt;&lt;/p&gt;
&lt;p&gt;This was the first package I uploaded.  The first pass of failures told me
about &lt;code&gt;pylint&lt;/code&gt; (expected), &lt;code&gt;pylint-flask&lt;/code&gt; (an obvious consequence), and
&lt;code&gt;python-sphinx-autodoc2&lt;/code&gt; and &lt;code&gt;sphinx-autoapi&lt;/code&gt; (surprises).  The slightly odd
pattern of failures and errors is because I retried a few things, and we
sometimes report retries in a slightly strange way, especially when there
are workflows involved that might not be able to resolve their input
parameters any&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;The next level&amp;nbsp;was:&lt;/p&gt;
&lt;p&gt;&lt;img alt="pylint workflow" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/debusine-transitions-pylint.png"&gt;&lt;/p&gt;
&lt;p&gt;Again, there were some retries involved here, and also some cases where
packages were already failing in unstable so the failures weren&amp;#8217;t the fault
of my change; for now I had to go through and analyze these by hand, but
we&amp;#8217;ll soon have regression tracking to compare with reference runs and show
you where things have got better or&amp;nbsp;worse.&lt;/p&gt;
&lt;p&gt;After excluding those, that left &lt;code&gt;pytest-pylint&lt;/code&gt; (not caused by my changes,
but I fixed it anyway in unstable to clear out some noise) and &lt;code&gt;spyder&lt;/code&gt;.
I&amp;#8217;d seen people talking about &lt;code&gt;spyder&lt;/code&gt; on #debian-python recently, so after
a bit of conversation there I sponsored a &lt;code&gt;rope&lt;/code&gt; upload by Aeliton Silva,
upgraded &lt;code&gt;python-lsp-server&lt;/code&gt;, and patched &lt;code&gt;spyder&lt;/code&gt;.  All those went into my
repository too, exposing a couple more tests I&amp;#8217;d forgotten in &lt;code&gt;spyder&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once I was satisfied with the results, I uploaded everything to unstable.
The next day, I looked through the tracker as usual starting from
&lt;a href="https://tracker.debian.org/pkg/astroid"&gt;astroid&lt;/a&gt;, and while there are some
test failures showing up right now it looks as though they should all clear
out as pieces migrate to testing.&amp;nbsp;Success!&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;We still have some way to go before this is a completely smooth experience
that I&amp;#8217;d be prepared to say that every developer can and should be using;
there are all sorts of fit-and-finish issues that I can easily see here.
Still, I do think we&amp;#8217;re at the point where a tolerant developer can use this
to deal with the common case of a mid-sized transition, and get more out of
it than they put&amp;nbsp;in.&lt;/p&gt;
&lt;p&gt;Without Debusine, either I&amp;#8217;d have had to put much more effort into searching
for and testing reverse-dependencies myself, or (more likely, let&amp;#8217;s face it)
I&amp;#8217;d have just dumped things into unstable and sorted them out afterwards,
resulting in potentially delaying other people&amp;#8217;s work.  This way, everything
was done with as little disruption as&amp;nbsp;possible.&lt;/p&gt;
&lt;p&gt;This works best when the packages likely to be involved have reasonably good
&lt;a href="https://wiki.debian.org/autopkgtest"&gt;autopkgtest&lt;/a&gt; coverage (even if the
tests themselves are relatively basic).  This is an &lt;a href="https://trends.debian.net/#test-suite"&gt;increasingly good
bet&lt;/a&gt; in Debian, but we have plans to
add installability comparisons (similar to &lt;a href="https://www.debian.org/devel/testing"&gt;how Debian&amp;#8217;s testing suite
works&lt;/a&gt;) as well as optional rebuild&amp;nbsp;testing.&lt;/p&gt;
&lt;p&gt;If this has got you interested, please &lt;a href="https://wiki.debian.org/DebusineDebianNet"&gt;try it out for
yourself&lt;/a&gt; and &lt;a href="https://wiki.debian.org/DebusineDebianNet#Where_to_get_help.3F"&gt;let us know how it
goes&lt;/a&gt;!&lt;/p&gt;</content><category term="debusine"/><category term="debusine"/><category term="freexian"/><category term="planet-debian"/></entry><entry><title>Free software activity in November 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-11.html" rel="alternate"/><published>2025-12-04T17:55:59+00:00</published><updated>2025-12-04T17:55:59+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-12-04:/~cjwatson/blog/activity-2025-11.html</id><summary type="html">&lt;p&gt;Beginning preparation for OpenSSH &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; split, but otherwise a fairly routine&amp;nbsp;month.&lt;/p&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  I had a bit less time than usual, because Freexian collaborators
gathered in Marseille this month for our yearly sprint, doing some planning
for next&amp;nbsp;year.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I began preparing for the second stage of the &lt;a href="https://lists.debian.org/debian-devel/2024/04/msg00044.html"&gt;&lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; key exchange package
split&lt;/a&gt; (some
details have changed since that message).  It seems that we&amp;#8217;ll need to wait
until Ubuntu 26.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; has been released, but that&amp;#8217;s close enough that it&amp;#8217;s
worth making sure we&amp;#8217;re ready.  This month I just did some packaging
cleanups that would otherwise have been annoying to copy, such as removing
support for direct upgrades from pre-bookworm.  I&amp;#8217;m considering some other
package rearrangements to make the split easier to manage, but haven&amp;#8217;t made
any decisions here&amp;nbsp;yet.&lt;/p&gt;
&lt;p&gt;This also led me to start on a long-overdue bug triage pass, mainly
consisting of applying usertags to lots of our open bugs to sort them by
which program they apply to, and also closing a few that have been fixed,
since some bugs will eventually need to be reassigned to &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; packages
and it would be helpful to make them easier to find.  At the time of
writing, about 30% of the bug list remains to be categorized this&amp;nbsp;way.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aioftp&lt;/li&gt;
&lt;li&gt;basemap (fixing &lt;a href="https://bugs.debian.org/1119728"&gt;Cython 3.1
  compatibility&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;billiard&lt;/li&gt;
&lt;li&gt;black&lt;/li&gt;
&lt;li&gt;django-phonenumber-field&lt;/li&gt;
&lt;li&gt;flask-security&lt;/li&gt;
&lt;li&gt;flufl.i18n&lt;/li&gt;
&lt;li&gt;langtable&lt;/li&gt;
&lt;li&gt;mariadb-connector-python&lt;/li&gt;
&lt;li&gt;peewee (fixing &lt;a href="https://bugs.debian.org/1119757"&gt;Cython 3.1
  compatibility&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pylsqpack&lt;/li&gt;
&lt;li&gt;pymongo&lt;/li&gt;
&lt;li&gt;pymssql&lt;/li&gt;
&lt;li&gt;pyodbc&lt;/li&gt;
&lt;li&gt;python-auditwheel (&lt;a href="https://github.com/pypa/auditwheel/pull/640"&gt;contributed follow-up fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-avro&lt;/li&gt;
&lt;li&gt;python-bleach&lt;/li&gt;
&lt;li&gt;python-btrees&lt;/li&gt;
&lt;li&gt;python-certifi&lt;/li&gt;
&lt;li&gt;python-charset-normalizer&lt;/li&gt;
&lt;li&gt;python-colorlog&lt;/li&gt;
&lt;li&gt;python-django-channels&lt;/li&gt;
&lt;li&gt;python-django-constance&lt;/li&gt;
&lt;li&gt;python-django-contact-form&lt;/li&gt;
&lt;li&gt;python-django-hashids&lt;/li&gt;
&lt;li&gt;python-djvulibre (fixing &lt;a href="https://bugs.debian.org/1119766"&gt;Cython 3.1
  compatibility&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-evalidate&lt;/li&gt;
&lt;li&gt;python-legacy-cgi&lt;/li&gt;
&lt;li&gt;python-openstep-plist (fixing &lt;a href="https://bugs.debian.org/1119767"&gt;Cython 3.1
  compatibility&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-pytokens&lt;/li&gt;
&lt;li&gt;python-tblib&lt;/li&gt;
&lt;li&gt;python-webargs&lt;/li&gt;
&lt;li&gt;pyupgrade&lt;/li&gt;
&lt;li&gt;sqlfluff&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;ttconv&lt;/li&gt;
&lt;li&gt;wcwidth&lt;/li&gt;
&lt;li&gt;zope.hookable&lt;/li&gt;
&lt;li&gt;zope.i18nmessageid (removing &lt;a href="https://bugs.debian.org/1084014"&gt;run-time dependency on
  setuptools&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.interface&lt;/li&gt;
&lt;li&gt;zope.proxy&lt;/li&gt;
&lt;li&gt;zope.security (removing &lt;a href="https://bugs.debian.org/1084018"&gt;run-time dependency on
  setuptools&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.sqlalchemy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1120507"&gt;django-pgtransaction&lt;/a&gt; and
backported it to trixie, since we plan to use it in Debusine; and I adopted
python-certifi for the Python&amp;nbsp;team.&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix several other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1119744"&gt;kivy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120242"&gt;mypy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114284"&gt;pytest-mypy-testing&lt;/a&gt; (&lt;a href="https://github.com/davidfritzsche/pytest-mypy-testing/pull/57"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-cytoolz/-/commit/52856c4c1d1bc9fab0241e4c1b0d20d75bdaa99a"&gt;python-cytoolz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120725"&gt;python-discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120469"&gt;python-ncls&lt;/a&gt;, fixing some failures in&amp;nbsp;pyranges&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121095"&gt;pyxdg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114415"&gt;traitlets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1120228"&gt;twine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed a couple of other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1119801"&gt;pmix: B-D on python3-all-dev, but not built for all supported Python3&amp;nbsp;versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1064621"&gt;python-certifi: Package not compatible with&amp;nbsp;multiarch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087524"&gt;cdebconf: Move to&amp;nbsp;/usr/lib/apt/apt-extracttemplates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debian/devscripts/-/merge_requests/588"&gt;devscripts: Restore dpkg-dev&amp;nbsp;dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121577"&gt;groff: Missing information about some utilities in the &amp;#8220;contrib&amp;#8221;&amp;nbsp;directory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1119914"&gt;base-passwd: French translation&lt;/a&gt; (merged
  and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/installer-team/cdebconf/-/merge_requests/23"&gt;cdebconf: Consider using the standard dh sequence in
  d/rules&lt;/a&gt;
  (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/430151"&gt;cdebconf: Multiple select is not right aligned in
  Hebrew&lt;/a&gt; (patch fails to build; asked
  reporter for an&amp;nbsp;update)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1078936"&gt;cdebconf: Allow building without
  libglib2.0-dev&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1121035"&gt;pydantic-core&lt;/a&gt; (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;pymongo (sponsored adoption by Aryan&amp;nbsp;Karamtoth)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/maturin/-/merge_requests/1"&gt;python-maturin: Add missing build
  dependencies&lt;/a&gt;
  (merged and&amp;nbsp;uploaded)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in October 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-10.html" rel="alternate"/><published>2025-11-09T15:33:33+00:00</published><updated>2025-11-09T15:33:33+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-11-09:/~cjwatson/blog/activity-2025-10.html</id><summary type="html">&lt;p&gt;OpenSSH 10.1p1/10.2p1, ansible-core autopkgtests, and the start of Python 3.14 packaging&amp;nbsp;work.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 95% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;OpenSSH upstream released
&lt;a href="https://www.openssh.org/releasenotes.html#10.1"&gt;10.1p1&lt;/a&gt; this month, so I
upgraded to that.  In the process, I reverted a Debian patch that changed &lt;span class="caps"&gt;IP&lt;/span&gt;
quality-of-service defaults, which &lt;a href="https://bugs.debian.org/923879"&gt;made sense at the
time&lt;/a&gt; but has since been reworked upstream
anyway, so it makes sense to find out whether we still have similar
problems.  So far I haven&amp;#8217;t heard anything bad in this&amp;nbsp;area.&lt;/p&gt;
&lt;p&gt;10.1p1 caused a regression in the ssh-agent-filter package&amp;#8217;s tests, which I
&lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3877"&gt;bisected and chased up with
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;10.1p1 also had a few other user-visible regressions
(&lt;a href="https://bugs.debian.org/1117574"&gt;#1117574&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1117594"&gt;#1117594&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1117638"&gt;#1117638&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1117720"&gt;#1117720&lt;/a&gt;); I upgraded to
&lt;a href="https://www.openssh.org/releasenotes.html#10.2"&gt;10.2p1&lt;/a&gt; which fixed some of
these, and &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3879#c10"&gt;contributed some upstream debugging
help&lt;/a&gt; to clear up the
rest.  While I was there, I also fixed &lt;a href="https://bugs.debian.org/1117965"&gt;ssh-session-cleanup: fails due to
wrong $ssh_session_pattern&lt;/a&gt; in our&amp;nbsp;packaging.&lt;/p&gt;
&lt;p&gt;Finally, I got all this into trixie-backports, which I intend to keep up to
date throughout the forky development&amp;nbsp;cycle.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;For some time, ansible-core has had occasional autopkgtest failures that
usually go away before anyone has a chance to look into them properly.  I
ran into these via openssh recently and decided to track them down.  It
turns out that they only happened when the &lt;code&gt;libpython3.13-stdlib&lt;/code&gt; package
had different versions in testing and unstable, because an integration test
setup script made a change that would be reverted if that package was ever
upgraded in the testbed, and one of the integration tests accidentally
failed to disable system apt sources comprehensively enough while testing
the behaviour of the &lt;code&gt;ansible.builtin.apt&lt;/code&gt; module.  I &lt;a href="https://salsa.debian.org/python-team/packages/ansible-core/-/compare/debian%2F2.19.3-1...debian%2F2.19.3-2?from_project_id=58498"&gt;fixed this in
Debian&lt;/a&gt;
and &lt;a href="https://github.com/ansible/ansible/pull/86050"&gt;contributed the relevant part
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve started working on enabling Python 3.14 as a supported version in
Debian.  I fixed or helped to fix a number of packages for&amp;nbsp;this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117894"&gt;cxxopt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117978"&gt;cython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117891"&gt;m2crypto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117899"&gt;pymongo&lt;/a&gt; (already fixed by Alexandre
  Detiste, but after checking this I took the opportunity to simplify its
  arrangements for disabling broken tests and to switch to&amp;nbsp;autopkgtest-pkg-pybuild)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117902"&gt;python-cytoolz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117907"&gt;python-lz4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117910"&gt;python-msgspec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aiomysql (fixing &lt;a href="https://bugs.debian.org/1118754"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-62611&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;audioread&lt;/li&gt;
&lt;li&gt;bitstruct&lt;/li&gt;
&lt;li&gt;black (fixing a &lt;a href="https://bugs.debian.org/1114067"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;blake3-py&lt;/li&gt;
&lt;li&gt;buildbot (fixing a &lt;a href="https://bugs.debian.org/1117640"&gt;regression&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;cxxopt&lt;/li&gt;
&lt;li&gt;django-cte&lt;/li&gt;
&lt;li&gt;django-pipeline&lt;/li&gt;
&lt;li&gt;django-q&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;khard&lt;/li&gt;
&lt;li&gt;lazy-object-proxy (fixing a &lt;a href="https://bugs.debian.org/1117892"&gt;build
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;psycopg3 (fixing a &lt;a href="https://bugs.debian.org/1117367"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pydantic-extra-types&lt;/li&gt;
&lt;li&gt;pytest-mock&lt;/li&gt;
&lt;li&gt;pytest-rerunfailures&lt;/li&gt;
&lt;li&gt;python-bcrypt&lt;/li&gt;
&lt;li&gt;python-bitarray&lt;/li&gt;
&lt;li&gt;python-confluent-kafka (&lt;a href="https://bugs.debian.org/1089748"&gt;#1089748&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-crispy-bootstrap4&lt;/li&gt;
&lt;li&gt;python-crispy-bootstrap5&lt;/li&gt;
&lt;li&gt;python-django-mptt&lt;/li&gt;
&lt;li&gt;python-ewoksppf (fixing a &lt;a href="https://bugs.debian.org/1115134"&gt;build
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-greenlet (fixing a &lt;a href="https://bugs.debian.org/1082800"&gt;build failure on
  powerpc&lt;/a&gt; and a &lt;a href="https://bugs.debian.org/1117906"&gt;Python 3.14 build
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-gssapi&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-persistent&lt;/li&gt;
&lt;li&gt;python-pyluach&lt;/li&gt;
&lt;li&gt;python-pytest-asyncio&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-pytokens (&lt;a href="https://github.com/tusharsadhwani/pytokens/pull/11"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-semantic-release&lt;/li&gt;
&lt;li&gt;python-stdlib-list&lt;/li&gt;
&lt;li&gt;python-tblib&lt;/li&gt;
&lt;li&gt;python-telethon&lt;/li&gt;
&lt;li&gt;python-treq&lt;/li&gt;
&lt;li&gt;python-typing-inspection&lt;/li&gt;
&lt;li&gt;python-watchfiles&lt;/li&gt;
&lt;li&gt;pyupgrade&lt;/li&gt;
&lt;li&gt;rpds-py (fixing a &lt;a href="https://bugs.debian.org/1114347"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.hookable&lt;/li&gt;
&lt;li&gt;zope.schema&lt;/li&gt;
&lt;li&gt;zope.testrunner (removing &lt;a href="https://bugs.debian.org/1084020"&gt;run-time dependency on
  setuptools&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1110998"&gt;python-blockbuster&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/1116692"&gt;python-pytokens&lt;/a&gt;, needed as new
dependencies of various other&amp;nbsp;packages.&lt;/p&gt;
&lt;p&gt;Santiago Vila filed a &lt;a href="https://udd.debian.org/cgi-bin/bts-usertags.cgi?user=debian-qa@lists.debian.org&amp;amp;tag=ftbfs-nocheck-profile"&gt;batch of
bugs&lt;/a&gt;
about packages that fail to build when using the &lt;a href="https://wiki.debian.org/BuildProfileSpec"&gt;&lt;code&gt;nocheck&lt;/code&gt; build
profile&lt;/a&gt;, and I fixed several of
these (generally just a matter of adjusting&amp;nbsp;build-dependencies):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pastedeploy (&lt;a href="https://bugs.debian.org/1116833"&gt;#1116833&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-ewokscore (&lt;a href="https://bugs.debian.org/1116858"&gt;#1116858&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-ewoksdask (&lt;a href="https://bugs.debian.org/1116859"&gt;#1116859&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-ewoksorange (&lt;a href="https://bugs.debian.org/1116862"&gt;#1116862&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-odmantic (&lt;a href="https://bugs.debian.org/1116866"&gt;#1116866&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-processview (&lt;a href="https://bugs.debian.org/1116871"&gt;#1116871&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-semantic-release (&lt;a href="https://bugs.debian.org/1116881"&gt;#1116881&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;sqlfluff (&lt;a href="https://bugs.debian.org/1116916"&gt;#1116916&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I helped out with the &lt;a href="https://udd.debian.org/cgi-bin/bts-usertags.cgi?user=debian-science@lists.debian.org&amp;amp;tag=scikit-learn-1.7"&gt;scikit-learn 1.7
transition&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117991"&gt;python-gplearn&lt;/a&gt; (&lt;a href="https://github.com/trevorstephens/gplearn/pull/305"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117992"&gt;scikit-optimize&lt;/a&gt; (&lt;a href="https://github.com/holgern/scikit-optimize/pull/8"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117989"&gt;sklearn-pandas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed or helped to fix several other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118418"&gt;beangulp&lt;/a&gt; (&lt;a href="https://github.com/beancount/beangulp/pull/193"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117386"&gt;beanquery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117391"&gt;buildbot&lt;/a&gt; (&lt;a href="https://github.com/buildbot/buildbot/pull/8707"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118419"&gt;celery&lt;/a&gt; (&lt;a href="https://github.com/celery/celery/pull/9968"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114604"&gt;cython&lt;/a&gt; (only on i386; involved a rather
  slow bisection process&amp;nbsp;first)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118305"&gt;django-measurement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118306"&gt;django-select2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118170"&gt;ocrmypdf&lt;/a&gt; (partial investigation, still&amp;nbsp;open)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117421"&gt;poetry-plugin-export&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114282"&gt;pytest-aiohttp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117423"&gt;python-aiohttp-session&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1107129"&gt;python-cups&lt;/a&gt;&amp;nbsp;(cross-building)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117647"&gt;python-django-postgres-extra&lt;/a&gt; (actually
  needed a fix in&amp;nbsp;python-django)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114715"&gt;python-fabio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114308"&gt;python-jellyfish&lt;/a&gt; (&lt;a href="https://codeberg.org/jpt/jellyfish/pulls/232"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117369"&gt;python-maturin&lt;/a&gt; (thanks to a patch from
  Peter Michael Green in &lt;a href="https://bugs.debian.org/1115459"&gt;#1115459&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114330"&gt;python-requests-oauthlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115760"&gt;python-telethon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//bugs.debian.org/1115756"&gt;python-webargs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114379"&gt;silx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/sphinx-inline-tabs/-/compare/debian%2F2023.4.21-2...debian%2F2023.4.21-3?from_project_id=75611"&gt;sphinx-inline-tabs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1105905"&gt;cython: The man page is &lt;code&gt;/usr/bin/env: 'python': No such file or
  directory&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1078006"&gt;depthcharge-tools: SyntaxWarnings with Python 3.12 about invalid escape
  sequences&lt;/a&gt; (&lt;a href="https://github.com/alpernebbi/depthcharge-tools/pull/9"&gt;contributed
  upstream&lt;/a&gt; a while&amp;nbsp;ago)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1112509"&gt;django-auditlog: Please drop dependencies on&amp;nbsp;python3-pytzdata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118055"&gt;pysmi: Might trigger: AttributeError: module &amp;#8216;importlib&amp;#8217; has no attribute
  &amp;#8216;machinery&amp;#8217;&lt;/a&gt; (&lt;a href="https://github.com/etingof/pysmi/pull/74"&gt;attempted to contribute
  upstream&lt;/a&gt;, although that
  repository is&amp;nbsp;dead)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115274"&gt;python-msgspec: Please use pseudo-packages for architecture&amp;nbsp;whitelisting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1118582"&gt;python-tomlkit: Binary package&amp;nbsp;rejected&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I investigated a &lt;a href="https://bugs.debian.org/1117768"&gt;python-py build failure&lt;/a&gt;,
which turned out to have been fixed in Python&amp;nbsp;3.13.9.&lt;/p&gt;
&lt;p&gt;I adopted &lt;a href="https://bugs.debian.org/948809"&gt;zope.hookable&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/948812"&gt;zope.location&lt;/a&gt; for the Python&amp;nbsp;team.&lt;/p&gt;
&lt;p&gt;Following an &lt;span class="caps"&gt;IRC&lt;/span&gt; question, I &lt;a href="https://salsa.debian.org/electronics-team/linux-gpib-user/-/merge_requests/1"&gt;ported linux-gpib-user to
pybuild-plugin-pyproject&lt;/a&gt;,
and added tests to make sure the resulting binary package layout is&amp;nbsp;correct.&lt;/p&gt;
&lt;h2&gt;Rust&amp;nbsp;packaging&lt;/h2&gt;
&lt;p&gt;Another Pydantic upgrade meant I had to upgrade a corresponding stack of
Rust packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rust-idna&lt;/li&gt;
&lt;li&gt;rust-jiter&lt;/li&gt;
&lt;li&gt;rust-pyo3&lt;/li&gt;
&lt;li&gt;rust-regex&lt;/li&gt;
&lt;li&gt;rust-regex-automata&lt;/li&gt;
&lt;li&gt;rust-speedate&lt;/li&gt;
&lt;li&gt;rust-uuid&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also upgraded rust-archery and&amp;nbsp;rust-rpds.&lt;/p&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;p&gt;I fixed a few bugs in other packages I&amp;nbsp;maintain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117014"&gt;halibut: &lt;span class="caps"&gt;FTCBFS&lt;/span&gt;: passes host flags to the build&amp;nbsp;compiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117112"&gt;iprutils: No package available for other&amp;nbsp;architectures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I investigated a &lt;a href="https://bugs.debian.org/1118530"&gt;malware report against
tini&lt;/a&gt;, which I think we can prove to be a
false positive (at least under the reasonable assumption that there isn&amp;#8217;t
malware hiding in libgcc or glibc).  Yay for reproducible&amp;nbsp;builds!&lt;/p&gt;
&lt;p&gt;I noticed and fixed a &lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/merge_requests/25"&gt;small &lt;span class="caps"&gt;UI&lt;/span&gt; deficiency in
debbugs&lt;/a&gt;,
making the checkboxes under &amp;#8220;Misc options&amp;#8221; on package pages easier to hit.
This is merged but we haven&amp;#8217;t yet deployed&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;I notced and fixed a
&lt;a href="https://salsa.debian.org/debian/developers-reference/-/merge_requests/73"&gt;typo&lt;/a&gt;
in the &lt;a href="https://www.debian.org/doc/manuals/developers-reference/pkgs.en.html#being-kind-to-porters"&gt;Being kind to
porters&lt;/a&gt;
section of the Debian Developer&amp;#8217;s&amp;nbsp;Reference.&lt;/p&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debian/base-passwd/-/merge_requests/17"&gt;base-passwd: Add clock
  group&lt;/a&gt;&amp;nbsp;(rejected)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/merge_requests/24"&gt;debbugs: Fix dep8 autopkgtests, make Salsa &lt;span class="caps"&gt;CI&lt;/span&gt; fully
  green&lt;/a&gt;
  (reviewed, awaiting&amp;nbsp;revisions)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1117764"&gt;python-gmpy2: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;&lt;/a&gt; (sponsored fix for
  Martin&amp;nbsp;Kelly)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Mistaken dichotomies about dgit</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/dgit-dichotomies.html" rel="alternate"/><published>2025-10-19T13:04:28+01:00</published><updated>2025-10-19T13:04:28+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-10-19:/~cjwatson/blog/dgit-dichotomies.html</id><summary type="html">&lt;p&gt;In &lt;a href="https://optimizedbyotto.com/post/xz-backdoor-debian-git-detection/"&gt;&amp;#8220;Could the &lt;span class="caps"&gt;XZ&lt;/span&gt; backdoor have been detected with better Git and Debian
packaging practices?&amp;#8221;&lt;/a&gt;,
Otto contrasts &amp;#8220;git-buildpackage managed git repositories&amp;#8221; with &amp;#8220;dgit
managed repositories&amp;#8221;, saying that &amp;#8220;the dgit managed repositories cannot
incorporate the upstream git history and are thus less useful for auditing
the full software supply-chain in&amp;nbsp;git …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In &lt;a href="https://optimizedbyotto.com/post/xz-backdoor-debian-git-detection/"&gt;&amp;#8220;Could the &lt;span class="caps"&gt;XZ&lt;/span&gt; backdoor have been detected with better Git and Debian
packaging practices?&amp;#8221;&lt;/a&gt;,
Otto contrasts &amp;#8220;git-buildpackage managed git repositories&amp;#8221; with &amp;#8220;dgit
managed repositories&amp;#8221;, saying that &amp;#8220;the dgit managed repositories cannot
incorporate the upstream git history and are thus less useful for auditing
the full software supply-chain in&amp;nbsp;git&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Otto does qualify this earlier with &amp;#8220;a package &amp;#8230; that has not had the
history recorded in dgit earlier&amp;#8221;, but the last sentence of the section is a
misleading oversimplification.  It&amp;#8217;s true for repositories that have been
&lt;em&gt;synthesized&lt;/em&gt; by dgit (which indeed was the focus of that section of Otto&amp;#8217;s
article), but it&amp;#8217;s not true in general for repositories that are &lt;em&gt;managed&lt;/em&gt;
by&amp;nbsp;dgit.&lt;/p&gt;
&lt;p&gt;I suspect this was just slightly unclear writing, so I don&amp;#8217;t want to nitpick
here, but rather to take the opportunity to try to clear up some
misconceptions around &lt;a href="https://salsa.debian.org/dgit-team/dgit"&gt;dgit&lt;/a&gt;
that I&amp;#8217;ve often heard at conferences and seen on mailing&amp;nbsp;lists.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not a dgit developer, although I&amp;#8217;m a happy user of it and I&amp;#8217;ve tried to
help out in various design discussions over the&amp;nbsp;years.&lt;/p&gt;
&lt;section id="dgit-and-git-buildpackage-sit-at-different-layers"&gt;
&lt;h2&gt;dgit and git-buildpackage sit at different&amp;nbsp;layers&lt;/h2&gt;
&lt;p&gt;It seems very common for people to think of git-buildpackage and dgit as
alternatives, as the example I quoted at the start of this article suggests.
It&amp;#8217;s really better to think of dgit as a separate and orthogonal&amp;nbsp;layer.&lt;/p&gt;
&lt;p&gt;You can use dgit &lt;em&gt;together&lt;/em&gt; with tools such as git-buildpackage.  In that
case, git-buildpackage handles the general shape of your git history, such
as helping you to import new upstream versions, and dgit handles gatewaying
between the archive and git.  The advantages become evident when you start
using &lt;a href="https://wiki.debian.org/tag2upload"&gt;tag2upload&lt;/a&gt;, in which case you
can just use &lt;code&gt;git debpush&lt;/code&gt; to push a tag and the tag2upload service deals
with building the source package and uploading it to the archive for you.
This is true regardless of how you put your package&amp;#8217;s git history together.
(There&amp;#8217;s currently a &lt;a href="https://bugs.debian.org/1106071"&gt;wrinkle around pristine-tar support&lt;/a&gt;, so at the moment I personally tend to
use &lt;code&gt;dgit push-source&lt;/code&gt; for new upstream versions and &lt;code&gt;git debpush&lt;/code&gt; for
new Debian revisions, since I haven&amp;#8217;t yet convinced myself that I see no
remaining value in pristine upstream&amp;nbsp;tarballs.)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dgit-supports-complete-history"&gt;
&lt;h2&gt;dgit supports complete&amp;nbsp;history&lt;/h2&gt;
&lt;p&gt;If the maintainer has never used dgit, and so &lt;code&gt;dgit clone&lt;/code&gt; synthesizes a
repository based on the current contents of the Debian archive, then there&amp;#8217;s
indeed no useful history there; in that situation it doesn&amp;#8217;t go back and
import everything from the snapshot archive the way that &lt;code&gt;gbp import-dscs
--debsnap&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;However, if the maintainer uses dgit, then dgit&amp;#8217;s view will include more
history, and it&amp;#8217;s absolutely possible for that to include complete upstream
git history as well.  Try&amp;nbsp;this:&lt;/p&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;dgit&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;man-db
&lt;span class="go"&gt;canonical suite name for unstable is sid&lt;/span&gt;
&lt;span class="go"&gt;fetching existing git history&lt;/span&gt;
&lt;span class="go"&gt;last upload to archive: specified git info (debian)&lt;/span&gt;
&lt;span class="go"&gt;downloading http://ftp.debian.org/debian//pool/main/m/man-db/man-db_2.13.1.orig.tar.xz...&lt;/span&gt;
&lt;span class="gp"&gt;  % &lt;/span&gt;Total&lt;span class="w"&gt;    &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Received&lt;span class="w"&gt; &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Xferd&lt;span class="w"&gt;  &lt;/span&gt;Average&lt;span class="w"&gt; &lt;/span&gt;Speed&lt;span class="w"&gt;   &lt;/span&gt;Time&lt;span class="w"&gt;    &lt;/span&gt;Time&lt;span class="w"&gt;     &lt;/span&gt;Time&lt;span class="w"&gt;  &lt;/span&gt;Current
&lt;span class="go"&gt;                                 Dload  Upload   Total   Spent    Left  Speed&lt;/span&gt;
&lt;span class="go"&gt;100 2060k  100 2060k    0     0  4643k      0 --:--:-- --:--:-- --:--:-- 4652k&lt;/span&gt;
&lt;span class="go"&gt;downloading http://ftp.debian.org/debian//pool/main/m/man-db/man-db_2.13.1.orig.tar.xz.asc...&lt;/span&gt;
&lt;span class="gp"&gt;  % &lt;/span&gt;Total&lt;span class="w"&gt;    &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Received&lt;span class="w"&gt; &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Xferd&lt;span class="w"&gt;  &lt;/span&gt;Average&lt;span class="w"&gt; &lt;/span&gt;Speed&lt;span class="w"&gt;   &lt;/span&gt;Time&lt;span class="w"&gt;    &lt;/span&gt;Time&lt;span class="w"&gt;     &lt;/span&gt;Time&lt;span class="w"&gt;  &lt;/span&gt;Current
&lt;span class="go"&gt;                                 Dload  Upload   Total   Spent    Left  Speed&lt;/span&gt;
&lt;span class="go"&gt;100   833  100   833    0     0  16322      0 --:--:-- --:--:-- --:--:-- 16660&lt;/span&gt;
&lt;span class="go"&gt;HEAD is now at 167835b0 releasing package man-db version 2.13.1-1&lt;/span&gt;
&lt;span class="go"&gt;dgit ok: ready for work in man-db&lt;/span&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;man-db&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--graph&lt;span class="w"&gt; &lt;/span&gt;--oneline&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head
&lt;span class="go"&gt;* 167835b0 releasing package man-db version 2.13.1-1&lt;/span&gt;
&lt;span class="go"&gt;*   f7910493 New upstream release (2.13.1)&lt;/span&gt;
&lt;span class="go"&gt;|\&lt;/span&gt;
&lt;span class="go"&gt;| *   3073b72e Import man-db_2.13.1.orig.tar.xz&lt;/span&gt;
&lt;span class="go"&gt;| |\&lt;/span&gt;
&lt;span class="go"&gt;| | * 349ce503 Release man-db 2.13.1&lt;/span&gt;
&lt;span class="go"&gt;| | * 0d6635c1 Update Russian manual page translation&lt;/span&gt;
&lt;span class="go"&gt;| | * cbf87caf Update Italian translation&lt;/span&gt;
&lt;span class="go"&gt;| | * fb5c5017 Update German manual page translation&lt;/span&gt;
&lt;span class="go"&gt;| | * dae2057b Update Brazilian Portuguese manual page translation&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;That package uses &lt;a href="https://manpages.debian.org/trixie/git-dpm/git-dpm.1.en.html"&gt;git-dpm&lt;/a&gt;, since I
prefer the way it represents patches.  But it works fine with
git-buildpackage&amp;nbsp;too:&lt;/p&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;dgit&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;isort
&lt;span class="go"&gt;canonical suite name for unstable is sid&lt;/span&gt;
&lt;span class="go"&gt;fetching existing git history&lt;/span&gt;
&lt;span class="go"&gt;last upload to archive: specified git info (debian)&lt;/span&gt;
&lt;span class="go"&gt;downloading http://ftp.debian.org/debian//pool/main/i/isort/isort_7.0.0.orig.tar.gz...&lt;/span&gt;
&lt;span class="gp"&gt;  % &lt;/span&gt;Total&lt;span class="w"&gt;    &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Received&lt;span class="w"&gt; &lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;Xferd&lt;span class="w"&gt;  &lt;/span&gt;Average&lt;span class="w"&gt; &lt;/span&gt;Speed&lt;span class="w"&gt;   &lt;/span&gt;Time&lt;span class="w"&gt;    &lt;/span&gt;Time&lt;span class="w"&gt;     &lt;/span&gt;Time&lt;span class="w"&gt;  &lt;/span&gt;Current
&lt;span class="go"&gt;                                 Dload  Upload   Total   Spent    Left  Speed&lt;/span&gt;
&lt;span class="go"&gt;100  786k  100  786k    0     0  1772k      0 --:--:-- --:--:-- --:--:-- 1774k&lt;/span&gt;
&lt;span class="go"&gt;HEAD is now at f812aae releasing package isort version 7.0.0-1&lt;/span&gt;
&lt;span class="go"&gt;dgit ok: ready for work in isort&lt;/span&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;isort&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;--graph&lt;span class="w"&gt; &lt;/span&gt;--oneline&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;head
&lt;span class="go"&gt;* f812aae releasing package isort version 7.0.0-1&lt;/span&gt;
&lt;span class="go"&gt;*   efde62f Update upstream source from tag &amp;#39;upstream/7.0.0&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;|\&lt;/span&gt;
&lt;span class="go"&gt;| * 9694f3d New upstream version 7.0.0&lt;/span&gt;
&lt;span class="go"&gt;* | 9cbfe0b releasing package isort version 6.1.0-1&lt;/span&gt;
&lt;span class="go"&gt;* | 5423ffe Mark isort and python3-isort Multi-Arch: foreign&lt;/span&gt;
&lt;span class="go"&gt;* | 5eaf5bf Update upstream source from tag &amp;#39;upstream/6.1.0&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;|\|&lt;/span&gt;
&lt;span class="go"&gt;| * edafbfc New upstream version 6.1.0&lt;/span&gt;
&lt;span class="go"&gt;* |   aedfd25 Merge branch &amp;#39;debian/master&amp;#39; into fix992793&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;If you look closely you&amp;#8217;ll see another difference here: the second only
includes one commit representing the new upstream release, and doesn&amp;#8217;t have
complete upstream history.  This doesn&amp;#8217;t represent a difference between
git-dpm and git-buildpackage.  Both tools can operate in both ways: for
example, &lt;code&gt;git-dpm import-new-upstream --parent&lt;/code&gt; and &lt;code&gt;gbp import-orig
--upstream-vcs-tag&lt;/code&gt; do broadly similar things, and something like &lt;code&gt;gbp
import-dscs --debsnap --upstream-vcs-tag='%(version)s'&lt;/code&gt; can be used to do a
bulk import provided that upstream&amp;#8217;s tags are named consistently enough.
This is not generally the default because adding complete upstream history
requires extra setup: the maintainer has to add an extra git remote pointing
to upstream and select the correct tag when importing a new version, and
some upstreams forget to push git tags or don&amp;#8217;t have the sort of consistency
you might&amp;nbsp;want.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://salsa.debian.org/python-team/tools/python-modules/blob/master/policy.rst"&gt;Debian Python team&amp;#8217;s policy&lt;/a&gt;
says that &amp;#8220;Complete upstream Git history should be avoided in the upstream
branch&amp;#8221;, which is why the isort history above looks the way it does.  I
don&amp;#8217;t love this because I think the results are less useful, but I
understand why it&amp;#8217;s there: in a moderately large team maintaining thousands
of packages, getting everyone to have the right git remotes set up would be
a recipe for frustrating&amp;nbsp;inconsistency.&lt;/p&gt;
&lt;p&gt;However, in packages I maintain myself, I strongly value having complete
upstream history in order to make it easier to debug problems, and I think
it makes things a bit more transparent to auditors too, so I&amp;#8217;m willing to go
to a little extra work to make that happen.  Doing that is completely
compatible with using&amp;nbsp;dgit.&lt;/p&gt;
&lt;/section&gt;
</content><category term="debian"/><category term="planet-debian"/></entry><entry><title>Free software activity in September 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-09.html" rel="alternate"/><published>2025-10-08T19:16:52+01:00</published><updated>2025-10-08T19:16:52+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-10-08:/~cjwatson/blog/activity-2025-09.html</id><summary type="html">&lt;p&gt;Regressions, regressions&amp;nbsp;everywhere.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 90% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some months I feel like I&amp;#8217;m pedalling furiously just to keep everything in a
roughly working state.  This was one of those&amp;nbsp;months.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aiosmtplib&lt;/li&gt;
&lt;li&gt;billiard&lt;/li&gt;
&lt;li&gt;dbus-fast&lt;/li&gt;
&lt;li&gt;django-modeltranslation&lt;/li&gt;
&lt;li&gt;django-sass-processor&lt;/li&gt;
&lt;li&gt;feedparser&lt;/li&gt;
&lt;li&gt;flask-security&lt;/li&gt;
&lt;li&gt;jaraco.itertools&lt;/li&gt;
&lt;li&gt;mariadb-connector-python&lt;/li&gt;
&lt;li&gt;mistune&lt;/li&gt;
&lt;li&gt;more-itertools&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pyina&lt;/li&gt;
&lt;li&gt;pytest-mock&lt;/li&gt;
&lt;li&gt;python-asyncssh&lt;/li&gt;
&lt;li&gt;python-bytecode&lt;/li&gt;
&lt;li&gt;python-ciso8601&lt;/li&gt;
&lt;li&gt;python-django-pgbulk&lt;/li&gt;
&lt;li&gt;python-ewokscore&lt;/li&gt;
&lt;li&gt;python-ewoksdask&lt;/li&gt;
&lt;li&gt;python-ewoksutils&lt;/li&gt;
&lt;li&gt;python-expandvars&lt;/li&gt;
&lt;li&gt;python-git&lt;/li&gt;
&lt;li&gt;python-gssapi&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-jira&lt;/li&gt;
&lt;li&gt;python-jpype&lt;/li&gt;
&lt;li&gt;python-mastodon&lt;/li&gt;
&lt;li&gt;python-orjson (fixing a &lt;a href="https://bugs.debian.org/1114315"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pyftpdlib&lt;/li&gt;
&lt;li&gt;python-pytest-asyncio (fixing a &lt;a href="https://bugs.debian.org/1114323"&gt;build
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-recurring-ical-events&lt;/li&gt;
&lt;li&gt;python-redis&lt;/li&gt;
&lt;li&gt;python-watchfiles (fixing a &lt;a href="https://bugs.debian.org/1114338"&gt;build
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-x-wr-timezone&lt;/li&gt;
&lt;li&gt;python-zipp&lt;/li&gt;
&lt;li&gt;pyzmq&lt;/li&gt;
&lt;li&gt;readability&lt;/li&gt;
&lt;li&gt;scalene (fixing test failures with pydantic&amp;nbsp;2.12.0~a1)&lt;/li&gt;
&lt;li&gt;sen (&lt;a href="https://github.com/TomasTomecek/sen/pull/190"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;sqlfluff&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;ttconv&lt;/li&gt;
&lt;li&gt;vdirsyncer&lt;/li&gt;
&lt;li&gt;zope.component&lt;/li&gt;
&lt;li&gt;zope.configuration&lt;/li&gt;
&lt;li&gt;zope.deferredimport&lt;/li&gt;
&lt;li&gt;zope.deprecation&lt;/li&gt;
&lt;li&gt;zope.exceptions&lt;/li&gt;
&lt;li&gt;zope.i18nmessageid&lt;/li&gt;
&lt;li&gt;zope.interface&lt;/li&gt;
&lt;li&gt;zope.proxy&lt;/li&gt;
&lt;li&gt;zope.schema&lt;/li&gt;
&lt;li&gt;zope.security (&lt;a href="https://github.com/zopefoundation/zope.security/pull/121"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.testing&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had to spend a fair bit of time this month chasing down build/test
regressions in various packages due to some other upgrades, particularly to
pydantic, python-pytest-asyncio, and&amp;nbsp;rust-pyo3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/aiohappyeyeballs/-/commit/b637c131c4860c33140012bdc55ed4cb2ce006ec"&gt;aiohappyeyeballs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;aiohttp-sse (&lt;a href="https://bugs.debian.org/1115561"&gt;filed bug&lt;/a&gt; and &lt;a href="https://github.com/aio-libs/aiohttp-sse/pull/597"&gt;contributed
  fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;aioimaplib (&lt;a href="https://github.com/iroco-co/aioimaplib/issues/124#issuecomment-3305911017"&gt;tried to fix upstream but failed to get tests&amp;nbsp;working&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/aiosmtplib/-/commit/6da2d47e5090d814e53319f77be4e93a47ae54b2"&gt;aiosmtplib&lt;/a&gt;
  (&lt;a href="https://github.com/cole/aiosmtplib/pull/328"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/app-model/-/commit/32619704f8c254d1ee2df8642835ea9bf88b4d0e"&gt;app-model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/aresponses/-/commit/bfc135122501ccdceabbcb8324be1c478fbe55d1"&gt;aresponses&lt;/a&gt;
  (&lt;a href="https://github.com/aresponses/aresponses/pull/85"&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;fastapi (&lt;a href="https://bugs.debian.org/1113771"&gt;filed bug&lt;/a&gt; and &lt;a href="https://github.com/fastapi/fastapi/pull/14036"&gt;contributed fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/ipython/-/commit/2bd12280052e5f80e9464506da4e4ebe1259c072"&gt;ipython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opendrop (&lt;a href="https://bugs.debian.org/1115562"&gt;filed bug&lt;/a&gt; and &lt;a href="https://github.com/jdber1/opendrop/pull/74"&gt;contributed
  fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/pydantic-extra-types/-/compare/debian%2F2.10.5-1...debian%2F2.10.5-2?from_project_id=98689"&gt;pydantic-extra-types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114286"&gt;pytest-relaxed&lt;/a&gt; (&lt;a href="https://github.com/bitprophet/pytest-relaxed/pull/34"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114301"&gt;python-drf-spectacular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-fakeredis/-/compare/debian%2F2.29.0-4...debian%2F2.29.0-5?from_project_id=10544"&gt;python-fakeredis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115563"&gt;python-jsonrpc-websocket&lt;/a&gt; (&lt;a href="https://github.com/emlove/jsonrpc-websocket/pull/16"&gt;contributed
  upstream&lt;/a&gt;, and
  sponsored upload for Tianyu&amp;nbsp;Chen)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-odmantic/-/commit/21977555a971b0b1fd8b59611f60984e74f3f3f0"&gt;python-odmantic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114324"&gt;python-pytest-trio&lt;/a&gt; (&lt;a href="https://github.com/python-trio/pytest-trio/issues/151"&gt;upstream
  issue&lt;/a&gt;, &lt;a href="https://github.com/python-trio/pytest-trio/pull/152"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;, &lt;a href="https://github.com/pytest-dev/pytest/issues/13734"&gt;pytest issue
  about possible root
  cause&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114327"&gt;python-repoze.sphinx.autointerface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114332"&gt;python-sluurp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-youtubeaio (&lt;a href="https://bugs.debian.org/1113903"&gt;filed bug&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115575"&gt;rtsp-to-webrtc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After some upstream discussion I &lt;a href="https://bugs.debian.org/1115318"&gt;requested removal of
pydantic-compat&lt;/a&gt;, since it was more trouble
than it was worth to keep it working with the latest pydantic&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;I filed &lt;a href="https://bugs.debian.org/1115299"&gt;dh-python: pybuild-plugin-pyproject doesn&amp;#8217;t know about
headers&lt;/a&gt; and added it to
&lt;a href="https://wiki.debian.org/Python/PybuildPluginPyproject"&gt;Python/PybuildPluginPyproject&lt;/a&gt;,
and converted some packages to &lt;code&gt;pybuild-plugin-pyproject&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aresponses&lt;/li&gt;
&lt;li&gt;python-azure, fixing an &lt;a href="https://bugs.debian.org/1114162"&gt;autopkgtest failure in&amp;nbsp;kombu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-ciso8601&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I updated dh-python to &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/62"&gt;suppress generated dependencies that would be
satisfied by python3 &amp;gt;=
3.11&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pkg_resources&lt;/code&gt; is
&lt;a href="https://github.com/pypa/setuptools/issues/3085"&gt;deprecated&lt;/a&gt;.  In most cases
replacing it is a relatively simple matter of &lt;a href="https://importlib-resources.readthedocs.io/en/latest/migration.html"&gt;porting to
&lt;code&gt;importlib.resources&lt;/code&gt;&lt;/a&gt;,
but packages that used its old namespace package support need more
complicated work to port them to &lt;a href="https://peps.python.org/pep-0420/"&gt;implicit namespace
packages&lt;/a&gt;.  We had quite a few bugs about
this on &lt;code&gt;zope.*&lt;/code&gt; packages, but fortunately upstream did the &lt;a href="https://github.com/zopefoundation/meta/issues/194"&gt;hard part of
this&lt;/a&gt; recently.  I went
round and cleaned up most of the remaining loose ends, with some help from
Alexandre Detiste.  Some of these aren&amp;#8217;t completely done yet as they&amp;#8217;re
awaiting new upstream&amp;nbsp;releases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zope.component (&lt;a href="https://bugs.debian.org/1084007"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.component/pull/80"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.configuration (&lt;a href="https://bugs.debian.org/1084006"&gt;Debian bug&lt;/a&gt;,
  &lt;a href="https://github.com/zopefoundation/zope.configuration/pull/68"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.deferredimport (&lt;a href="https://bugs.debian.org/1084008"&gt;Debian bug&lt;/a&gt;,
  &lt;a href="https://github.com/zopefoundation/zope.deferredimport/pull/18"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.deprecation (&lt;a href="https://bugs.debian.org/1084009"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.deprecation/pull/27"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.exceptions (&lt;a href="https://bugs.debian.org/1084012"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.exceptions/pull/42"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.i18nmessageid (&lt;a href="https://bugs.debian.org/1084014"&gt;Debian bug&lt;/a&gt;,
  &lt;a href="https://github.com/zopefoundation/zope.i18nmessageid/pull/67"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.interface (&lt;a href="https://bugs.debian.org/1084013"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.interface/pull/346"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.location (&lt;a href="https://bugs.debian.org/1084016"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.location/pull/17"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.security (&lt;a href="https://bugs.debian.org/1084018"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.security/pull/122"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.testing (&lt;a href="https://bugs.debian.org/1084019"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.testing/pull/55"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;zope.testrunner (&lt;a href="https://bugs.debian.org/1084020"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://github.com/zopefoundation/zope.testrunner/pull/201"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This work also caused a couple of build regressions, which I&amp;nbsp;fixed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115803"&gt;zope.hookable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115763"&gt;zope.location&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed
&lt;a href="https://salsa.debian.org/python-team/packages/jupyter-client/-/commit/ebe94146e3bb6405c529aeae8118161334bc9ab1"&gt;jupyter-client&lt;/a&gt;
so that its autopkgtests would work in&amp;nbsp;Debusine.&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1116924"&gt;waitress&lt;/a&gt; to build with the
&lt;code&gt;nocheck&lt;/code&gt; profile.&lt;/p&gt;
&lt;p&gt;I fixed several other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114057"&gt;austin&lt;/a&gt; (&lt;a href="https://github.com/P403n1x87/austin/pull/330"&gt;contributed follow-up fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/fsspec/-/commit/849213bc0a6abb533d8046302378246c9da5549e"&gt;fsspec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1114876"&gt;python-asgiref&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1115079"&gt;python-django-channels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1116155"&gt;twisted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1017761"&gt;python-jpype: java.lang.ClassNotFoundException:&amp;nbsp;org.jpype.classloader.DynamicClassLoader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1035211"&gt;python-jpype: Please add autopkgtests (to add coverage for&amp;nbsp;python3-numpy)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code&amp;nbsp;reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;debbugs: &lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/merge_requests/24"&gt;Fix dep8 autopkgtests, make Salsa &lt;span class="caps"&gt;CI&lt;/span&gt; fully
  green&lt;/a&gt;
  (still in&amp;nbsp;progress)&lt;/li&gt;
&lt;li&gt;dput-ng: &lt;a href="https://bugs.debian.org/1112107"&gt;Add trixie-backports &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;bookworm-backports-sloppy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;openssh: &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/34"&gt;Update sshd@.service to follow&amp;nbsp;upstream&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;openssh: &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/35"&gt;authfd: fallback to default if $SSH_AUTH_SOCK is
  unset&lt;/a&gt;
  (still in&amp;nbsp;progress)&lt;/li&gt;
&lt;li&gt;putty: &lt;a href="https://salsa.debian.org/ssh-team/putty/-/merge_requests/7"&gt;d/rules: Use dh_assistant&amp;nbsp;restore-file-on-clean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-debian: &lt;a href="https://salsa.debian.org/python-debian-team/python-debian/-/merge_requests/151"&gt;Update from pyupgrade to
  &amp;#8212;py37-plus&lt;/a&gt;
  (still in&amp;nbsp;progress)&lt;/li&gt;
&lt;li&gt;release-notes: &lt;a href="https://salsa.debian.org/ddp-team/release-notes/-/merge_requests/322"&gt;issues: mention tzdata-legacy&amp;nbsp;split&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;p&gt;I fixed several CMake 4 build&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1112984"&gt;halibut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1112986"&gt;hdf5-blosc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1112987"&gt;hdf5-filter-plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1113655"&gt;yubihsm-shell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I got &lt;span class="caps"&gt;CI&lt;/span&gt; for debbugs passing
(&lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/merge_requests/22"&gt;!22&lt;/a&gt;,
&lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/merge_requests/23"&gt;!23&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I fixed a &lt;a href="https://bugs.debian.org/1114418"&gt;build failure with &lt;span class="caps"&gt;GCC&lt;/span&gt; 15 in
trn4&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I filed a &lt;a href="https://bugs.debian.org/1114970"&gt;release-notes bug&lt;/a&gt; about the
tzdata reorganization in the trixie&amp;nbsp;cycle.&lt;/p&gt;
&lt;p&gt;I filed and fixed a &lt;a href="https://bugs.debian.org/1115226"&gt;git-dpm regression with bash
5.3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I upgraded libfilter-perl to a new upstream&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://code.launchpad.net/~cjwatson/ubuntu-dev-tools/+git/ubuntu-dev-tools/+merge/492543"&gt;optimized some code in
ubuntu-dev-tools&lt;/a&gt;
that made O(1) &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests when it could instead make&amp;nbsp;O(n).&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in August 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-08.html" rel="alternate"/><published>2025-09-03T11:56:59+01:00</published><updated>2025-09-03T11:56:59+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-09-03:/~cjwatson/blog/activity-2025-08.html</id><summary type="html">&lt;p&gt;Lots of Python package upgrades, and planning for &lt;code&gt;setup.py install&lt;/code&gt; being&amp;nbsp;removed.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 95% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;forky is
&lt;a href="https://lists.debian.org/debian-devel-announce/2025/08/msg00002.html"&gt;open&lt;/a&gt;!
As a result I&amp;#8217;m starting to think about the &lt;a href="https://peps.python.org/pep-0745/"&gt;upcoming Python
3.14&lt;/a&gt;.  At some point we&amp;#8217;ll doubtless do
a full test rebuild, but in advance of that I concluded that one of the most
useful things I could do would be to work on our &lt;a href="https://udd.debian.org/dmd/?email1=team%2Bpython%40tracker.debian.org"&gt;very long list of packages
with new upstream
versions&lt;/a&gt;.
Of course there&amp;#8217;s no real chance of this ever becoming empty since upstream
maintainers aren&amp;#8217;t going to stop work for that long, but there are a lot of
packages there where we&amp;#8217;re quite a long way out of date, and many of those
include fixes that we&amp;#8217;ll need for 3.14, either directly or by fixing
interactions with new versions of other packages that in turn will need to
be fixed.  We can backport changes when we need to, but more often than not
the most efficient way to do things is just to keep up to&amp;nbsp;date.&lt;/p&gt;
&lt;p&gt;So, I upgraded these packages to new upstream versions (deep&amp;nbsp;breath):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aioftp&lt;/li&gt;
&lt;li&gt;aiosignal (building on &lt;a href="https://salsa.debian.org/python-team/packages/aiosignal/-/merge_requests/1"&gt;work by
  IanLucca&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;audioop-lts&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;djangorestframework&lt;/li&gt;
&lt;li&gt;djoser&lt;/li&gt;
&lt;li&gt;fpylll&lt;/li&gt;
&lt;li&gt;frozenlist&lt;/li&gt;
&lt;li&gt;git-repo-updater&lt;/li&gt;
&lt;li&gt;ipykernel&lt;/li&gt;
&lt;li&gt;klepto&lt;/li&gt;
&lt;li&gt;kombu&lt;/li&gt;
&lt;li&gt;multipart&lt;/li&gt;
&lt;li&gt;netmiko (sponsoring &lt;a href="https://salsa.debian.org/python-team/packages/netmiko/-/merge_requests/1"&gt;work by Eduardo
  Silva&lt;/a&gt;;
  &lt;a href="https://github.com/ktbyers/netmiko/pull/3722"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pathos&lt;/li&gt;
&lt;li&gt;ppft&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pylsqpack&lt;/li&gt;
&lt;li&gt;pymssql&lt;/li&gt;
&lt;li&gt;pytest-mock&lt;/li&gt;
&lt;li&gt;pytest-pretty&lt;/li&gt;
&lt;li&gt;pytest-repeat&lt;/li&gt;
&lt;li&gt;pytest-rerunfailures&lt;/li&gt;
&lt;li&gt;python-a2wsgi&lt;/li&gt;
&lt;li&gt;python-apptools (sponsoring &lt;a href="https://salsa.debian.org/python-team/packages/python-apptools/-/merge_requests/6"&gt;work by Kathlyn Lara
  Murussi&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-asgiref&lt;/li&gt;
&lt;li&gt;python-asyncssh&lt;/li&gt;
&lt;li&gt;python-bitarray&lt;/li&gt;
&lt;li&gt;python-bitstring&lt;/li&gt;
&lt;li&gt;python-bytecode&lt;/li&gt;
&lt;li&gt;python-channels-redis&lt;/li&gt;
&lt;li&gt;python-charset-normalizer&lt;/li&gt;
&lt;li&gt;python-daphne&lt;/li&gt;
&lt;li&gt;python-django-analytical&lt;/li&gt;
&lt;li&gt;python-django-guid&lt;/li&gt;
&lt;li&gt;python-django-health-check&lt;/li&gt;
&lt;li&gt;python-django-pgbulk&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger&lt;/li&gt;
&lt;li&gt;python-django-postgres-extra&lt;/li&gt;
&lt;li&gt;python-django-storages&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-httpx-sse&lt;/li&gt;
&lt;li&gt;python-icalendar&lt;/li&gt;
&lt;li&gt;python-lazy-model&lt;/li&gt;
&lt;li&gt;python-line-profiler&lt;/li&gt;
&lt;li&gt;python-lz4&lt;/li&gt;
&lt;li&gt;python-marshmallow-dataclass&lt;/li&gt;
&lt;li&gt;python-mastodon&lt;/li&gt;
&lt;li&gt;python-model-bakery&lt;/li&gt;
&lt;li&gt;python-oauthlib&lt;/li&gt;
&lt;li&gt;python-parse-type&lt;/li&gt;
&lt;li&gt;python-pathvalidate&lt;/li&gt;
&lt;li&gt;python-pgspecial&lt;/li&gt;
&lt;li&gt;python-processview&lt;/li&gt;
&lt;li&gt;python-pytest-subtests&lt;/li&gt;
&lt;li&gt;python-roman&lt;/li&gt;
&lt;li&gt;python-semantic-release&lt;/li&gt;
&lt;li&gt;python-testfixtures&lt;/li&gt;
&lt;li&gt;python-time-machine&lt;/li&gt;
&lt;li&gt;python-tokenize-rt&lt;/li&gt;
&lt;li&gt;python-typeguard&lt;/li&gt;
&lt;li&gt;python-typing-extensions&lt;/li&gt;
&lt;li&gt;python-urllib3&lt;/li&gt;
&lt;li&gt;pyupgrade&lt;/li&gt;
&lt;li&gt;requests (fixing &lt;a href="http://bugs.debian.org/1107368"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-47081&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;responses&lt;/li&gt;
&lt;li&gt;zope.deferredimport&lt;/li&gt;
&lt;li&gt;zope.schema&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8217;s only about 10% of the backlog, but of course others are working on
this too.  If we can keep this up for a while then it should&amp;nbsp;help.&lt;/p&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1111640"&gt;pytest-run-parallel&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1110995"&gt;pytest-unmagic&lt;/a&gt; (still in &lt;code&gt;NEW&lt;/code&gt;), and
&lt;a href="https://bugs.debian.org/1111569"&gt;python-forbiddenfruit&lt;/a&gt; (still in &lt;code&gt;NEW&lt;/code&gt;),
all needed as new dependencies of various other&amp;nbsp;packages.&lt;/p&gt;
&lt;p&gt;setuptools upstream will be &lt;a href="https://setuptools.pypa.io/en/stable/history.html#v80-1-0"&gt;removing the &lt;code&gt;setup.py install&lt;/code&gt;
command&lt;/a&gt; on 31
October.  While this may not trickle down immediately into Debian, it does
mean that in the near future nearly all Python packages will have to use
&lt;code&gt;pybuild-plugin-pyproject&lt;/code&gt; (note that this does &lt;em&gt;not&lt;/em&gt; mean that they
necessarily have to use &lt;code&gt;pyproject.toml&lt;/code&gt;; this is just a question of how the
packaging runs the build system).  We talked about this a bit at DebConf,
and I said that I&amp;#8217;d noticed a number of packages where this isn&amp;#8217;t
straightforward and promised to write up some notes.  I wrote the
&lt;a href="https://wiki.debian.org/Python/PybuildPluginPyproject"&gt;Python/PybuildPluginPyproject&lt;/a&gt;
wiki page for this; I expect to add more bits and pieces to it as I find&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;On that note, I converted several packages to &lt;code&gt;pybuild-plugin-pyproject&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;billiard&lt;/li&gt;
&lt;li&gt;lazr.config&lt;/li&gt;
&lt;li&gt;python-timeline&lt;/li&gt;
&lt;li&gt;zope.sqlalchemy&lt;/li&gt;
&lt;li&gt;zope.testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed several build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1111057"&gt;aiosmtplib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1111058"&gt;blinker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1111059"&gt;ipykernel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1111060"&gt;ipyparallel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/quart/-/commit/481c11c4fc33a18b17f8b223dff584342adc84af"&gt;quart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1110821"&gt;austin: binutils now has a libsframe-dev package, please add an explicit
  build&amp;nbsp;dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-django-pgbulk/-/commit/96a17113f634d3c401c21a113579273ec49ccc2b"&gt;python-django-pgbulk: Missing dependency on
  python3-typing-extensions&lt;/a&gt;
  (&lt;a href="https://github.com/AmbitionEng/django-pgbulk/pull/54"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1110139"&gt;python-maturin: Upcoming rust-which&amp;nbsp;update&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I reviewed &lt;a href="https://salsa.debian.org/python-team/packages/fail2ban/-/merge_requests/18"&gt;Debian defaults: nftables as banaction and systemd as
backend&lt;/a&gt;,
but it looked as though nothing actually needed to be changed so we closed
this with no&amp;nbsp;action.&lt;/p&gt;
&lt;h2&gt;Rust&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;Upgrading Pydantic was complicated, and required a rust-pyo3 transition
(which Jelmer Vernooĳ started and Peter Michael Green has mostly been
driving, thankfully), packaging rust-malloc-size-of (including an &lt;a href="https://github.com/servo/malloc_size_of/pull/12"&gt;upstream
portability fix&lt;/a&gt;), and
upgrading several packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rust-serde&lt;/li&gt;
&lt;li&gt;rust-serde-derive&lt;/li&gt;
&lt;li&gt;rust-serde-json&lt;/li&gt;
&lt;li&gt;rust-smallvec&lt;/li&gt;
&lt;li&gt;rust-speedate&lt;/li&gt;
&lt;li&gt;rust-time&lt;/li&gt;
&lt;li&gt;rust-time-core&lt;/li&gt;
&lt;li&gt;rust-time-macros&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;bugs.debian.org&lt;/h2&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1078575"&gt;bugs.debian.org: misspelled checkbox id
&amp;#8220;uselessmesages&amp;#8221;&lt;/a&gt;, as well as a &lt;a href="https://salsa.debian.org/debbugs-team/debbugs/-/commit/fff0db4e57a2781f5c82827e42f395a3325270f3"&gt;bug that
caused incoming emails with certain header contents to go
missing&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1080350"&gt;openssh-server: refuses further connections after having handled
PerSourceMaxStartups connections&lt;/a&gt; with a
cherry-pick from&amp;nbsp;upstream.&lt;/p&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;p&gt;I upgraded libfido2 to a new upstream&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1103589"&gt;mimalloc: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; on armhf: cc1: error: ‘-mfloat-abi=hard’: selected
architecture lacks an &lt;span class="caps"&gt;FPU&lt;/span&gt;&lt;/a&gt;, which was
blocking changes to pendulum in the Python team.  I also spent some time
helping to investigate &lt;a href="https://bugs.debian.org/1106879"&gt;libmimalloc3: Illegal instruction Running mtxrun
&amp;#8212;generate&lt;/a&gt;, though that bug is still&amp;nbsp;open.&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://salsa.debian.org/debian/gssproxy/-/compare/debian%2F0.9.2-3...debian%2F0.9.2-4?from_project_id=45135"&gt;various autopkgtest bugs in
gssproxy&lt;/a&gt;,
prompted by
&lt;a href="https://salsa.debian.org/freexian-team/debusine/-/issues/1007"&gt;#1007&lt;/a&gt; in&amp;nbsp;Debusine.&lt;/p&gt;
&lt;p&gt;Since my old team is &lt;a href="https://blog.launchpad.net/general/phasing-out-bazaar-code-hosting"&gt;decommissioning Bazaar/Breezy code hosting in
Launchpad&lt;/a&gt;
(the end of an era, which I have distinctly mixed feelings about), I
converted &lt;a href="https://git.launchpad.net/storm"&gt;Storm&lt;/a&gt; to&amp;nbsp;git.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in July 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-07.html" rel="alternate"/><published>2025-08-06T11:41:41+01:00</published><updated>2025-08-06T11:41:41+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-08-06:/~cjwatson/blog/activity-2025-07.html</id><summary type="html">&lt;p&gt;DebConf, and a fiddly OpenSSH upgrade&amp;nbsp;problem.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 90% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;DebConf&lt;/h2&gt;
&lt;p&gt;I attended DebConf for the first time in 11 years (my last one was DebConf
14 in Portland).  It was great!  For once I had a conference where I had a
fairly light load of things I absolutely had to do, so I was able to spend
time catching up with old friends, making some new friends, and doing some
volunteering - a bit of Front Desk, and quite a lot of video team work where
I got to play with sound desks and such.  Apparently one of the BoFs (&amp;#8220;birds
of a feather&amp;#8221;, i.e. relatively open discussion sessions) where I was
talkmeister managed to break the automatic video cutting system by starting
and ending precisely on time, to the second, which I&amp;#8217;m told has never
happened before.  I&amp;#8217;ll take&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;I gave a &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-398-using-debusine-to-pre-test-your-unstable-uploads.av1.webm"&gt;talk about
Debusine&lt;/a&gt;,
along with &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-669-debusine-workflow-bof.av1.webm"&gt;helping Enrico run a Debusine
BoF&lt;/a&gt;.
We still need to process some of the feedback from this, but are generally
pretty thrilled about the reception.  My personal highlight was getting a
shout-out in a &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-605-approaching-the-speed-of-light-with-debian-debians-role-in-the-worlds-largest-particle-accelerator.av1.webm"&gt;talk from
&lt;span class="caps"&gt;CERN&lt;/span&gt;&lt;/a&gt;
(in the slide starting at&amp;nbsp;32:55).&lt;/p&gt;
&lt;p&gt;Other highlights for me included a &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-416-debian-python-bof.av1.webm"&gt;Python team
BoF&lt;/a&gt;,
&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-397-tag2upload-upload-simply-by-pushing-a-signed-git-tag.av1.webm"&gt;Ian&amp;#8217;s tag2upload
talk&lt;/a&gt;
and some very useful follow-up discussions, a session on &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-420-future-of-archive-wide-testing.av1.webm"&gt;archive-wide
testing&lt;/a&gt;,
a somewhat brain-melting whiteboard session about the &amp;#8220;multiarch interpreter
problem&amp;#8221;,
&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-649-salsa-bof.av1.webm"&gt;several&lt;/a&gt;
&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-624-salsa-ci-bof.av1.webm"&gt;useful&lt;/a&gt;
&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-560-salsa-ci-now-running-for-27-000-packages-what-have-we-learnt.av1.webm"&gt;discussions&lt;/a&gt;
about salsa.debian.org, &lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2025/DebConf25/debconf25-180-automating-downstream-debian-package-builds-and-updates-in-ci.av1.webm"&gt;Matthew&amp;#8217;s talk on how Wikimedia automates their Debian package
builds&lt;/a&gt;,
and many others.  I hope I can start attending regularly&amp;nbsp;again!&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;Towards the end of a release cycle, people tend to do more upgrade testing,
and this sometimes results in interesting problems.  Manfred Stock reported
&lt;a href="https://bugs.debian.org/1109742"&gt;&amp;#8220;No new &lt;span class="caps"&gt;SSH&lt;/span&gt; connections possible during large part of upgrade to Debian
Trixie&amp;#8221;&lt;/a&gt;, and after a little testing in a
container I confirmed that this was a reproducible problem that would have
affected many people upgrading from Debian 12 (bookworm), with potentially
severe consequences for people upgrading remote systems.  In fact, there
were two independent problems that each led to much the same&amp;nbsp;symptom:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OpenSSH 9.8 split the monolithic &lt;code&gt;sshd&lt;/code&gt; listener process into two
    pieces: a minimal network listener (still called &lt;code&gt;sshd&lt;/code&gt;), and an
    &lt;code&gt;sshd-session&lt;/code&gt; process dealing with each individual session.  (OpenSSH
    10.0 further split &lt;code&gt;sshd-session&lt;/code&gt;, adding an &lt;code&gt;sshd-auth&lt;/code&gt; process that
    deals with the user authentication phase of the protocol.)  This hardens
    the OpenSSH server by using different address spaces for privileged and
    unprivileged&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;Before this change, when &lt;code&gt;sshd&lt;/code&gt; received an incoming connection, it
forked and re-executed itself with some special parameters to deal with
it.  After this change, it forks and executes &lt;code&gt;sshd-session&lt;/code&gt; instead,
and &lt;code&gt;sshd&lt;/code&gt; no longer accepts the parameters it used to accept for&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;Debian package upgrades happen in two phases: first we unpack the new
files onto disk, and then we run some package-specific configuration
steps which usually include things like restarting services.  (I&amp;#8217;m
simplifying, but this is good enough for this post.)  Normally this is
fine, and in fact desirable: the old service keeps on working, and this
approach often allows breaking what would otherwise be difficult cycles
by ensuring that the system is in a more coherent state before trying to
restart services.  However, in this case, unpacking the new files onto
disk immediately means that new &lt;span class="caps"&gt;SSH&lt;/span&gt; connections no longer work: the old
&lt;code&gt;sshd&lt;/code&gt; receives the connection and tries to hand it off to a
freshly-executed copy of the new &lt;code&gt;sshd&lt;/code&gt; binary on disk, which no longer
supports&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re just upgrading OpenSSH on its own or with a small number of
other packages, this isn&amp;#8217;t much of a problem as the listener will be
restarted quite soon; but if you&amp;#8217;re upgrading from bookworm to trixie,
there may be a long gap when you can&amp;#8217;t &lt;span class="caps"&gt;SSH&lt;/span&gt; to the system any more, and
if something fails in the middle of the upgrade then you could be in&amp;nbsp;trouble.&lt;/p&gt;
&lt;p&gt;So, what to do?  I considered keeping a copy of the old &lt;code&gt;sshd&lt;/code&gt; around
temporarily and patching the new &lt;code&gt;sshd&lt;/code&gt; to re-execute it if it&amp;#8217;s being
run to handle an incoming connection, but that turned out to fail in my
first test: dependencies are normally only checked when configuring a
package, so it&amp;#8217;s possible to unpack &lt;code&gt;openssh-server&lt;/code&gt; before unpacking a
newer &lt;code&gt;libc6&lt;/code&gt; that it depends on, at which point you can&amp;#8217;t execute the
new &lt;code&gt;sshd&lt;/code&gt; at all.  (That also means that the approach of restarting the
service at unpack time instead of configure time is a non-starter.)  We
needed a different&amp;nbsp;idea.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dpkg&lt;/code&gt;, the core Debian package manager, has a specialized facility
called &amp;#8220;diversions&amp;#8221;: you can tell it that when it&amp;#8217;s unpacking a
particular file it should put it somewhere else instead.  This is
normally used by administrators when they want to install a
locally-modified version of a particular file at their own risk, or by
packages that knowingly override a file normally provided by some other
package.  However, in this case it turns out to be useful for
&lt;code&gt;openssh-server&lt;/code&gt; to temporarily divert one of its own files!  When
upgrading from before 9.8, it now diverts &lt;code&gt;/usr/sbin/sshd&lt;/code&gt; to
&lt;code&gt;/usr/sbin/sshd.session-split&lt;/code&gt; before the new version is unpacked, then
removes the diversion and moves the new file into place once it&amp;#8217;s ready
to restart the service; this reduces the period when incoming
connections fail to a minimum.  (We actually have to pretend that the
diversion is being performed on behalf of a slightly different package
since we&amp;#8217;re using &lt;code&gt;dpkg-divert&lt;/code&gt; in a strange way here, but it all&amp;nbsp;works.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Most OpenSSH processes, including &lt;code&gt;sshd&lt;/code&gt;, check for a compatible version
    of the OpenSSL library when they start up.  This check used to be very
    picky, among other things requiring both the major and minor number to
    match.  OpenSSL 3 has a &lt;a href="https://www.openssl-library.org/policies/general/versioning-policy/"&gt;better versioning
    policy&lt;/a&gt;,
    and so OpenSSH 9.4p1 &lt;a href="https://anongit.mindrot.org/openssh.git/commit/?id=b7afd8a4ecaca8afd3179b55e9db79c0ff210237"&gt;relaxed this
    check&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, bookworm shipped with OpenSSH 9.2p1, which means that as
soon as you unpack the new &lt;code&gt;libssl3&lt;/code&gt; during an upgrade (actually
&lt;code&gt;libssl3t64&lt;/code&gt; due to the &lt;a href="https://wiki.debian.org/ReleaseGoals/64bit-time"&gt;64-bit &lt;code&gt;time_t&lt;/code&gt;
transition&lt;/a&gt;), &lt;code&gt;sshd&lt;/code&gt;
stops working.  This couldn&amp;#8217;t be fixed by a change in trixie; we needed
to change bookworm in advance of the upgrade so that it would tolerate
newer versions of OpenSSL.  And time was tight if we wanted to maximize
the chance that people would apply that stable update before upgrading
to trixie; there isn&amp;#8217;t going to be another point release of Debian 12
before the release of Debian&amp;nbsp;13.&lt;/p&gt;
&lt;p&gt;Fortunately, there&amp;#8217;s a
&lt;a href="https://www.debian.org/doc/manuals/developers-reference/pkgs.en.html#special-case-the-stable-updates-suite"&gt;&lt;code&gt;stable-updates&lt;/code&gt;&lt;/a&gt;
mechanism for exactly this sort of thing, and the stable release
managers kindly accepted my proposal to fix this&amp;nbsp;there.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The net result is that if you apply updates to bookworm (including
&lt;code&gt;stable-updates&lt;/code&gt; / &lt;code&gt;bookworm-updates&lt;/code&gt;, which is enabled by default) before
starting the upgrade to trixie, everything should be fine.  Many thanks to
Manfred for reporting this with just enough time to spare that we were able
to fix it before Debian 13 is released in a few&amp;nbsp;days!&lt;/p&gt;
&lt;h2&gt;debmirror&lt;/h2&gt;
&lt;p&gt;I did my twice-yearly refresh of debmirror&amp;#8217;s &lt;a href="https://salsa.debian.org/debian/debmirror/-/blob/master/mirror_size"&gt;&lt;code&gt;mirror_size&lt;/code&gt;
documentation&lt;/a&gt;,
and applied a &lt;a href="https://bugs.debian.org/1108274"&gt;patch from Christoph Goehre&lt;/a&gt;
to improve mirroring of installer&amp;nbsp;files.&lt;/p&gt;
&lt;h2&gt;madison-lite&lt;/h2&gt;
&lt;p&gt;I &lt;a href="https://bugs.debian.org/1109003"&gt;proposed&lt;/a&gt; renaming this project along
with the &lt;code&gt;rmadison&lt;/code&gt; tool in &lt;code&gt;devscripts&lt;/code&gt;, although I&amp;#8217;m not yet sure what a
good replacement name would&amp;nbsp;be.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded python-expandvars, python-typing-extensions (in experimental),
and webtest to new upstream&amp;nbsp;versions.&lt;/p&gt;
&lt;p&gt;I backported fixes for some security vulnerabilities to&amp;nbsp;unstable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-urllib3: &lt;a href="https://bugs.debian.org/1108076"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-50181&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1108077"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-50182&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed or helped to fix a number of release-critical&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108968"&gt;bitstruct: autopkgtest regression: invalid command&amp;nbsp;&amp;#8216;test&amp;#8217;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1102611"&gt;django-pipeline: autopkgtest failure&lt;/a&gt;
  (&lt;a href="https://github.com/jazzband/django-pipeline/pull/837"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108946"&gt;pnopaste: Fails to install with debconf noninteractive
  frontend&lt;/a&gt; (suggested possible&amp;nbsp;patch)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108799"&gt;py3dns: autopkgtest regression: &amp;#8216;96.7.128.186&amp;#8217; !=
  &amp;#8216;93.184.215.14&amp;#8217;&lt;/a&gt; (&lt;a href="https://code.launchpad.net/~cjwatson/py3dns/+git/py3dns/+merge/488798"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108782"&gt;python-marshmallow-dataclass: autopkgtest depends on removed package&amp;nbsp;python-marshmallow-enum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108795"&gt;python-pkgconfig: autopkgtest regression: list index out of&amp;nbsp;range&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108797"&gt;python-txrequests: autopkgtest regression:
  twisted.trial.unittest.FailTest: 200 !=&amp;nbsp;404&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other bugs, mostly &lt;code&gt;Severity: important&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1106896"&gt;afew: Unable to remove tags&lt;/a&gt; (&lt;a href="https://salsa.debian.org/python-team/packages/afew/-/merge_requests/3"&gt;reviewed
  and merged
  &lt;span class="caps"&gt;MR&lt;/span&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103313"&gt;ipy: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with the nocheck build&amp;nbsp;profile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1108434"&gt;paramiko: Does not correctly handle OpenSSH 10&amp;nbsp;version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103323"&gt;python-django-storages: &lt;span class="caps"&gt;FTBFS&lt;/span&gt; with the nocheck build&amp;nbsp;profile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1104638"&gt;python-icalendar: Depends on a transitional
  package&lt;/a&gt; (and follow-up fixes for missing
  build-dependencies in python-recurring-ical-events, python-x-wr-timezone,
  and&amp;nbsp;todoman)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1025404"&gt;python-libais: Stop calling python3 setup.py
  test&lt;/a&gt; (&lt;a href="https://github.com/schwehr/libais/pull/252"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I reinstated python3-mastodon&amp;#8217;s build-dependency on and recommendation of
python3-blurhash, now that the latter has been &lt;a href="https://bugs.debian.org/1101140"&gt;fixed to use the correct
upstream source&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in June 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-06.html" rel="alternate"/><published>2025-07-01T00:30:51+01:00</published><updated>2025-07-01T00:30:51+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-07-01:/~cjwatson/blog/activity-2025-06.html</id><summary type="html">&lt;p&gt;pterm on Wayland, a groff &lt;span class="caps"&gt;PDF&lt;/span&gt; bug, and a few other odds and&amp;nbsp;ends.&lt;/p&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  This was a very light month; I did a few things that were easy or
that seemed urgent for the upcoming trixie release, but otherwise most of my
energy went into
&lt;a href="https://salsa.debian.org/freexian-team/debusine"&gt;Debusine&lt;/a&gt;.  I&amp;#8217;ll be giving
a talk about that at DebConf in a couple of weeks; this is the first DebConf
I&amp;#8217;ll have managed to make it to in over a decade, so I&amp;#8217;m pretty&amp;nbsp;excited.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;PuTTY&lt;/h2&gt;
&lt;p&gt;After reading a bunch of recent discourse about X11 and Wayland, I decided
to try switching my laptop (a Framework 13 &lt;span class="caps"&gt;AMD&lt;/span&gt; running Debian trixie with
&lt;span class="caps"&gt;GNOME&lt;/span&gt;) over to Wayland.  I don&amp;#8217;t remember why it was running X; I think I
must have either inherited some configuration from my previous laptop (in
which case it could have been due to anything up to ten years ago or so), or
else I had some initial problem while setting up my new laptop and failed to
make a note of it.  Anyway, the switch was hardly noticeable, which was&amp;nbsp;great.&lt;/p&gt;
&lt;p&gt;One problem I did notice is that my preferred terminal emulator, &lt;code&gt;pterm&lt;/code&gt;,
crashed after the upgrade.  I run a slightly-modified version from git to
make some small terminal emulation changes that I really must either get
upstream or work out how to live without one of these days, so it took me a
while to notice that it only crashed when running from the packaged version,
because the crash was in code that only runs when &lt;code&gt;pterm&lt;/code&gt; has a set-id bit.
I reported this upstream, they &lt;a href="https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=26a8ef376daf5f50c441a65691b84f87df49db9b"&gt;quickly fixed
it&lt;/a&gt;,
and I
&lt;a href="https://salsa.debian.org/ssh-team/putty/-/commit/14d65a6b00f559295e3174f09e233888da4b125c"&gt;backported&lt;/a&gt;
it to the Debian&amp;nbsp;package.&lt;/p&gt;
&lt;h2&gt;groff&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://savannah.gnu.org/bugs/index.php?67169"&gt;Upstream bug #67169&lt;/a&gt;
reported URLs being dropped from &lt;span class="caps"&gt;PDF&lt;/span&gt; output in some cases.  I &lt;a href="https://bugs.debian.org/1107068"&gt;investigated
the history&lt;/a&gt; both upstream and in Debian,
identified the &lt;a href="https://cgit.git.savannah.gnu.org/cgit/groff.git/commit/?id=d9e90209725a716dff23807ffffda403c58020c9"&gt;correct upstream patch to
backport&lt;/a&gt;,
and uploaded a&amp;nbsp;fix.&lt;/p&gt;
&lt;h2&gt;libfido2&lt;/h2&gt;
&lt;p&gt;I upgraded libfido2 to 1.16.0 in&amp;nbsp;experimental.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded pydantic-extra-types to a new upstream version, and &lt;a href="https://salsa.debian.org/python-team/packages/pendulum/-/commit/76ddf2d9a665a57f28867179cad43818545496aa"&gt;fixed some
resulting fallout in
pendulum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I updated python-typing-extensions in bookworm-backports, to help fix
&lt;a href="https://bugs.debian.org/1107980"&gt;python3-tango: python3-pytango from bookworm-backports does not work
(10.0.2-1~bpo12+1)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I upgraded twisted to a new upstream version in&amp;nbsp;experimental.&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix a few release-critical&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1107304"&gt;pdfarranger: Fails to start: RuntimeError: context has already been&amp;nbsp;set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1107410"&gt;python-covdefaults: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: E AttributeError: type object &amp;#8216;Plugins&amp;#8217; has no
  attribute&amp;nbsp;&amp;#8216;load_plugins&amp;#8217;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1107782"&gt;python-jq: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: E ValueError: jq: error: syntax error, unexpected&amp;nbsp;INVALID_CHARACTER&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1106442"&gt;python-returns: &lt;span class="caps"&gt;FTBFS&lt;/span&gt;: &lt;span class="caps"&gt;FAILED&lt;/span&gt;
  returns/future.py::returns.future.Future.do&lt;/a&gt;
  (fixed in python3.13, closed with no&amp;nbsp;action)&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in May 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-05.html" rel="alternate"/><published>2025-06-08T01:20:02+01:00</published><updated>2025-06-08T01:20:02+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-06-08:/~cjwatson/blog/activity-2025-05.html</id><summary type="html">&lt;p&gt;Debian work as we reached the hard freeze for&amp;nbsp;trixie.&lt;/p&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  Things were a bit quieter than usual, as for the most part I was
sticking to things that seemed urgent for the upcoming trixie&amp;nbsp;release.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt; or &lt;a href="https://github.com/sponsors/cjwatson"&gt;GitHub
Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;After my appeal for help &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-04.html"&gt;last month&lt;/a&gt; to
debug &lt;a href="https://bugs.debian.org/1103418"&gt;intermittent &lt;code&gt;sshd&lt;/code&gt; crashes&lt;/a&gt;, Michel
Casabona helped me put together an environment where I could reproduce it,
which allowed me to track it down to a &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3822"&gt;root
cause&lt;/a&gt; and fix it.  (I
also found a &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3819"&gt;misuse of
&lt;code&gt;strlcpy&lt;/code&gt;&lt;/a&gt; affecting at
least glibc-based systems in passing, though I think that was&amp;nbsp;unrelated.)&lt;/p&gt;
&lt;p&gt;I worked with Daniel Kahn Gillmor to fix a &lt;a href="https://bugs.debian.org/1103522"&gt;regression in &lt;code&gt;ssh-agent&lt;/code&gt; socket
handling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed a &lt;a href="https://bugs.debian.org/1104992"&gt;reproducibility bug depending on whether &lt;code&gt;passwd&lt;/code&gt; is installed on
the build system&lt;/a&gt;, which would have
affected security updates during the lifetime of&amp;nbsp;trixie.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://bugs.debian.org/1105036"&gt;backported&lt;/a&gt; openssh 1:10.0p1-5 to&amp;nbsp;bookworm-backports.&lt;/p&gt;
&lt;p&gt;I issued bookworm and
&lt;a href="https://lists.debian.org/debian-lts-announce/2025/05/msg00008.html"&gt;bullseye&lt;/a&gt;
updates for &lt;a href="https://bugs.debian.org/1102603"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-32728&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;groff&lt;/h2&gt;
&lt;p&gt;I backported a fix for &lt;a href="https://bugs.debian.org/1104609"&gt;incorrect output when formatting multiple documents
as &lt;span class="caps"&gt;PDF&lt;/span&gt;/PostScript at once&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;debmirror&lt;/h2&gt;
&lt;p&gt;I added a &lt;a href="https://salsa.debian.org/debian/debmirror/-/commit/c122f7ff32c4ae24a729a6ecf42d15c9ac05eb5c"&gt;simple
autopkgtest&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;automat&lt;/li&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;flufl.i18n&lt;/li&gt;
&lt;li&gt;flufl.lock&lt;/li&gt;
&lt;li&gt;frozenlist&lt;/li&gt;
&lt;li&gt;python-charset-normalizer&lt;/li&gt;
&lt;li&gt;python-evalidate (including pointing out an &lt;a href="https://github.com/yaroslaff/evalidate/issues/15"&gt;upstream release handling
  issue&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pythonjsonlogger&lt;/li&gt;
&lt;li&gt;python-setproctitle&lt;/li&gt;
&lt;li&gt;python-telethon&lt;/li&gt;
&lt;li&gt;python-typing-inspection&lt;/li&gt;
&lt;li&gt;python-webargs&lt;/li&gt;
&lt;li&gt;pyzmq&lt;/li&gt;
&lt;li&gt;trove-classifiers (including a &lt;a href="https://github.com/pypa/trove-classifiers/pull/212"&gt;small upstream
  cleanup&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;uncertainties&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In bookworm-backports, I updated these&amp;nbsp;packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-django to 3:4.2.21-1 (issuing
  &lt;a href="https://backports.debian.org/news/BSA-124_Security_Update_for_python-django/"&gt;&lt;span class="caps"&gt;BSA&lt;/span&gt;-124&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger to&amp;nbsp;4.14.0-1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed problems building these packages&amp;nbsp;reproducibly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;celery (&lt;a href="https://github.com/celery/celery/pull/9687"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-setproctitle&lt;/li&gt;
&lt;li&gt;uncertainties (&lt;a href="https://github.com/lmfit/uncertainties/pull/312"&gt;contributed
  upstream&lt;/a&gt;, after some&amp;nbsp;discussion)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I backported fixes for some security vulnerabilities to unstable (since
we&amp;#8217;re in freeze now so it&amp;#8217;s not always appropriate to upgrade to new
upstream&amp;nbsp;versions):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;django-select2: &lt;a href="https://bugs.debian.org/1106747"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-48383&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-tornado: &lt;a href="https://bugs.debian.org/1105886"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-47287&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/fail2ban/-/merge_requests/17"&gt;fail2ban&lt;/a&gt;
  (also reviewing and merging &lt;a href="https://salsa.debian.org/python-team/packages/fail2ban/-/merge_requests/15"&gt;fix sshd 10.0 log
  identifier&lt;/a&gt;
  and &lt;a href="https://salsa.debian.org/python-team/packages/fail2ban/-/merge_requests/16"&gt;remove runtime calls to
  distutils&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103147"&gt;karabo-bridge&lt;/a&gt; (&lt;a href="https://github.com/European-XFEL/karabo-bridge-py/pull/71"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1104837"&gt;kegtron-ble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091947"&gt;python-click-option-group&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1104508"&gt;python-holidays&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103591"&gt;python-mastodon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1106440"&gt;python-mechanize&lt;/a&gt; (&lt;a href="https://github.com/python-mechanize/mechanize/pull/102"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/thermobeacon-ble/-/commit/c1bc246f0a04018483074cbdca1501088165dc07"&gt;thermobeacon-ble&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I added non-superficial autopkgtests to these&amp;nbsp;packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1035163"&gt;karabo-bridge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-lazy-model/-/compare/debian%2F0.3.0-1...debian%2F0.3.0-2?from_project_id=93488"&gt;python-lazy-model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1103977"&gt;python-django-hashids&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/1103880"&gt;python-django-pgbulk&lt;/a&gt;, needed for new
upstream versions of&amp;nbsp;python-django-pgtrigger.&lt;/p&gt;
&lt;p&gt;I
&lt;a href="https://code.launchpad.net/~cjwatson/storm/py314-beta/+merge/485763"&gt;ported&lt;/a&gt;
storm to Python&amp;nbsp;3.14.&lt;/p&gt;
&lt;h2&gt;Science&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I fixed a &lt;a href="https://bugs.debian.org/1103232"&gt;build failure&lt;/a&gt; in&amp;nbsp;apertium-oci-fra.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="man-db"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in April 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-04.html" rel="alternate"/><published>2025-05-04T16:38:13+01:00</published><updated>2025-05-04T16:38:13+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-05-04:/~cjwatson/blog/activity-2025-04.html</id><summary type="html">&lt;p&gt;OpenSSH 10.0 (and a request for help), dput-ng, and&amp;nbsp;more.&lt;/p&gt;</summary><content type="html">&lt;p&gt;About 90% of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Request for OpenSSH debugging&amp;nbsp;help&lt;/h2&gt;
&lt;p&gt;Following the OpenSSH work described below, I have an &lt;a href="https://bugs.debian.org/1103418"&gt;open
report&lt;/a&gt; about the &lt;code&gt;sshd&lt;/code&gt; server sometimes
crashing when clients try to connect to it.  I can&amp;#8217;t reproduce this myself,
and arm&amp;#8217;s-length debugging is very difficult, but three different users have
reported it.  For the time being I can&amp;#8217;t pass it upstream, as it&amp;#8217;s entirely
possible it&amp;#8217;s due to a Debian&amp;nbsp;patch.&lt;/p&gt;
&lt;p&gt;Is there anyone reading this who can reproduce this bug and is capable of
doing some independent debugging work, most likely involving bisecting
changes to OpenSSH?  I&amp;#8217;d suggest first seeing whether a build of the
unmodified upstream 10.0p2 release exhibits the same bug.  If it does, then
bisect between 9.9p2 and 10.0p2; if not, then bisect the list of Debian
patches.  This would be extremely helpful, since at the moment it&amp;#8217;s a bit
like trying to look for a needle in a haystack from the next field over by
sending instructions to somebody with a magnifying&amp;nbsp;glass.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I upgraded the Debian packaging to &lt;a href="https://www.openssh.com/releasenotes.html#10.0p2"&gt;OpenSSH
10.0p1&lt;/a&gt; (now &lt;a href="https://lists.mindrot.org/pipermail/openssh-unix-announce/2025-April/000163.html"&gt;designated
10.0p2&lt;/a&gt;
by upstream due to a mistake in the release process, but they&amp;#8217;re the same
thing), fixing &lt;a href="https://bugs.debian.org/1102603"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-32728&lt;/a&gt;.  This also
involved a &lt;a href="https://bugs.debian.org/1102658"&gt;diffoscope bug report&lt;/a&gt; due to
the version number&amp;nbsp;change.&lt;/p&gt;
&lt;p&gt;I enabled the new &lt;code&gt;--with-linux-memlock-onfault&lt;/code&gt; configure option to protect
&lt;code&gt;sshd&lt;/code&gt; against being swapped out, but this turned out to cause test failures
on riscv64, so I disabled it again there.  Debugging this took some time
since I needed to do it under emulation, and in the process of setting up a
testbed I &lt;a href="https://gitlab.com/larswirzenius/vmdb2/-/merge_requests/154"&gt;added riscv64 support to
vmdb2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://bugs.debian.org/1102643"&gt;coordination&lt;/a&gt; with the wtmpdb
maintainer, I enabled the new Y2038-safe native wtmpdb support in OpenSSH,
so &lt;code&gt;wtmpdb last&lt;/code&gt; now reports the correct&amp;nbsp;tty.&lt;/p&gt;
&lt;p&gt;I fixed a couple of packaging&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1072184"&gt;Please stop writing&amp;nbsp;/var/log/btmp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095686"&gt;Restore sshd_config(5) documentation about&amp;nbsp;rdomain&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I reviewed and merged several packaging contributions from&amp;nbsp;others:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103037"&gt;ssh-agent: Improve systemd user service socket
  activation&lt;/a&gt; (Daniel Kahn&amp;nbsp;Gillmor)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/30"&gt;Switch from adduser to
  sysusers.d&lt;/a&gt;
  (Luca&amp;nbsp;Boccassi)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/31"&gt;Add sshd-keygen
  service&lt;/a&gt;
  (Luca&amp;nbsp;Boccassi)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;dput-ng&lt;/h2&gt;
&lt;p&gt;Since we &lt;a href="https://salsa.debian.org/freexian-team/debusine/-/issues/713"&gt;added &lt;code&gt;dput-ng&lt;/code&gt; integration to
Debusine&lt;/a&gt;
recently, I wanted to make sure that it was in good condition in trixie, so
I fixed &lt;a href="https://bugs.debian.org/1078613"&gt;dput-ng: will &lt;span class="caps"&gt;FTBFS&lt;/span&gt; during trixie support
period&lt;/a&gt;.  Previously a similar bug had been
fixed by just using different Ubuntu release names in tests; this time I
made the tests independent of the current supported release data returned by
&lt;code&gt;distro_info&lt;/code&gt;, so this shouldn&amp;#8217;t come up&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;We also ran into &lt;a href="https://bugs.debian.org/983160"&gt;dput-ng: &amp;#8212;override doesn&amp;#8217;t override profile
parameters&lt;/a&gt;, which needed somewhat more
extensive changes since it turned out that that option had never worked.  I
fixed this after some discussion with Paul Tagliamonte to make sure I
understood the background&amp;nbsp;properly.&lt;/p&gt;
&lt;h2&gt;man-db&lt;/h2&gt;
&lt;p&gt;I released &lt;a href="https://gitlab.com/man-db/man-db/-/releases/2.13.1"&gt;man-db
2.13.1&lt;/a&gt;.  This just
included various small fixes and a number of translation updates, but I
wanted to get it into trixie in order to include a contribution to &lt;a href="https://gitlab.com/man-db/man-db/-/issues/48"&gt;increase
the &lt;code&gt;MAX_NAME&lt;/code&gt; constant&lt;/a&gt;,
since that was now causing problems for some pathological cases of manual
pages in the wild that documented a very large number of&amp;nbsp;terms.&lt;/p&gt;
&lt;h2&gt;debmirror&lt;/h2&gt;
&lt;p&gt;I fixed one security bug: &lt;a href="https://bugs.debian.org/1104091"&gt;debmirror prints credentials with
&amp;#8212;progress&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;celery&lt;/li&gt;
&lt;li&gt;django-modeltranslation (maintained by&amp;nbsp;Freexian)&lt;/li&gt;
&lt;li&gt;django-phonenumber-field&lt;/li&gt;
&lt;li&gt;djangorestframework&lt;/li&gt;
&lt;li&gt;kombu&lt;/li&gt;
&lt;li&gt;orderly-set&lt;/li&gt;
&lt;li&gt;pox&lt;/li&gt;
&lt;li&gt;pydantic-extra-types&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1072833"&gt;python-cmarkgfm&lt;/a&gt; (fixing
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2022-39209"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2022-39209&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-22483"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-22483&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-22484"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-22484&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-22485"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-22485&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-22486"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-22486&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-24824"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-24824&lt;/a&gt;,
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-26485"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-26485&lt;/a&gt;,
  and
  &lt;a href="https://security-tracker.debian.org/tracker/CVE-2023-37463"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-37463&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-crispy-forms&lt;/li&gt;
&lt;li&gt;python-django-extensions (fixing incompatibilities with Python 3.12:
  &lt;a href="https://bugs.debian.org/1040091"&gt;#1040091&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1040119"&gt;#1040119&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger&lt;/li&gt;
&lt;li&gt;python-django-test-migrations&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-legacy-cgi&lt;/li&gt;
&lt;li&gt;python-pydash&lt;/li&gt;
&lt;li&gt;python-redis (4.3.4 to 5.2.1; needed some autopkgtest&amp;nbsp;adjustments)&lt;/li&gt;
&lt;li&gt;python-tblib&lt;/li&gt;
&lt;li&gt;python-typing-extensions&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;xonsh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In bookworm-backports, I updated these&amp;nbsp;packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-django to 3:4.2.20-1 (issuing
  &lt;a href="https://backports.debian.org/news/BSA-123_Security_Update_for_python-django/"&gt;&lt;span class="caps"&gt;BSA&lt;/span&gt;-123&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger to&amp;nbsp;4.13.3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I dropped a stale build-dependency from
&lt;a href="https://bugs.debian.org/1102526"&gt;python-aiohttp-security&lt;/a&gt; that kept it out
of testing (though unfortunately too late for the trixie&amp;nbsp;freeze).&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101621"&gt;billiard&lt;/a&gt; (&lt;a href="https://github.com/celery/billiard/pull/423"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1102380"&gt;bleak-retry-connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103184"&gt;cairosvg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103066"&gt;errbot&lt;/a&gt; (&lt;a href="https://github.com/errbotio/errbot/pull/1724"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103116"&gt;haversine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1104240"&gt;json-tricks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103146"&gt;jsonpickle&lt;/a&gt; (&lt;a href="https://github.com/jsonpickle/jsonpickle/pull/560"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/lazygal/-/commit/ea71ae96f4a48dd390f0e2b514234ce864ba430f"&gt;lazygal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101856"&gt;mypy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1102283"&gt;pydantic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101417"&gt;pydantic-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101859"&gt;pydantic-settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103197"&gt;pympress&lt;/a&gt; (&lt;a href="https://github.com/Cimbali/pympress/pull/333"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101861"&gt;pysequoia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103103"&gt;pysodium&lt;/a&gt; (&lt;a href="https://github.com/stef/pysodium/pull/117"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-decorator/-/commit/e9d3b610e7cc7e3766ea0be2b21b3489dc11d9d9"&gt;python-decorator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103593"&gt;python-djvulibre&lt;/a&gt; (&lt;a href="https://github.com/FriedrichFroebel/python-djvulibre/pull/25"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103140"&gt;python-momepy&lt;/a&gt; (&lt;a href="https://github.com/pysal/momepy/pull/698"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103362"&gt;python-msgspec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103581"&gt;python-tz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103501"&gt;storm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103208"&gt;supysonic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101258"&gt;uvloop&lt;/a&gt; (&lt;a href="https://github.com/MagicStack/uvloop/pull/662"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1102391"&gt;python-typing-inspection&lt;/a&gt;,
needed for a new upstream version of&amp;nbsp;pydantic.&lt;/p&gt;
&lt;p&gt;I
&lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/merge_requests/57"&gt;documented&lt;/a&gt;
the &lt;code&gt;architecture&lt;/code&gt; field in &lt;code&gt;debian/tests/autopkgtest-pkg-pybuild.conf&lt;/code&gt;
files.&lt;/p&gt;
&lt;p&gt;I fixed other odds and ends of&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087330"&gt;python-pydash: please make the build&amp;nbsp;reproducible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092859"&gt;thunarx-python: fails to allow plugins to
  run&lt;/a&gt; / &lt;a href="https://bugs.debian.org/1103704"&gt;thunarx-python: fails to discover
  &lt;span class="caps"&gt;SONAME&lt;/span&gt; of libpython, tries to load
  /usr/lib/&lt;span class="caps"&gt;MULTIARCH&lt;/span&gt;/lib.so.1.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1086561"&gt;ttconv: package installs superfluous files under&amp;nbsp;/usr/lib/python3/dist-packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Science&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I fixed various build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1102477"&gt;python-vispy&lt;/a&gt; (also fixing &lt;a href="https://bugs.debian.org/1064607"&gt;unhandled
  failures to build documentation can
  occur&lt;/a&gt; while I was&amp;nbsp;there)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1103004"&gt;skimage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="man-db"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in March 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-03.html" rel="alternate"/><published>2025-04-01T13:17:35+01:00</published><updated>2025-04-01T13:17:35+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-04-01:/~cjwatson/blog/activity-2025-03.html</id><summary type="html">&lt;p&gt;Fallout from python-click and dh-python changes; 59 &lt;span class="caps"&gt;RC&lt;/span&gt; bugs&amp;nbsp;fixed.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;Changes in dropbear 2025.87 &lt;a href="https://bugs.debian.org/1100948"&gt;broke OpenSSH&amp;#8217;s regression
tests&lt;/a&gt;.  I cherry-picked the&amp;nbsp;fix.&lt;/p&gt;
&lt;p&gt;I reviewed and merged &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/32"&gt;patches from Luca
Boccassi&lt;/a&gt; to
send and accept the &lt;code&gt;COLORTERM&lt;/code&gt; and &lt;code&gt;NO_COLOR&lt;/code&gt; environment&amp;nbsp;variables.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;Following up on &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-02.html"&gt;last month&lt;/a&gt;, I fixed some
more uscan&amp;nbsp;errors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-ewokscore&lt;/li&gt;
&lt;li&gt;python-ewoksdask&lt;/li&gt;
&lt;li&gt;python-ewoksdata&lt;/li&gt;
&lt;li&gt;python-ewoksorange&lt;/li&gt;
&lt;li&gt;python-ewoksutils&lt;/li&gt;
&lt;li&gt;python-processview&lt;/li&gt;
&lt;li&gt;python-rsyncmanager&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bitstruct&lt;/li&gt;
&lt;li&gt;django-modeltranslation (maintained by&amp;nbsp;Freexian)&lt;/li&gt;
&lt;li&gt;django-yarnpkg&lt;/li&gt;
&lt;li&gt;flit&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;jinja2 (fixing &lt;a href="https://bugs.debian.org/1099690"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-27516&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;mkdocstrings-python-legacy&lt;/li&gt;
&lt;li&gt;mysql-connector-python (fixing
  &lt;a href="https://bugs.debian.org/1093881"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-21548&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;psycopg3&lt;/li&gt;
&lt;li&gt;pydantic-extra-types&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pytest-httpx (fixing a &lt;a href="https://bugs.debian.org/1099269"&gt;build failure with httpx
  0.28&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-argcomplete&lt;/li&gt;
&lt;li&gt;python-cymem&lt;/li&gt;
&lt;li&gt;python-djvulibre&lt;/li&gt;
&lt;li&gt;python-ecdsa&lt;/li&gt;
&lt;li&gt;python-expandvars&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-json-log-formatter&lt;/li&gt;
&lt;li&gt;python-keycloak (fixing a &lt;a href="https://bugs.debian.org/1099273"&gt;build failure with httpx
  0.28&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-limits&lt;/li&gt;
&lt;li&gt;python-mastodon (in the course of which I found
  &lt;a href="https://bugs.debian.org/1101140"&gt;#1101140&lt;/a&gt; in blurhash-python and
  proposed a &lt;a href="https://salsa.debian.org/xmpp-team/slidge/-/merge_requests/1"&gt;small
  cleanup&lt;/a&gt; to&amp;nbsp;slidge)&lt;/li&gt;
&lt;li&gt;python-model-bakery&lt;/li&gt;
&lt;li&gt;python-multidict&lt;/li&gt;
&lt;li&gt;python-pip&lt;/li&gt;
&lt;li&gt;python-rsyncmanager&lt;/li&gt;
&lt;li&gt;python-service-identity&lt;/li&gt;
&lt;li&gt;python-setproctitle&lt;/li&gt;
&lt;li&gt;python-telethon&lt;/li&gt;
&lt;li&gt;python-trio&lt;/li&gt;
&lt;li&gt;python-typing-extensions&lt;/li&gt;
&lt;li&gt;responses&lt;/li&gt;
&lt;li&gt;setuptools-scm&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In bookworm-backports, I updated python-django to&amp;nbsp;3:4.2.19-1.&lt;/p&gt;
&lt;p&gt;Although Debian&amp;#8217;s upgrade to python-click 8.2.0 was
&lt;a href="https://bugs.debian.org/1098507#74"&gt;reverted&lt;/a&gt; for the time being, I fixed a
number of related problems anyway since we&amp;#8217;re going to have to deal with it&amp;nbsp;eventually:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098539"&gt;celery&lt;/a&gt; (&lt;a href="https://github.com/celery/celery/pull/9590"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098575"&gt;magic-wormhole&lt;/a&gt; (closed in Debian
  without action, but &lt;a href="https://github.com/magic-wormhole/magic-wormhole/pull/584"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098599"&gt;python-flasgger&lt;/a&gt; (&lt;a href="https://github.com/flasgger/flasgger/pull/633"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098630"&gt;sqlfluff&lt;/a&gt; (closed in Debian without
  action, but &lt;a href="https://github.com/sqlfluff/sqlfluff/pull/6706"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;dh-python dropped its dependency on python3-setuptools in 6.20250306, which
was long overdue, but it had quite a bit of fallout; in most cases this was
simply a question of adding build-dependencies on python3-setuptools, but in
a few cases there was a missing build-dependency on
python3-typing-extensions which had previously been pulled in as a
dependency of python3-setuptools.  I fixed these bugs resulting from&amp;nbsp;this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100195"&gt;beangrow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100196"&gt;beangulp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100198"&gt;beanprice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100197"&gt;beanquery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100199"&gt;beautifulsoup4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100213"&gt;django-choices-field&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100214"&gt;django-modeltranslation&lt;/a&gt; (maintained by&amp;nbsp;Freexian)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100217"&gt;flake8-class-newline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100216"&gt;flake8-quotes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100246"&gt;nodeenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100287"&gt;pygments-ansi-color&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100257"&gt;pytest-mypy-plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100256"&gt;python-agilent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100258"&gt;python-aiohttp-security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100259"&gt;python-aiohttp-session&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100265"&gt;python-djvulibre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100264"&gt;python-ewoksutils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100269"&gt;python-jsonlines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100271"&gt;python-mastodon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100277"&gt;python-pydash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100282"&gt;python-pytest-venv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100283"&gt;python-redfish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100285"&gt;python-ring-doorbell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100287"&gt;python-sluurp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100288"&gt;python-sqlite-migrate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100291"&gt;python-trubar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We agreed to &lt;a href="https://bugs.debian.org/1100231"&gt;remove python-pytest-flake8&lt;/a&gt;.
In support of this, I removed unnecessary build-dependencies from
pytest-pylint, python-proton-core, python-pyzipper, python-tatsu,
python-tatsu-lts, and python-tinycss, and filed &lt;a href="https://bugs.debian.org/1101178"&gt;#1101178 on
eccodes-python&lt;/a&gt; and &lt;a href="https://bugs.debian.org/1101179"&gt;#1101179 on
rpmlint&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There was a &lt;a href="https://bugs.debian.org/1099935"&gt;dnspython autopkgtest regression on
s390x&lt;/a&gt;.  I independently tracked that down
to a pylsqpack bug and came up with a reduced test case before realizing
that Pranav P had already been working on it; we then worked together on it
and I uploaded their patch to&amp;nbsp;Debian.&lt;/p&gt;
&lt;p&gt;I fixed various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087781"&gt;aiomysql&lt;/a&gt; (closed with no action&amp;nbsp;needed)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/lazr.uri/-/commit/d4a50b86d6fadc7345a7dc85ef0dbcf854bdaf3b"&gt;lazr.uri&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101045"&gt;m2crypto&lt;/a&gt; (thanks to Sebastian Andrzej&amp;nbsp;Siewior)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/mkdocstrings/-/commit/1c663daa5bee65ac5d4db36bf5f2b7a2e875254a"&gt;mkdocstrings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090106"&gt;mystic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100252"&gt;poetry-plugin-export&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/poetry/-/commit/364c8db9537acf09e69bdfe859d267d0fdfd6002"&gt;poetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101617"&gt;pydantic-extra-types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1097668"&gt;pymilter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1099271"&gt;python-a2wsgi&lt;/a&gt; (&lt;a href="https://github.com/abersheeran/a2wsgi/pull/66"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1099051"&gt;python-anyio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1093017"&gt;python-cymem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-django-timescaledb/-/commit/1527b5ec91656f69c0ac75468b3a56924fdd67ae"&gt;python-django-timescaledb&lt;/a&gt;
  (only partially&amp;nbsp;successful)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-ewokscore/-/commit/cdf90be20bb6d48dfbf8dfb3b5afe302d22503f6"&gt;python-ewokscore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092042"&gt;python-ewoksorange&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-httpx-sse/-/commit/56c64f0199cce1fd4c5262146815b00829376c89"&gt;python-httpx-sse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098875"&gt;python-ml-collections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100276"&gt;python-opt-einsum&lt;/a&gt; (&lt;a href="https://github.com/dgasmith/opt_einsum/pull/250"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090282"&gt;python-passlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101252"&gt;python-pdoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1099498"&gt;python-ppmd&lt;/a&gt; (with a
  &lt;a href="https://salsa.debian.org/python-team/packages/python-ppmd/-/commit/3f18f3e35eac5d2c90cbfe402dabaa0e21cc553c"&gt;follow-up&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092043"&gt;python-processview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1099275"&gt;python-respx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-rsyncmanager/-/compare/debian%2F0.1.3-2.1...debian%2F0.1.3-3"&gt;python-rsyncmanager&lt;/a&gt;
  (contributed upstream:
  &lt;a href="https://gitlab.esrf.fr/payno/rsyncmanager/-/commit/ccc5f66dc702f63753fa5f45b1c3d3d37f879595"&gt;ccc5f66dc7&lt;/a&gt;,
  &lt;a href="https://gitlab.esrf.fr/payno/rsyncmanager/-/commit/51c15ca8d119cffe32b24d26b9686b9877217a1e"&gt;51c15ca8d1&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100289"&gt;python-sphobjinv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1099277"&gt;python-urllib3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098810"&gt;pytrainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/tlv8-python/-/commit/1d386d168d5983537adea903d2963cfd7ba630d6"&gt;tlv8-python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I &lt;a href="https://salsa.debian.org/python-team/packages/python-moto/-/commit/b5ca2ee8cfbc197436b13d88445ee34e7f83864e"&gt;enabled more tests in
python-moto&lt;/a&gt;
and &lt;a href="https://github.com/getmoto/moto/pull/8669"&gt;contributed a supporting fix
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I sponsored Maximilian Engelhardt to &lt;a href="https://bugs.debian.org/1100340"&gt;reintroduce
zope.sqlalchemy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed various odds and ends of&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098888"&gt;catfish: does not start because of a missing&amp;nbsp;dependency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100077"&gt;jupyterhub: creates&amp;nbsp;/usr/alembic.ini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1035201"&gt;pgzero: please add autopkgtests (to add coverage for&amp;nbsp;python3-numpy)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1100081"&gt;pyspread: creates /usr/pyspread/share/applications/ instead of using&amp;nbsp;/usr/share/applications/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1101112"&gt;python-aiosmtpd: python3-aiosmtpd-doc/trixie misses Breaks and Replaces
  for&amp;nbsp;python3-aiosmtpd/bookworm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1078638"&gt;python-dateutil: will &lt;span class="caps"&gt;FTBFS&lt;/span&gt; during trixie support
  period&lt;/a&gt; (&lt;a href="https://github.com/dateutil/dateutil/pull/1422"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082011"&gt;python-passlib: bcrypt&amp;nbsp;warning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1067158"&gt;python-pip: pip3-* manual pages could be&amp;nbsp;aliased&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092252"&gt;python3-deprecation: installs deprecation-2.0.7.egg-info instead of&amp;nbsp;2.1.0-2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095175"&gt;quodlibet: crashes on start if libmodplug1 is not&amp;nbsp;installed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/974496"&gt;reparser: autopkgtest must be marked&amp;nbsp;superficial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I contributed a &lt;a href="https://salsa.debian.org/python-team/tools/dh-python/-/commit/20f7f6767dd7c82feb699d5218427ab2c127326c"&gt;small documentation improvement to
pybuild-autopkgtest(1)&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Rust&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I &lt;a href="https://bugs.debian.org/1088744"&gt;upgraded rust-asn1 to 0.20.0&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Science&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I finally gave in and joined the &lt;a href="https://salsa.debian.org/science-team"&gt;Debian Science
Team&lt;/a&gt; this month, since it often has
a lot of overlap with the Python team, and Freexian maintains several
packages under&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;I fixed a uscan error in hdf5-blosc (maintained by Freexian), and upgraded
it to a new upstream&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1099022"&gt;python-vispy: missing dependency on numpy
abi&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Other bits and&amp;nbsp;pieces&lt;/h2&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1061480"&gt;debconf should automatically be noninteractive if input is
/dev/null&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed a build failure with &lt;span class="caps"&gt;GCC&lt;/span&gt; 15 in
&lt;a href="https://bugs.debian.org/1098195"&gt;yubihsm-shell&lt;/a&gt; (maintained by&amp;nbsp;Freexian).&lt;/p&gt;
&lt;p&gt;Prompted by a &lt;span class="caps"&gt;CI&lt;/span&gt; failure in
&lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;debusine&lt;/a&gt;, I submitted a
large batch of spelling fixes and some improved static analysis to incus
(&lt;a href="https://github.com/lxc/incus/pull/1777"&gt;#1777&lt;/a&gt;,
&lt;a href="https://github.com/lxc/incus/pull/1778"&gt;#1778&lt;/a&gt;) and
&lt;a href="https://github.com/lxc/distrobuilder/pull/910"&gt;distrobuilder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After regaining access to the repository, I fixed &lt;a href="https://gitlab.gnome.org/GNOME/telegnome/-/issues/2"&gt;telegnome: missing app
icon in &amp;#8216;About&amp;#8217;
dialogue&lt;/a&gt; and made a
new 0.3.7&amp;nbsp;release.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in February 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-02.html" rel="alternate"/><published>2025-03-02T13:49:47+00:00</published><updated>2025-03-02T13:49:47+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-03-02:/~cjwatson/blog/activity-2025-02.html</id><summary type="html">&lt;p&gt;OpenSSH security fixes; Python team upstream&amp;nbsp;reporting.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;OpenSSH upstream released
&lt;a href="https://www.openssh.com/releasenotes.html#9.9p2"&gt;9.9p2&lt;/a&gt; with fixes for
&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-26465 and &lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-26466.  I got a heads-up on this in advance from
the Debian security team, and prepared updates for all of testing/unstable,
bookworm (Debian 12), bullseye (Debian 11), buster (Debian 10, &lt;span class="caps"&gt;LTS&lt;/span&gt;), and
stretch (Debian 9, &lt;span class="caps"&gt;ELTS&lt;/span&gt;).  jessie (Debian 8) is also still in &lt;span class="caps"&gt;ELTS&lt;/span&gt; for a few
more months, but wasn&amp;#8217;t affected by either&amp;nbsp;vulnerability.&lt;/p&gt;
&lt;p&gt;Although I&amp;#8217;m not particularly active in the Perl team, I fixed a
&lt;a href="https://bugs.debian.org/1096245"&gt;libnet-ssleay-perl build failure&lt;/a&gt; because
it was blocking openssl from migrating to testing, which in turn was
blocking the above openssh&amp;nbsp;fixes.&lt;/p&gt;
&lt;p&gt;I also sent a minor &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3788"&gt;&lt;code&gt;sshd -T&lt;/code&gt;
fix&lt;/a&gt; upstream, simplified
a number of autopkgtests using the newish &lt;a href="https://bugs.debian.org/906424"&gt;&lt;code&gt;Restrictions:
needs-sudo&lt;/code&gt;&lt;/a&gt; facility, and prepared for
&lt;a href="https://bugs.debian.org/1098760"&gt;removing the obsolete &lt;code&gt;slogin&lt;/code&gt; symlink&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;PuTTY&lt;/h2&gt;
&lt;p&gt;I upgraded to the &lt;a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;new upstream version
0.83&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;GCC&lt;/span&gt; 15 build&amp;nbsp;failures&lt;/h2&gt;
&lt;p&gt;I fixed build failures with &lt;a href="https://gcc.gnu.org/gcc-15/porting_to.html"&gt;&lt;span class="caps"&gt;GCC&lt;/span&gt;
15&lt;/a&gt; in a few&amp;nbsp;packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1096829"&gt;icoutils&lt;/a&gt; (&lt;a href="https://savannah.nongnu.org/bugs/index.php?66812"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1096891"&gt;kali&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1097550"&gt;parted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1097681"&gt;python-setproctitle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098064"&gt;vigor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;A lot of my Python team work is driven by its &lt;a href="https://udd.debian.org/dmd/?email1=team%2Bpython%40tracker.debian.org&amp;amp;nosponsor1=on&amp;amp;email2=&amp;amp;email3=&amp;amp;packages=&amp;amp;ignpackages=&amp;amp;format=html&amp;amp;onlytesting=on"&gt;maintainer
dashboard&lt;/a&gt;.
Now that we&amp;#8217;ve finished the transition to Python 3.13 as the default
version, and inspired by a recent &lt;a href="https://lists.debian.org/debian-devel/2025/02/msg00134.html"&gt;debian-devel thread started by
Santiago&lt;/a&gt;, I
thought it might be worth spending a bit of time on the &amp;#8220;uscan error&amp;#8221;
section.  &lt;a href="https://wiki.debian.org/debian/watch"&gt;&lt;code&gt;uscan&lt;/code&gt;&lt;/a&gt; is typically
scraping upstream web sites to figure out whether new versions are
available, and so it&amp;#8217;s easy for its configuration to become outdated or
broken.  Most of this work is pretty boring, but it can often reveal
situations where we didn&amp;#8217;t even realize that a Debian package was out of
date.  I fixed these&amp;nbsp;packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cssutils (this in particular was very out of date due to a new and active
  upstream maintainer since&amp;nbsp;2021)&lt;/li&gt;
&lt;li&gt;django-assets&lt;/li&gt;
&lt;li&gt;django-celery-email&lt;/li&gt;
&lt;li&gt;django-sass&lt;/li&gt;
&lt;li&gt;django-yarnpkg&lt;/li&gt;
&lt;li&gt;json-tricks&lt;/li&gt;
&lt;li&gt;mercurial-extension-utils&lt;/li&gt;
&lt;li&gt;pydbus&lt;/li&gt;
&lt;li&gt;pydispatcher&lt;/li&gt;
&lt;li&gt;pylint-celery&lt;/li&gt;
&lt;li&gt;pyspread&lt;/li&gt;
&lt;li&gt;pytest-pretty&lt;/li&gt;
&lt;li&gt;python-apptools&lt;/li&gt;
&lt;li&gt;python-django-libsass (&lt;a href="https://github.com/torchbox/django-libsass/pull/59"&gt;contributed a packaging fix
  upstream&lt;/a&gt; in&amp;nbsp;passing)&lt;/li&gt;
&lt;li&gt;python-django-postgres-extra&lt;/li&gt;
&lt;li&gt;python-django-waffle&lt;/li&gt;
&lt;li&gt;python-ephemeral-port-reserve&lt;/li&gt;
&lt;li&gt;python-ifaddr&lt;/li&gt;
&lt;li&gt;python-log-symbols&lt;/li&gt;
&lt;li&gt;python-msrest&lt;/li&gt;
&lt;li&gt;python-msrestazure&lt;/li&gt;
&lt;li&gt;python-netdisco&lt;/li&gt;
&lt;li&gt;python-pathtools&lt;/li&gt;
&lt;li&gt;python-user-agents&lt;/li&gt;
&lt;li&gt;sinntp&lt;/li&gt;
&lt;li&gt;wchartype&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cssutils (&lt;a href="https://github.com/jaraco/cssutils/pull/62"&gt;contributed a packaging tweak
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;django-iconify&lt;/li&gt;
&lt;li&gt;django-sass&lt;/li&gt;
&lt;li&gt;domdf-python-tools&lt;/li&gt;
&lt;li&gt;extra-data (fixing a &lt;a href="https://bugs.debian.org/1095343"&gt;numpy 2.0 failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;flufl.i18n&lt;/li&gt;
&lt;li&gt;json-tricks&lt;/li&gt;
&lt;li&gt;jsonpickle&lt;/li&gt;
&lt;li&gt;mercurial-extension-utils&lt;/li&gt;
&lt;li&gt;mod-wsgi&lt;/li&gt;
&lt;li&gt;nbconvert&lt;/li&gt;
&lt;li&gt;orderly-set&lt;/li&gt;
&lt;li&gt;pydispatcher (&lt;a href="https://github.com/mcfletch/pydispatcher/pull/9"&gt;contributed a Python 3.12 fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pylint&lt;/li&gt;
&lt;li&gt;pytest-rerunfailures&lt;/li&gt;
&lt;li&gt;python-asyncssh&lt;/li&gt;
&lt;li&gt;python-box (&lt;a href="https://github.com/cdgriffith/Box/pull/290"&gt;contributed a packaging fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-charset-normalizer&lt;/li&gt;
&lt;li&gt;python-django-constance&lt;/li&gt;
&lt;li&gt;python-django-guid&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger&lt;/li&gt;
&lt;li&gt;python-django-waffle&lt;/li&gt;
&lt;li&gt;python-djangorestframework-simplejwt&lt;/li&gt;
&lt;li&gt;python-formencode&lt;/li&gt;
&lt;li&gt;python-holidays (&lt;a href="https://github.com/vacanza/holidays/pull/2273"&gt;contributed a test fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-legacy-cgi&lt;/li&gt;
&lt;li&gt;python-marshmallow-polyfield (fixing a &lt;a href="https://bugs.debian.org/1098600"&gt;test
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-model-bakery&lt;/li&gt;
&lt;li&gt;python-mrcz (fixing a &lt;a href="https://bugs.debian.org/1095373"&gt;numpy 2.0
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-netdisco&lt;/li&gt;
&lt;li&gt;python-npe2&lt;/li&gt;
&lt;li&gt;python-persistent&lt;/li&gt;
&lt;li&gt;python-pkginfo (fixing a &lt;a href="https://bugs.debian.org/1098603"&gt;test failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-proto-plus&lt;/li&gt;
&lt;li&gt;python-requests-ntlm&lt;/li&gt;
&lt;li&gt;python-roman&lt;/li&gt;
&lt;li&gt;python-semantic-release&lt;/li&gt;
&lt;li&gt;python-setproctitle&lt;/li&gt;
&lt;li&gt;python-stdlib-list&lt;/li&gt;
&lt;li&gt;python-trustme&lt;/li&gt;
&lt;li&gt;python-typeguard (fixing a &lt;a href="https://bugs.debian.org/1098615"&gt;test
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-tzlocal&lt;/li&gt;
&lt;li&gt;pyzmq&lt;/li&gt;
&lt;li&gt;setuptools-scm&lt;/li&gt;
&lt;li&gt;sqlfluff&lt;/li&gt;
&lt;li&gt;stravalib&lt;/li&gt;
&lt;li&gt;tomopy&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;xhtml2pdf (fixing &lt;a href="https://bugs.debian.org/1084986"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-25885&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;xonsh&lt;/li&gt;
&lt;li&gt;zodbpickle&lt;/li&gt;
&lt;li&gt;zope.deprecation&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In bookworm-backports, I updated python-django to 3:4.2.18-1 (issuing
&lt;a href="https://backports.debian.org/news/BSA-121_Security_Update_for_python-django/"&gt;&lt;span class="caps"&gt;BSA&lt;/span&gt;-121&lt;/a&gt;)
and added new backports of python-django-dynamic-fixture and
python-django-pgtrigger, all of which are dependencies of
&lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;debusine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I went through all the build failures related to python-click 8.2.0 (which
was confusingly &lt;a href="https://github.com/pallets/click/pull/2844"&gt;tagged but not fully released
upstream&lt;/a&gt; and posted an
&lt;a href="https://bugs.debian.org/1098507#17"&gt;analysis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095084"&gt;cython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095019"&gt;dask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095339"&gt;deepdish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094905"&gt;hickle&lt;/a&gt; (&lt;a href="https://github.com/telegraphic/hickle/pull/186"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095356"&gt;mdp&lt;/a&gt; (&lt;a href="https://github.com/mdp-toolkit/mdp-toolkit/pull/105"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098578"&gt;mypy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094040"&gt;pillow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098590"&gt;pynput&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094085"&gt;python-fonticon-fontawesome6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1098602"&gt;python-persistent&lt;/a&gt; (&lt;a href="https://github.com/zopefoundation/persistent/pull/214"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1056874"&gt;python-srsly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I &lt;a href="https://github.com/zopefoundation/zope.testrunner/pull/192"&gt;dropped support for the old &lt;code&gt;setup.py ftest&lt;/code&gt;
command&lt;/a&gt; from
zope.testrunner&amp;nbsp;upstream.&lt;/p&gt;
&lt;p&gt;I fixed various odds and ends of&amp;nbsp;bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/974455"&gt;django-memoize: autopkgtest must be marked&amp;nbsp;superficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1035135"&gt;extra-data: extra-data: please add autopkgtests (to add coverage for&amp;nbsp;python3-numpy)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094910"&gt;fpylll: missing dependency on numpy&amp;nbsp;abi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/974492"&gt;python-box: autopkgtest must be marked&amp;nbsp;superficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1095284"&gt;python-hdmedians: missing dependency on numpy&amp;nbsp;abi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094317"&gt;python-legacy-cgi: missing requirement:&amp;nbsp;openstack-pkg-tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1063372"&gt;python-tzlocal: doesn&amp;#8217;t run any tests during the build or as&amp;nbsp;autopkgtest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091503"&gt;requests: will &lt;span class="caps"&gt;FTBFS&lt;/span&gt; during trixie support
  period&lt;/a&gt; (&lt;a href="https://github.com/psf/requests/pull/6897"&gt;contributed supporting fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1096004"&gt;setuptools-scm: project was renamed from &lt;code&gt;setuptools_scm&lt;/code&gt; to
  &lt;code&gt;setuptools-scm&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Installer&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;Following up on &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-01.html"&gt;last month&lt;/a&gt;, I merged and
uploaded &lt;a href="https://salsa.debian.org/installer-team/debian-installer-utils/-/merge_requests/11"&gt;Helmut&amp;#8217;s &lt;code&gt;/usr&lt;/code&gt;-move
fix&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Qalculate time hacks</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/qalculate-time-hacks.html" rel="alternate"/><published>2025-02-23T20:00:12+00:00</published><updated>2025-02-23T20:00:12+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-02-23:/~cjwatson/blog/qalculate-time-hacks.html</id><summary type="html">&lt;p&gt;Anarcat recently &lt;a href="https://anarc.at/blog/2025-02-08-qalculate-hacks/"&gt;wrote&lt;/a&gt; about &lt;a href="https://qalculate.github.io/"&gt;Qalculate&lt;/a&gt;, and I think I&amp;#8217;m a convert, even though
I&amp;#8217;ve only barely scratched the&amp;nbsp;surface.&lt;/p&gt;
&lt;p&gt;The thing I almost immediately started using it for is time calculations.
When I &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/task-management.html"&gt;started tracking my time&lt;/a&gt;, I
quickly found that &lt;a href="https://timewarrior.net/"&gt;Timewarrior&lt;/a&gt; was good at
keeping all the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Anarcat recently &lt;a href="https://anarc.at/blog/2025-02-08-qalculate-hacks/"&gt;wrote&lt;/a&gt; about &lt;a href="https://qalculate.github.io/"&gt;Qalculate&lt;/a&gt;, and I think I&amp;#8217;m a convert, even though
I&amp;#8217;ve only barely scratched the&amp;nbsp;surface.&lt;/p&gt;
&lt;p&gt;The thing I almost immediately started using it for is time calculations.
When I &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/task-management.html"&gt;started tracking my time&lt;/a&gt;, I
quickly found that &lt;a href="https://timewarrior.net/"&gt;Timewarrior&lt;/a&gt; was good at
keeping all the data I needed, but I often found myself extracting bits of
it and reprocessing it in variously clumsy ways.  For example, I often don&amp;#8217;t
finish a task in one sitting; maybe I take breaks, or I switch back and
forth between a couple of different tasks.  The raw output of &lt;code&gt;timew
summary&lt;/code&gt; is a bit clumsy for this, as it shows each chunk of time spent as
a separate&amp;nbsp;row:&lt;/p&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;timew&lt;span class="w"&gt; &lt;/span&gt;summary&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2025&lt;/span&gt;-02-18&lt;span class="w"&gt; &lt;/span&gt;Debian

&lt;span class="go"&gt;Wk Date       Day Tags                            Start      End    Time   Total&lt;/span&gt;
&lt;span class="go"&gt;W8 2025-02-18 Tue CVE-2025-26465, Debian,       9:41:44 10:24:17 0:42:33&lt;/span&gt;
&lt;span class="go"&gt;                  next, openssh&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, FTBFS with GCC-15,   10:24:17 10:27:12 0:02:55&lt;/span&gt;
&lt;span class="go"&gt;                  icoutils&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, FTBFS with GCC-15,   11:50:05 11:57:25 0:07:20&lt;/span&gt;
&lt;span class="go"&gt;                  kali&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, Upgrade to 0.67,     11:58:21 12:12:41 0:14:20&lt;/span&gt;
&lt;span class="go"&gt;                  python_holidays&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, FTBFS with GCC-15,   12:14:15 12:33:19 0:19:04&lt;/span&gt;
&lt;span class="go"&gt;                  vigor&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, FTBFS with GCC-15,   12:39:02 12:39:38 0:00:36&lt;/span&gt;
&lt;span class="go"&gt;                  python_setproctitle&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, Upgrade to 1.3.4,    12:39:39 12:46:05 0:06:26&lt;/span&gt;
&lt;span class="go"&gt;                  python_setproctitle&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, FTBFS with GCC-15,   12:48:28 12:49:42 0:01:14&lt;/span&gt;
&lt;span class="go"&gt;                  python_setproctitle&lt;/span&gt;
&lt;span class="go"&gt;                  Debian, Upgrade to 3.4.1,    12:52:07 13:02:27 0:10:20 1:44:48&lt;/span&gt;
&lt;span class="go"&gt;                  python_charset_normalizer&lt;/span&gt;

&lt;span class="go"&gt;                                                                         1:44:48&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;So I wrote this Python program to help&amp;nbsp;me:&lt;/p&gt;
&lt;pre class="m-code"&gt;&lt;span class="ch"&gt;#! /usr/bin/python3&lt;/span&gt;

&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;Summarize timewarrior data, grouped and sorted by time spent.&lt;/span&gt;
&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;argparse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RawDescriptionHelpFormatter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;datetime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;operator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;itemgetter&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich.table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;


&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;__doc__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;formatter_class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;RawDescriptionHelpFormatter&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-t&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;--only-total&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;store_true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;range&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;nargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;?&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;:today&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Time range (usually a hint, e.g. :lastweek)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tags to filter by&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;timew&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;export&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;start&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;end&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;
    &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tags&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;only_total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIMPLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Tags&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;itemgetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;divmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;divmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Total time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;02&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;02&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;02&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;summarize-time&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2025&lt;/span&gt;-02-18&lt;span class="w"&gt; &lt;/span&gt;Debian

&lt;span class="go"&gt;  Tags                                                     Time&lt;/span&gt;
&lt;span class="go"&gt; ───────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="go"&gt;  CVE-2025-26465, Debian, next, openssh                 0:42:33&lt;/span&gt;
&lt;span class="go"&gt;  Debian, FTBFS with GCC-15, vigor                      0:19:04&lt;/span&gt;
&lt;span class="go"&gt;  Debian, Upgrade to 0.67, python_holidays              0:14:20&lt;/span&gt;
&lt;span class="go"&gt;  Debian, Upgrade to 3.4.1, python_charset_normalizer   0:10:20&lt;/span&gt;
&lt;span class="go"&gt;  Debian, FTBFS with GCC-15, kali                       0:07:20&lt;/span&gt;
&lt;span class="go"&gt;  Debian, Upgrade to 1.3.4, python_setproctitle         0:06:26&lt;/span&gt;
&lt;span class="go"&gt;  Debian, FTBFS with GCC-15, icoutils                   0:02:55&lt;/span&gt;
&lt;span class="go"&gt;  Debian, FTBFS with GCC-15, python_setproctitle        0:01:50&lt;/span&gt;

&lt;span class="go"&gt;Total time: 01:44:48&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Much nicer.  But that only helps with some of my reporting.  At the end of a
month, I have to work out how much time to bill Freexian for and fill out a
timesheet, and for various reasons those queries don&amp;#8217;t correspond to single
&lt;code&gt;timew&lt;/code&gt; tags: they sometimes correspond to the sum of all time spent on
multiple tags, or to the time spent on one tag minus the time spent on
another tag, or similar.  As a result I quite often have to do basic
arithmetic on time intervals; but that&amp;#8217;s surprisingly annoying!  I didn&amp;#8217;t
previously have good tools for that, and was reduced to doing things like
&lt;code&gt;str(timedelta(hours=..., minutes=..., seconds=...) + ...)&lt;/code&gt; in Python,
which gets old&amp;nbsp;fast.&lt;/p&gt;
&lt;p&gt;Instead:&lt;/p&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;qalc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;62:46:30 - 51:02:42 to time&amp;#39;&lt;/span&gt;
&lt;span class="gp gp-VirtualEnv"&gt;(225990 / 3600)&lt;/span&gt; &lt;span class="go"&gt;− (183762 / 3600) = 11:43:48&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;I also often want to work out how much of my time I&amp;#8217;ve spent on Debian work
this month so far, since Freexian pays me for &lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;up to 20% of my work time on
Debian&lt;/a&gt;; if I&amp;#8217;m
under that then I might want to prioritize more Debian projects, and if I&amp;#8217;m
over then I should be prioritizing more Freexian projects as otherwise I&amp;#8217;m
not going to get paid for that&amp;nbsp;time.&lt;/p&gt;
&lt;pre class="m-console"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;summarize-time&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;:month&lt;span class="w"&gt; &lt;/span&gt;Freexian
&lt;span class="go"&gt;Total time: 69:19:42&lt;/span&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;summarize-time&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;:month&lt;span class="w"&gt; &lt;/span&gt;Debian
&lt;span class="go"&gt;Total time: 24:05:30&lt;/span&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;qalc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;24:05:30 / (24:05:30 + 69:19:42) to %&amp;#39;&lt;/span&gt;
&lt;span class="gp gp-VirtualEnv"&gt;(86730 / 3600)&lt;/span&gt; &lt;span class="go"&gt;/ ((86730 / 3600) + (249582 / 3600)) ≈ 25.78855349%&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;I love&amp;nbsp;it.&lt;/p&gt;
</content><category term="debian"/><category term="columbiform"/><category term="debian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in January 2025</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2025-01.html" rel="alternate"/><published>2025-02-02T19:48:40+00:00</published><updated>2025-02-02T19:48:40+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-02-02:/~cjwatson/blog/activity-2025-01.html</id><summary type="html">&lt;p&gt;Python 3.13 as default; about 45 &lt;span class="caps"&gt;RC&lt;/span&gt; bugs&amp;nbsp;fixed.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  If you appreciate this sort of work and are at a company that
uses Debian, have a look to see whether you can pay for any of
&lt;a href="https://www.freexian.com/"&gt;Freexian&lt;/a&gt;&amp;#8216;s services; as well as the direct
benefits, that revenue stream helps to keep Debian development sustainable
for me and &lt;a href="https://www.freexian.com/about/team/"&gt;several other lovely
people&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;We finally made Python 3.13 the default version in testing!  I fixed various
bugs that got in the way of&amp;nbsp;this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092748"&gt;dnarrange&lt;/a&gt; (&lt;a href="https://github.com/mcfrith/dnarrange/pull/2"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084703"&gt;docker-compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092519"&gt;ionit&lt;/a&gt; (&lt;a href="https://github.com/bdrung/ionit/pull/3"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084602"&gt;nbclassic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092753"&gt;pymilter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092754"&gt;pyspf&lt;/a&gt; (&lt;a href="https://github.com/sdgathman/pyspf/pull/42"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082209"&gt;python-django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092547"&gt;python-handy-archives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094719"&gt;sinntp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092796"&gt;wireless-regdb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As with &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-12.html"&gt;last month&lt;/a&gt;, I fixed a few more
build regressions due to the removal of a deprecated &lt;code&gt;intersphinx_mapping&lt;/code&gt;
syntax in Sphinx&amp;nbsp;8.0:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090099"&gt;jupyter-console&lt;/a&gt; (&lt;a href="https://github.com/jupyter/jupyter_console/pull/301"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090141"&gt;python-ewmh&lt;/a&gt; (&lt;a href="https://salsa.debian.org/python-team/packages/python-ewmh/-/merge_requests/2"&gt;reviewed patch from a
  contributor&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090144"&gt;python-gplearn&lt;/a&gt; (&lt;a href="https://github.com/trevorstephens/gplearn/pull/302"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ported a few packages to Django&amp;nbsp;5.1:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;django-sitetree (thanks to an &lt;a href="https://launchpadlibrarian.net/764907004/django-sitetree_1.18.0+dfsg-2_1.18.0+dfsg-2ubuntu1.diff.gz"&gt;Ubuntu
  patch&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-parler (thanks to an &lt;a href="https://launchpadlibrarian.net/764919408/python-django-parler_2.3-3_2.3-3ubuntu1.diff.gz"&gt;Ubuntu&amp;nbsp;patch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ported &lt;a href="https://bugs.debian.org/1090356"&gt;python-pypump&lt;/a&gt; to IPython&amp;nbsp;8.0.&lt;/p&gt;
&lt;p&gt;I fixed python-datamodel-code-generator to handle isort 6, and &lt;a href="https://github.com/koxudaxi/datamodel-code-generator/pull/2289"&gt;contributed
that
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed some packages to tolerate future versions of dh-python that will
drop their dependency on&amp;nbsp;python3-setuptools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080564"&gt;cerealizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080897"&gt;pyinotify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080861"&gt;pyspf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080749"&gt;python-holidays&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I removed the old &lt;a href="https://bugs.debian.org/1038295"&gt;python-celery-common transitional
package&lt;/a&gt; from celery, since nothing in
Debian needs it any&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;I fixed or helped to fix various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094076"&gt;awesomeversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094077"&gt;django-graphiql-debug-toolbar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094053"&gt;django-iconify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090220"&gt;flask-sqlalchemy&lt;/a&gt; (&lt;a href="https://github.com/pallets-eco/flask-sqlalchemy/pull/1380"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090225"&gt;freezegun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090247"&gt;napari&lt;/a&gt; (somewhat inconclusive, but I
  contributed fixes upstream to
  &lt;a href="https://github.com/napari/napari/pull/7479"&gt;napari&lt;/a&gt; and
  &lt;a href="https://github.com/napari/npe2/pull/368"&gt;npe2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092867"&gt;pyglet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094112"&gt;python-construct-classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1094095"&gt;python-django-guid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090285"&gt;python-pyfakefs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090168"&gt;python-ring-doorbell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1057939"&gt;recommonmark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092352"&gt;spectral-cube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091951"&gt;sphinx&lt;/a&gt; (&lt;a href="https://github.com/sphinx-doc/sphinx/pull/13224"&gt;helped with an upstream
  fix&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090307"&gt;sphinxcontrib-openapi&lt;/a&gt; (&lt;a href="https://github.com/sphinx-contrib/openapi/pull/164"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091952"&gt;sqlfluff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1092532"&gt;terminator&lt;/a&gt; (&lt;a href="https://github.com/gnome-terminator/terminator/pull/986"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091357"&gt;trac-wikiprint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087334"&gt;vcr.py&lt;/a&gt; (&lt;a href="https://github.com/kevin1024/vcrpy/issues/905#issuecomment-2619147042"&gt;investigated and reported
  findings
  upstream&lt;/a&gt;,
  confirming that disabling these tests in the Debian packaging seems
  reasonable for&amp;nbsp;now)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;buildbot&lt;/li&gt;
&lt;li&gt;cloudpickle&lt;/li&gt;
&lt;li&gt;dask (fixing a &lt;a href="https://bugs.debian.org/1088234"&gt;Python 3.13 failure&lt;/a&gt; and
  working around a &lt;a href="https://bugs.debian.org/1091016"&gt;build failure due to&amp;nbsp;sphinx-book-theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;distributed (fixing a &lt;a href="https://bugs.debian.org/1088286"&gt;Python 3.13
  failure&lt;/a&gt;; also &lt;a href="https://github.com/dask/distributed/pull/8975"&gt;contributed a fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;importlib-resources (fixing a &lt;a href="https://bugs.debian.org/1076534"&gt;test failure on
  s390x&lt;/a&gt; and a &lt;a href="https://bugs.debian.org/1090233"&gt;test failure on all
  architectures&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;nbconvert&lt;/li&gt;
&lt;li&gt;psycopg3&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pydoctor&lt;/li&gt;
&lt;li&gt;pypandoc&lt;/li&gt;
&lt;li&gt;python-argcomplete&lt;/li&gt;
&lt;li&gt;python-cai&lt;/li&gt;
&lt;li&gt;python-colormap (fixing a &lt;a href="https://bugs.debian.org/1094084"&gt;build failure with poetry-core
  2.0&lt;/a&gt;, for which I &lt;a href="https://github.com/cokelaer/colormap/pull/26"&gt;contributed a fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-guid&lt;/li&gt;
&lt;li&gt;python-easydev (fixing a &lt;a href="https://bugs.debian.org/1094057"&gt;build failure with poetry-core
  2.0&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-holidays&lt;/li&gt;
&lt;li&gt;python-launchpadlib&lt;/li&gt;
&lt;li&gt;python-limits&lt;/li&gt;
&lt;li&gt;python-model-bakery&lt;/li&gt;
&lt;li&gt;python-openapi-schema-validator&lt;/li&gt;
&lt;li&gt;python-pathvalidate&lt;/li&gt;
&lt;li&gt;python-pyftpdlib&lt;/li&gt;
&lt;li&gt;python-quart-trio&lt;/li&gt;
&lt;li&gt;python-urllib3 (&lt;a href="https://github.com/urllib3/urllib3/pull/3547"&gt;contributed a test fix
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-telethon&lt;/li&gt;
&lt;li&gt;python-webob (fixing &lt;a href="https://bugs.debian.org/1078879"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-42353&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;responses&lt;/li&gt;
&lt;li&gt;restrictedpython (fixing &lt;a href="https://bugs.debian.org/1084057"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-47532&lt;/a&gt;
  and &lt;a href="https://bugs.debian.org/1094026"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2025-22153&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;sqlfluff&lt;/li&gt;
&lt;li&gt;vcr.py (fixing a &lt;a href="https://bugs.debian.org/1093445"&gt;build failure with python-urllib3&amp;nbsp;2.3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;xonsh (fixing a &lt;a href="https://bugs.debian.org/1092797"&gt;Python 3.13 failure&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rust&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1094282"&gt;rust-pyo3-ffi&lt;/a&gt; to avoid explicit
Python version dependencies that were getting in the way of making Python
3.13 the default&amp;nbsp;version.&lt;/p&gt;
&lt;h2&gt;Security tools packaging&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I uploaded libevt to fix a &lt;a href="https://bugs.debian.org/1091579"&gt;build failure on
i386&lt;/a&gt; and to &lt;a href="https://bugs.debian.org/1080920"&gt;tolerate future versions of
dh-python that will drop their dependency on
python3-setuptools&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Installer&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I helped with some testing of a &lt;a href="https://salsa.debian.org/installer-team/debian-installer-utils/-/merge_requests/11"&gt;debian-installer-utils
patch&lt;/a&gt;
as part of the &lt;code&gt;/usr&lt;/code&gt; move.  I need to get around to uploading this, since
it looks &lt;span class="caps"&gt;OK&lt;/span&gt;&amp;nbsp;now.&lt;/p&gt;
&lt;h2&gt;Other small&amp;nbsp;things&lt;/h2&gt;
&lt;p&gt;Helmut Grohne reached out for help debugging a multi-arch coinstallability
problem (you know it&amp;#8217;s going to be complicated when even &lt;em&gt;Helmut&lt;/em&gt; can&amp;#8217;t
figure it out on his own &amp;#8230;) in
&lt;a href="https://bugs.debian.org/1093594"&gt;binutils&lt;/a&gt;, and we had a call about&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;I reviewed and applied a &lt;a href="https://bugs.debian.org/1083078"&gt;new Romanian
translation&lt;/a&gt; of debconf&amp;#8217;s manual&amp;nbsp;pages.&lt;/p&gt;
&lt;p&gt;I did my twice-yearly refresh of debmirror&amp;#8217;s &lt;a href="https://salsa.debian.org/debian/debmirror/-/blob/master/mirror_size"&gt;&lt;code&gt;mirror_size&lt;/code&gt;
documentation&lt;/a&gt;,
and applied a &lt;a href="https://bugs.debian.org/865024"&gt;contribution to improve the example
&lt;code&gt;debmirror.conf&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed an arguable &lt;a href="https://bugs.debian.org/1093431"&gt;preprocessor string handling
bug&lt;/a&gt; in man-db, and applied a &lt;a href="https://gitlab.com/man-db/man-db/-/merge_requests/12"&gt;fix for
out-of-tree builds&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in December 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-12.html" rel="alternate"/><published>2025-01-02T00:16:14+00:00</published><updated>2025-01-02T00:16:14+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2025-01-02:/~cjwatson/blog/activity-2024-12.html</id><summary type="html">&lt;p&gt;OpenSSH, debconf, Python 3.13; about 70 &lt;span class="caps"&gt;RC&lt;/span&gt; bugs&amp;nbsp;fixed.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian, as well as one direct donation via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;&amp;nbsp;(thanks!).&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I issued a &lt;a href="https://tracker.debian.org/news/1592591/accepted-openssh-192p1-2deb12u4-source-into-proposed-updates/"&gt;bookworm
update&lt;/a&gt;
with a number of fixes that had accumulated over the last year, especially
fixing &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; key exchange which
&lt;a href="https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/2053146"&gt;was&lt;/a&gt;
&lt;a href="https://bugs.debian.org/1041521"&gt;quite&lt;/a&gt;
&lt;a href="https://bugs.debian.org/1088248"&gt;broken&lt;/a&gt; in&amp;nbsp;bookworm.&lt;/p&gt;
&lt;h2&gt;base-passwd&lt;/h2&gt;
&lt;p&gt;A few months ago, the adduser maintainer started a discussion with me (as
the base-passwd maintainer) and the shadow maintainer about bringing all
three source packages under one team, since they often need to cooperate on
things like user and group names.  I agreed, but hadn&amp;#8217;t got round to doing
anything about it until recently.  I&amp;#8217;ve now officially moved it under team&amp;nbsp;maintenance.&lt;/p&gt;
&lt;h2&gt;debconf&lt;/h2&gt;
&lt;p&gt;Gioele Barabucci has been working on eliminating duplicated code between
debconf and cdebconf, ultimately with the goal of migrating to cdebconf
(which I&amp;#8217;m not sure I&amp;#8217;m convinced of as a goal, but if we can make
improvements to both packages as part of working towards it then there&amp;#8217;s no
harm in that).  I finally got round to reviewing and merging confmodule
changes in each of
&lt;a href="https://salsa.debian.org/pkg-debconf/debconf/-/merge_requests/13"&gt;debconf&lt;/a&gt;
and
&lt;a href="https://salsa.debian.org/installer-team/cdebconf/-/merge_requests/19"&gt;cdebconf&lt;/a&gt;.
This caused an &lt;a href="https://bugs.debian.org/1091366"&gt;installer regression&lt;/a&gt; due
to a weirdness in cdebconf-udeb&amp;#8217;s packaging, which I fixed - sorry about&amp;nbsp;that!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve also been dealing with a few patch submissions that had been in my
queue for a long time, but more on that next month if all goes&amp;nbsp;well.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CI&lt;/span&gt;&amp;nbsp;issues&lt;/h2&gt;
&lt;p&gt;I noticed and fixed a &lt;a href="https://salsa.debian.org/ci-team/autopkgtest/-/merge_requests/497"&gt;problem with &lt;code&gt;Restrictions:
needs-sudo&lt;/code&gt;&lt;/a&gt;
in&amp;nbsp;autopkgtest.&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://salsa.debian.org/salsa-ci-team/pipeline/-/merge_requests/572"&gt;broken aptly
images&lt;/a&gt;
in the Salsa &lt;span class="caps"&gt;CI&lt;/span&gt;&amp;nbsp;pipeline.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-11.html"&gt;Last month&lt;/a&gt;, I mentioned some progress on
sorting out the multipart vs. python-multipart name conflict in Debian
(&lt;a href="https://bugs.debian.org/1085728"&gt;#1085728&lt;/a&gt;), and said that I thought we&amp;#8217;d
be able to finish it soon.  I was right!  We got it all done this&amp;nbsp;month:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088642"&gt;gavodachs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088647"&gt;matrix-synapse&lt;/a&gt; (uploaded by Andrej&amp;nbsp;Shadura)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088869"&gt;Packaged&amp;nbsp;multipart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/python-wadllib/-/commit/a8a9d7a5b2473099138295258bb7e73098632dfa"&gt;Converted python-wadllib to use the packaged version of&amp;nbsp;multipart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082321"&gt;Made trac (build-)depend on python3-multipart, fixing build failures in
  trac-customfieldadmin and&amp;nbsp;trac-wysiwyg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Python 3.13 transition continues, and last month we were able to add it
to the supported Python versions in testing.  (The next step will be to make
it the default.)  I fixed lots of problems in aid of this,&amp;nbsp;including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082047"&gt;audioread&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1089102"&gt;celery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088224"&gt;cloud-sptheme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088246"&gt;djangorestframework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088247"&gt;dominate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090766"&gt;fenics-basix&lt;/a&gt; (investigated and
  suggested a fix, although it hasn&amp;#8217;t yet been&amp;nbsp;uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088315"&gt;ipykernel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088322"&gt;ipython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088366"&gt;jupyter-server&lt;/a&gt; (&lt;a href="https://github.com/jupyter-server/jupyter_server/pull/1477"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088752"&gt;mdp&lt;/a&gt; (&lt;a href="https://github.com/mdp-toolkit/mdp-toolkit/pull/104"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088763"&gt;pastescript&lt;/a&gt; (&lt;a href="https://github.com/pasteorg/pastescript/pull/15"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088768"&gt;pypandoc&lt;/a&gt; (&lt;a href="https://github.com/JessicaTegner/pypandoc/pull/384"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082193"&gt;python-aiosmtpd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1089026"&gt;python-cheroot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090275"&gt;python-hjson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090278"&gt;python-miio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082259"&gt;python-pyramid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1089664"&gt;python-trustme&lt;/a&gt; (uploaded by Robie&amp;nbsp;Basak)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082290"&gt;rich&lt;/a&gt; (investigated and tested; uploaded
  by Sandro&amp;nbsp;Tosi)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1089058"&gt;supervisor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1089068"&gt;tomopy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sphinx 8.0 &lt;a href="https://github.com/sphinx-doc/sphinx/pull/12083"&gt;removed some old &lt;code&gt;intersphinx_mapping&lt;/code&gt;
syntax&lt;/a&gt; which turned out to
still be in use by many packages in Debian.  The fixes for this were
individually trivial, but there were a lot of&amp;nbsp;them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090088"&gt;alot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090097"&gt;dot2tex&lt;/a&gt; (&lt;a href="https://github.com/xyz2tex/dot2tex/pull/116"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090098"&gt;flask-paginate&lt;/a&gt; (&lt;a href="https://github.com/lixxu/flask-paginate/pull/115"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090234"&gt;ipython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090103"&gt;klepto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090111"&gt;nose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090113"&gt;pathos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090087"&gt;pox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090116"&gt;ppft&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090263"&gt;psycopg3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090117"&gt;pybindgen&lt;/a&gt; (&lt;a href="https://github.com/gjcarneiro/pybindgen/pull/56"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090118"&gt;pyina&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090122"&gt;pyrr&lt;/a&gt; (&lt;a href="https://github.com/adamlwgriffiths/Pyrr/pull/128"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090127"&gt;pytest-mpi&lt;/a&gt; (&lt;a href="https://github.com/aragilar/pytest-mpi/pull/53"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090129"&gt;python-aiohttp-security&lt;/a&gt; (&lt;a href="https://github.com/aio-libs/aiohttp-security/pull/832"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090128"&gt;python-aiohttp-session&lt;/a&gt; (&lt;a href="https://github.com/aio-libs/aiohttp-session/pull/1047"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090131"&gt;python-anyqt&lt;/a&gt; (&lt;a href="https://github.com/ales-erjavec/anyqt/pull/8"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090133"&gt;python-argon2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090135"&gt;python-cai&lt;/a&gt; (&lt;a href="https://github.com/Benjamin-Lee/CodonAdaptationIndex/pull/16"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090138"&gt;python-django-analytical&lt;/a&gt; (&lt;a href="https://github.com/jazzband/django-analytical/pull/230"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090146"&gt;python-iptables&lt;/a&gt; (&lt;a href="https://github.com/ldx/python-iptables/pull/349"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090152"&gt;python-nacl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090157"&gt;python-pygtrie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090156"&gt;python-proto-plus&lt;/a&gt; (&lt;a href="https://github.com/googleapis/proto-plus-python/pull/509"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090160"&gt;python-requests-toolbelt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090163"&gt;python-tinycss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090164"&gt;python-whoosh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090172"&gt;symmetrize&lt;/a&gt; (&lt;a href="https://github.com/RealPolitiX/symmetrize/pull/23"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090175"&gt;vcr.py&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090177"&gt;wtforms-components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090179"&gt;wtforms-test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090178"&gt;yoyo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090180"&gt;zope.deferredimport&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I found that twisted 24.11.0 broke tests in
&lt;a href="https://salsa.debian.org/python-team/packages/buildbot/-/commit/e6318ddf6be6db950ea8e07041f0115af1064e1d"&gt;buildbot&lt;/a&gt;
and
&lt;a href="https://salsa.debian.org/python-team/packages/wokkel/-/commit/a386fb1a35922e1ebd32e05e9a760b7e971a6b42"&gt;wokkel&lt;/a&gt;,
and fixed&amp;nbsp;those.&lt;/p&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1089014"&gt;python-flatdict&lt;/a&gt;, needed for a
new upstream version of&amp;nbsp;python-semantic-release.&lt;/p&gt;
&lt;p&gt;I tracked down a &lt;a href="https://bugs.debian.org/1088043"&gt;test failure&lt;/a&gt; in
vdirsyncer (which &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/new-address-book.html"&gt;I&amp;#8217;ve been using for some
years&lt;/a&gt;, but had never previously needed to
modify) and &lt;a href="https://github.com/pimutils/vdirsyncer/pull/1153"&gt;contributed a fix
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed some packages to tolerate future versions of dh-python that will
drop their dependency on&amp;nbsp;python3-setuptools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080705"&gt;pyfribidi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1080709"&gt;pylibmc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1072850"&gt;python-mkdocs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1018341"&gt;django-cte&lt;/a&gt; to remove a
build-dependency on the obsolete python3-nose&amp;nbsp;package.&lt;/p&gt;
&lt;p&gt;I added Django 5.1 support to django-polymorphic.  (There are a number of
other packages that still need work&amp;nbsp;here.)&lt;/p&gt;
&lt;p&gt;I fixed various other build/test&amp;nbsp;failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1091135"&gt;black&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;datalad-next: &lt;a href="https://bugs.debian.org/1080969"&gt;#1080969&lt;/a&gt; and
  &lt;a href="https://bugs.debian.org/1088038"&gt;#1088038&lt;/a&gt; (&lt;a href="https://github.com/datalad/datalad-next/pull/768"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090768"&gt;dipy&lt;/a&gt; (uploaded by Andreas&amp;nbsp;Tille)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087453"&gt;pyfribidi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090196"&gt;pylibmc&lt;/a&gt;, fixing a build failure in&amp;nbsp;cachelib&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1076908"&gt;pympress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/python-team/packages/pytest-forked/-/commit/01697be93cdef9bcb751ba4cc8bfc13ec29cb26b"&gt;pytest-forked&lt;/a&gt;
  (&lt;a href="https://github.com/pytest-dev/pytest-forked/pull/93"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-mongomock:
  &lt;a href="https://salsa.debian.org/python-team/packages/python-mongomock/-/commit/c03f91b51048e87d20035cbabd0a89bd6f041cf8"&gt;c03f91b51048&lt;/a&gt;
  and
  &lt;a href="https://salsa.debian.org/python-team/packages/python-mongomock/-/commit/c485fb8fef2383b35cd00b4f14f7c1af9e6438b4"&gt;c485fb8fef23&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1090281"&gt;python-nox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aioftp&lt;/li&gt;
&lt;li&gt;alot&lt;/li&gt;
&lt;li&gt;astroid&lt;/li&gt;
&lt;li&gt;buildbot&lt;/li&gt;
&lt;li&gt;cloudpickle (fixing a &lt;a href="https://bugs.debian.org/1088227"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;django-countries&lt;/li&gt;
&lt;li&gt;django-sass-processor&lt;/li&gt;
&lt;li&gt;djoser (fixing &lt;a href="https://bugs.debian.org/1089915"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-21543&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ipython&lt;/li&gt;
&lt;li&gt;jsonpickle&lt;/li&gt;
&lt;li&gt;lazr.delegates&lt;/li&gt;
&lt;li&gt;loguru (fixing a &lt;a href="https://bugs.debian.org/1088751"&gt;Python 3.13 failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;netmiko&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pydoctor&lt;/li&gt;
&lt;li&gt;pygresql&lt;/li&gt;
&lt;li&gt;pylint (fixing Python 3.13 failures
  &lt;a href="https://bugs.debian.org/1089758"&gt;#1089758&lt;/a&gt; and
  &lt;a href="https://bugs.debian.org/1091029"&gt;#1091029&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pypandoc (fixing a &lt;a href="https://bugs.debian.org/1083204"&gt;Python 3.12 warning&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-aiohttp (fixing &lt;a href="https://bugs.debian.org/1088108"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-52303&lt;/a&gt;
  and &lt;a href="https://bugs.debian.org/1088109"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-52304&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;python-aiohttp-security&lt;/li&gt;
&lt;li&gt;python-argcomplete&lt;/li&gt;
&lt;li&gt;python-asyncssh&lt;/li&gt;
&lt;li&gt;python-click&lt;/li&gt;
&lt;li&gt;python-cytoolz&lt;/li&gt;
&lt;li&gt;python-jira (fixing a &lt;a href="https://bugs.debian.org/1084531"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-limits&lt;/li&gt;
&lt;li&gt;python-line-profiler&lt;/li&gt;
&lt;li&gt;python-mkdocs&lt;/li&gt;
&lt;li&gt;python-model-bakery&lt;/li&gt;
&lt;li&gt;python-pgspecial&lt;/li&gt;
&lt;li&gt;python-pyramid (fixing &lt;a href="https://bugs.debian.org/1050740"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-40587&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pythonjsonlogger&lt;/li&gt;
&lt;li&gt;python-semantic-release&lt;/li&gt;
&lt;li&gt;python-utils&lt;/li&gt;
&lt;li&gt;python-venusian&lt;/li&gt;
&lt;li&gt;pyupgrade&lt;/li&gt;
&lt;li&gt;pyzmq&lt;/li&gt;
&lt;li&gt;quart&lt;/li&gt;
&lt;li&gt;six&lt;/li&gt;
&lt;li&gt;sqlparse&lt;/li&gt;
&lt;li&gt;twisted&lt;/li&gt;
&lt;li&gt;vcr.py&lt;/li&gt;
&lt;li&gt;vulture&lt;/li&gt;
&lt;li&gt;yoyo&lt;/li&gt;
&lt;li&gt;zope.configuration&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I updated the team&amp;#8217;s &lt;a href="https://wiki.debian.org/Python/LibraryStyleGuide"&gt;library style
guide&lt;/a&gt; to remove material
related to Python 2 and early versions of Python 3, which is no longer
relevant to any current Python packaging&amp;nbsp;work.&lt;/p&gt;
&lt;h2&gt;Other Python upstream&amp;nbsp;work&lt;/h2&gt;
&lt;p&gt;I happened to notice a &lt;a href="https://github.com/twisted/twisted/issues/12396"&gt;Twisted upstream
issue&lt;/a&gt; requesting the
removal of the deprecated &lt;code&gt;twisted.internet.defer.returnValue&lt;/code&gt;, realized it
was still used in many places in Debian, and went on a &lt;span class="caps"&gt;PR&lt;/span&gt;-filing spree
informed by &lt;a href="https://codesearch.debian.net/"&gt;codesearch&lt;/a&gt; to try to reduce
the future impact of such a change on&amp;nbsp;Debian:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/warner/foolscap/pull/114"&gt;foolscap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gnome-keysign/gnome-keysign/pull/122"&gt;gnome-keysign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/magic-wormhole/magic-wormhole/pull/564"&gt;magic-wormhole&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/element-hq/synapse/pull/18020"&gt;matrix-synapse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/crossbario/autobahn-python/pull/1651"&gt;python-autobahn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/testing-cabal/testtools/pull/413"&gt;python-testtools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/twisted/treq/pull/404"&gt;python-treq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;tahoe-lafs: &lt;a href="https://github.com/twisted/twisted/pull/12395#issuecomment-2529868689"&gt;Inconclusive&amp;nbsp;investigation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/meejah/txtorcon/pull/403"&gt;txtorcon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other small&amp;nbsp;fixes&lt;/h2&gt;
&lt;p&gt;Santiago Vila has been &lt;a href="https://people.debian.org/~sanvila/make-shuffle/"&gt;building the archive with &lt;code&gt;make
--shuffle&lt;/code&gt;&lt;/a&gt; (also see &lt;a href="https://trofi.github.io/posts/238-new-make-shuffle-mode.html"&gt;its
author&amp;#8217;s
explanation&lt;/a&gt;).
I fixed associated bugs in cccc (&lt;a href="https://github.com/sarnold/cccc/pull/46"&gt;contributed
upstream&lt;/a&gt;), groff, and&amp;nbsp;spectemu.&lt;/p&gt;
&lt;p&gt;I backported an upstream patch to putty to fix &lt;a href="https://bugs.debian.org/1087844"&gt;undefined behaviour that
affected use of the &amp;#8220;small keypad&amp;#8221;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I removed groff&amp;#8217;s &lt;code&gt;Recommends: libpaper1&lt;/code&gt;
(&lt;a href="https://bugs.debian.org/1091375"&gt;#1091375&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1091376"&gt;#1091376&lt;/a&gt;), since it isn&amp;#8217;t currently all
that useful and was getting in the way of a transition to libpaper2.  I
filed an &lt;a href="https://savannah.gnu.org/bugs/?66597"&gt;upstream bug&lt;/a&gt; suggesting
better integration in this&amp;nbsp;area.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in November 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-11.html" rel="alternate"/><published>2024-12-01T15:00:22+00:00</published><updated>2024-12-01T15:00:22+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-12-01:/~cjwatson/blog/activity-2024-11.html</id><summary type="html">&lt;p&gt;MiniDebConf Toulouse, multipart, Python 3.13, and&amp;nbsp;more.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Most of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Conferences&lt;/h2&gt;
&lt;p&gt;I attended &lt;a href="https://wiki.debian.org/DebianEvents/fr/2024/Toulouse"&gt;MiniDebConf Toulouse
2024&lt;/a&gt;, and the
MiniDebCamp before it.  Most of my time was spent with the Freexian folks
working on debusine; Stefano gave a
&lt;a href="https://toulouse2024.mini.debconf.org/talks/3-using-debusine-to-automate-your-qa/"&gt;talk&lt;/a&gt;
about its current status with a live demo (frantically fixed up over the
previous couple of days, as is traditional) and with me and others helping
to answer questions at the end.  I also caught up with some people I haven&amp;#8217;t
seen in ages, ate a variety of delicious cheeses, and generally had a good
time.  Many thanks to the
&lt;a href="https://toulouse2024.mini.debconf.org/about/org/"&gt;organizers&lt;/a&gt; and
&lt;a href="https://toulouse2024.mini.debconf.org/sponsors/"&gt;sponsors&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;After the conference, Freexian collaborators spent a day and a half doing
some planning for next year, and then went for an afternoon visiting the
&lt;a href="https://www.cite-espace.com/"&gt;Cité de l&amp;#8217;espace&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Rust&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded these packages to new upstream versions, as part of upgrading
pydantic and&amp;nbsp;rpds-py:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rust-archery&lt;/li&gt;
&lt;li&gt;rust-jiter (noticing an &lt;a href="https://github.com/pydantic/jiter/pull/169"&gt;upstream test
  bug&lt;/a&gt; in the&amp;nbsp;process)&lt;/li&gt;
&lt;li&gt;rust-pyo3 (fixing &lt;a href="https://bugs.debian.org/1085296"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-9979&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;rust-pyo3-build-config&lt;/li&gt;
&lt;li&gt;rust-pyo3-ffi&lt;/li&gt;
&lt;li&gt;rust-pyo3-macros&lt;/li&gt;
&lt;li&gt;rust-pyo3-macros-backend&lt;/li&gt;
&lt;li&gt;rust-regex&lt;/li&gt;
&lt;li&gt;rust-regex-automata&lt;/li&gt;
&lt;li&gt;rust-regex&lt;/li&gt;
&lt;li&gt;rust-serde&lt;/li&gt;
&lt;li&gt;rust-serde-derive&lt;/li&gt;
&lt;li&gt;rust-serde-json&lt;/li&gt;
&lt;li&gt;rust-speedate&lt;/li&gt;
&lt;li&gt;rust-triomphe&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-10.html"&gt;Last month&lt;/a&gt;, I mentioned that we still need
to work out what to do about the multipart vs. python-multipart name
conflict in Debian (&lt;a href="https://bugs.debian.org/1085728"&gt;#1085728&lt;/a&gt;).  We
eventually managed to come up with an agreed plan; Sandro has uploaded a
renamed binary package to experimental, and I&amp;#8217;ve begun work on converting
reverse-dependencies
(&lt;a href="https://tracker.debian.org/news/1588976/accepted-asgi-csrf-011-1-source-into-unstable/"&gt;asgi-csrf&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1088569"&gt;fastapi&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1088646"&gt;python-curies&lt;/a&gt;, and
&lt;a href="https://tracker.debian.org/news/1588738/accepted-starlette-0413-2-source-into-unstable/"&gt;starlette&lt;/a&gt;
done so far).  There&amp;#8217;s a bit more still to do, but I expect we can finish it&amp;nbsp;soon.&lt;/p&gt;
&lt;p&gt;I fixed problems related to adding Python 3.13 support&amp;nbsp;in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084643"&gt;coreapi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084626"&gt;git-repo-updater&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1084729"&gt;offlineimap3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082145"&gt;ptyprocess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082191"&gt;pytest-testinfra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082213"&gt;python-formencode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082221"&gt;python-iniparse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1081625"&gt;python-line-profiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082239"&gt;python-parameterized&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082269"&gt;python-sdjson&lt;/a&gt; (&lt;a href="https://github.com/domdfcoding/singledispatch-json/pull/56"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082272"&gt;python-testfixtures&lt;/a&gt; (&lt;a href="https://github.com/simplistix/testfixtures/pull/203"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082279"&gt;python-venusian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082311"&gt;sphinx-a4doc&lt;/a&gt; (&lt;a href="https://github.com/taminomara/sphinx-a4doc/pull/22"&gt;contributed
  upstream&lt;/a&gt;, and I also
  made a &lt;a href="https://github.com/antlr/antlr4/pull/4726"&gt;small antlr4
  improvement&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082337"&gt;webpy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some packaging problems that resulted in failures any time we add a
new Python version to&amp;nbsp;Debian:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082123"&gt;python-btrees&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1082234"&gt;python-nox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed other build/autopkgtest failures&amp;nbsp;in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1086590"&gt;psycopg3&lt;/a&gt; (&lt;a href="https://github.com/psycopg/psycopg/pull/953"&gt;contributed
  upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1086658"&gt;python-aiohttp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087830"&gt;python-cotengrust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1086223"&gt;python-distutils-extra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087906"&gt;python-formencode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087788"&gt;python-openapi-schema-validator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1087789"&gt;python-openapi-spec-validator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.debian.org/1088147"&gt;sphinxcontrib-towncrier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1086691"&gt;python-quart-trio&lt;/a&gt;, needed for
a new upstream version of python-urllib3, and &lt;a href="https://github.com/pgjones/quart-trio/pull/19"&gt;contributed a small packaging
tweak upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I backported a &lt;a href="https://bugs.debian.org/1087390"&gt;twisted fix&lt;/a&gt; that caused
problems in other packages, including breaking
&lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;debusine&lt;/a&gt;&amp;#8216;s&amp;nbsp;tests.&lt;/p&gt;
&lt;p&gt;I disentangled some &lt;a href="https://github.com/explosion/catalogue/issues/74"&gt;upstream version
confusion&lt;/a&gt; in
python-catalogue, and upgraded to the current upstream&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;I upgraded these packages to new upstream&amp;nbsp;versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aioftp (fixing a &lt;a href="https://bugs.debian.org/1082132"&gt;Python 3.13 failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ansible-core&lt;/li&gt;
&lt;li&gt;ansible&lt;/li&gt;
&lt;li&gt;debugpy&lt;/li&gt;
&lt;li&gt;jsonpickle&lt;/li&gt;
&lt;li&gt;manuel&lt;/li&gt;
&lt;li&gt;psycopg2&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;pymssql (fixing a &lt;a href="https://bugs.debian.org/1081620"&gt;Python 3.13 failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pyodbc (fixing a &lt;a href="https://bugs.debian.org/1081433"&gt;Python 3.13 failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-argh (fixing a &lt;a href="https://bugs.debian.org/1082194"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-boltons (fixing a &lt;a href="https://bugs.debian.org/1082199"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-channels-redis&lt;/li&gt;
&lt;li&gt;python-colorlog (fixing a &lt;a href="https://bugs.debian.org/1082229"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-django-pgtrigger&lt;/li&gt;
&lt;li&gt;python-line-profiler&lt;/li&gt;
&lt;li&gt;python-pathvalidate (fixing a &lt;a href="https://bugs.debian.org/1082241"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-plac (fixing a &lt;a href="https://bugs.debian.org/1082249"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-precis-i18n&lt;/li&gt;
&lt;li&gt;python-pure-eval (fixing a &lt;a href="https://bugs.debian.org/1082250"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-pythonjsonlogger (contributing a &lt;a href="https://github.com/nhairs/python-json-logger/pull/28"&gt;small packaging
  fix&lt;/a&gt; upstream, as
  well as a &lt;a href="https://github.com/jupyter/jupyter_events/pull/103"&gt;test fix to
  jupyter-events&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-rdata (fixing a &lt;a href="https://bugs.debian.org/1084636"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-semantic-release&lt;/li&gt;
&lt;li&gt;python-telethon (fixing a &lt;a href="https://bugs.debian.org/1081476"&gt;Python 3.13
  failure&lt;/a&gt;, and &lt;a href="https://github.com/LonamiWebs/Telethon/pull/4504"&gt;contributing some test
  fixes upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-tornado (fixing &lt;a href="https://bugs.debian.org/1088112"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-52804&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-trio (fixing a &lt;a href="https://bugs.debian.org/1082276"&gt;Python 3.13
  failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-trustme&lt;/li&gt;
&lt;li&gt;python-typeguard&lt;/li&gt;
&lt;li&gt;python-urllib3 (fixing &lt;a href="https://bugs.debian.org/1074149"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-37891&lt;/a&gt;
  and a &lt;a href="https://bugs.debian.org/1082278"&gt;Python 3.13 failure&lt;/a&gt;, and
  requiring some &lt;a href="https://bugs.debian.org/1086794"&gt;shenanigans&lt;/a&gt; with its
  hypercorn&amp;nbsp;test-dependency)&lt;/li&gt;
&lt;li&gt;python-zipp&lt;/li&gt;
&lt;li&gt;quart (fixing &lt;a href="https://bugs.debian.org/1086063"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-49767&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;rpds-py (fixing a &lt;a href="https://bugs.debian.org/1078392"&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;sen&lt;/li&gt;
&lt;li&gt;sqlparse&lt;/li&gt;
&lt;li&gt;stravalib&lt;/li&gt;
&lt;li&gt;transaction&lt;/li&gt;
&lt;li&gt;waitress&lt;/li&gt;
&lt;li&gt;zope.interface&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other small&amp;nbsp;fixes&lt;/h2&gt;
&lt;p&gt;I contributed &lt;a href="https://github.com/liske/needrestart/pull/315"&gt;Incus support&lt;/a&gt;
to needrestart&amp;nbsp;upstream.&lt;/p&gt;
&lt;p&gt;In response to Helmut&amp;#8217;s &lt;a href="https://toulouse2024.mini.debconf.org/talks/12-cross-building/"&gt;Cross
building&lt;/a&gt;
talk at MiniDebConf Toulouse, I fixed libfilter-perl to support
cross-building
(&lt;a href="https://salsa.debian.org/debian/libfilter-perl/-/commit/5b4c2e105d96c5342c3f6544eb6d9fce3603e9b5"&gt;5b4c2e10&lt;/a&gt;,
&lt;a href="https://salsa.debian.org/debian/libfilter-perl/-/commit/f9788c27cefc68d3723921ce15ae8d6eb2ad52a9"&gt;f9788c27&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I applied a patch to move aliased files from &lt;code&gt;/&lt;/code&gt; to &lt;code&gt;/usr&lt;/code&gt; in iprutils
(&lt;a href="https://bugs.debian.org/1087733"&gt;#1087733&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I adjusted debconf to use the new &lt;code&gt;/usr/lib/apt/apt-extracttemplates&lt;/code&gt; path
(&lt;a href="https://bugs.debian.org/1087523"&gt;#1087523&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I upgraded putty to
&lt;a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;0.82&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in October 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-10.html" rel="alternate"/><published>2024-11-01T12:19:04+00:00</published><updated>2024-11-01T12:19:04+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-11-01:/~cjwatson/blog/activity-2024-10.html</id><summary type="html">&lt;p&gt;Ansible, OpenSSH, and lots of&amp;nbsp;Python.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Almost all of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Ansible&lt;/h2&gt;
&lt;p&gt;I noticed that &lt;a href="https://www.ansible.com/"&gt;Ansible&lt;/a&gt; had fallen out of Debian
testing due to autopkgtest failures.  This seemed like a problem worth
fixing: in common with many other people, we use Ansible for configuration
management at Freexian, and it probably wouldn&amp;#8217;t make our sysadmins too
happy if they upgraded to trixie after its release and found that Ansible
was&amp;nbsp;gone.&lt;/p&gt;
&lt;p&gt;The problems here were really just slogging through test failures in both
the &lt;code&gt;ansible-core&lt;/code&gt; and &lt;code&gt;ansible&lt;/code&gt; packages, but their test suites are large
and take a while to run so this took some time.  I was able to contribute a
few small fixes to various upstreams in the&amp;nbsp;process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ansible/ansible/pull/84129"&gt;test: Make git archive prefix fit in 32-bit
  &lt;code&gt;ssize_t&lt;/code&gt;&lt;/a&gt; (though upstream
  went for a different&amp;nbsp;approach)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ansible-collections/community.grafana/pull/406"&gt;test: replace more deprecated
  &lt;code&gt;assertEquals&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ansible-collections/community.mongodb/pull/684"&gt;Fix import error on Python&amp;nbsp;3.13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ansible-collections/cloud.common/pull/162"&gt;Make &lt;code&gt;test_start_daemon_with_no_mock&lt;/code&gt; less&amp;nbsp;flaky&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should now get back into testing&amp;nbsp;tomorrow.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;Martin-Éric Racine
&lt;a href="https://github.com/jtesta/ssh-audit/issues/291"&gt;reported&lt;/a&gt; that &lt;code&gt;ssh-audit&lt;/code&gt;
didn&amp;#8217;t list the &lt;code&gt;ext-info-s&lt;/code&gt; feature as being available in Debian&amp;#8217;s OpenSSH
9.2 packaging in bookworm, contrary to what OpenSSH upstream said on their
&lt;a href="https://www.openssh.com/specs.html"&gt;specifications page&lt;/a&gt; at the time.  I
spent some time looking into this and realized that upstream was mistakenly
saying that implementations of &lt;code&gt;ext-info-c&lt;/code&gt; and &lt;code&gt;ext-info-s&lt;/code&gt; were added at
the same time, while in fact &lt;code&gt;ext-info-s&lt;/code&gt; was added rather later.
&lt;code&gt;ssh-audit&lt;/code&gt; now has clearer output, and the OpenSSH maintainers have
corrected their specifications&amp;nbsp;page.&lt;/p&gt;
&lt;p&gt;I looked into a &lt;a href="https://bugs.debian.org/1041521"&gt;report&lt;/a&gt; of an &lt;code&gt;ssh&lt;/code&gt;
failure in certain cases when using &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; key exchange (which is a Debian
patch).  Once again, having &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-05.html"&gt;integration
tests&lt;/a&gt; was a huge win here: the affected
scenario is quite a fiddly one, but I was able to set it up in the
&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/blob/master/debian/tests/ssh-gssapi"&gt;test&lt;/a&gt;,
and thereby make sure it doesn&amp;#8217;t regress in future.  It still took me a
couple of hours to get all the details right, but in the past this sort of
thing took me much longer with a much lower degree of confidence that the
fix was&amp;nbsp;correct.&lt;/p&gt;
&lt;p&gt;On upstream&amp;#8217;s
&lt;a href="https://lists.mindrot.org/pipermail/openssh-unix-dev/2024-October/041682.html"&gt;advice&lt;/a&gt;,
I cherry-picked some key exchange fixes needed for big-endian&amp;nbsp;architectures.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I packaged &lt;a href="https://bugs.debian.org/1085206"&gt;python-evalidate&lt;/a&gt;, needed for a
new upstream version of&amp;nbsp;buildbot.&lt;/p&gt;
&lt;p&gt;The Python 3.13 transition rolls on.  I fixed problems related to it in
&lt;a href="https://bugs.debian.org/1084575"&gt;htmlmin&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084718"&gt;humanfriendly&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1082143"&gt;postgresfixture&lt;/a&gt; (&lt;a href="https://code.launchpad.net/~cjwatson/postgresfixture/py313/+merge/474603"&gt;contributed
upstream&lt;/a&gt;),
&lt;a href="https://bugs.debian.org/1084621"&gt;pylint&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084679"&gt;python-asyncssh&lt;/a&gt; (&lt;a href="https://github.com/ronf/asyncssh/pull/697"&gt;contributed
upstream&lt;/a&gt;),
&lt;a href="https://bugs.debian.org/1082235"&gt;python-oauthlib&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084589"&gt;python3-simpletal&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084610"&gt;quodlibet&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1082339"&gt;zope.exceptions&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1081541"&gt;zope.interface&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A trickier Python 3.13 issue involved the &lt;code&gt;cgi&lt;/code&gt; module.  Years ago I &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3.html"&gt;ported
zope.publisher to the multipart module&lt;/a&gt; because
&lt;code&gt;cgi.FieldStorage&lt;/code&gt; was broken in some situations, and as a result I got a
&lt;a href="https://github.com/python/peps/pull/2306"&gt;recommendation&lt;/a&gt; into Python&amp;#8217;s
&lt;a href="https://peps.python.org/pep-0594/"&gt;&amp;#8220;dead batteries&amp;#8221; &lt;span class="caps"&gt;PEP&lt;/span&gt; 594&lt;/a&gt;.
Unfortunately there turns out to be a &lt;a href="https://github.com/pypa/packaging-problems/issues/818"&gt;name conflict between multipart and
python-multipart on
PyPI&lt;/a&gt;;
python-multipart upstream has been &lt;a href="https://github.com/Kludex/python-multipart/pull/166"&gt;working to disentangle
this&lt;/a&gt;, though we still
need to &lt;a href="https://bugs.debian.org/1085728"&gt;work out what to do in Debian&lt;/a&gt;.
All the same, I needed to fix
&lt;a href="https://bugs.debian.org/1082280"&gt;python-wadllib&lt;/a&gt; and multipart seemed like
the best fit; I &lt;a href="https://code.launchpad.net/~cjwatson/wadllib/+git/wadllib/+merge/474861"&gt;contributed a port
upstream&lt;/a&gt;
and temporarily copied multipart into Debian&amp;#8217;s python-wadllib source package
to allow its tests to pass.  I&amp;#8217;ll come back and fix this properly once we
sort out the multipart vs. python-multipart&amp;nbsp;packaging.&lt;/p&gt;
&lt;p&gt;tzdata
&lt;a href="https://tracker.debian.org/news/1573095/accepted-tzdata-2024b-3-source-into-unstable/"&gt;moved&lt;/a&gt;
some timezone definitions to tzdata-legacy, which has broken a number of
packages.  I added tzdata-legacy build-dependencies to
&lt;a href="https://bugs.debian.org/1086253"&gt;alembic&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/1086374"&gt;python-icalendar&lt;/a&gt; to deal with this in
those packages, though there are still some other instances of this&amp;nbsp;left.&lt;/p&gt;
&lt;p&gt;I tracked down an &lt;a href="https://bugs.debian.org/1084385"&gt;nltk regression&lt;/a&gt; that
caused build failures in many other&amp;nbsp;packages.&lt;/p&gt;
&lt;p&gt;I fixed Rust crate versioning issues in
&lt;a href="https://bugs.debian.org/1084322"&gt;pydantic-core&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084329"&gt;python-bcrypt&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1081875"&gt;python-maturin&lt;/a&gt; (mostly fixed by Peter
Michael Green and Jelmer Vernooĳ, but it needed a little extra&amp;nbsp;work).&lt;/p&gt;
&lt;p&gt;I fixed other build failures in
&lt;a href="https://bugs.debian.org/1052826"&gt;entrypoints&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1082685"&gt;mayavi2&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1052793"&gt;python-pyvmomi&lt;/a&gt; (mostly fixed by Alexandre
Detiste, but it needed a little extra work), and
&lt;a href="https://bugs.debian.org/1018589"&gt;python-testing.postgresql&lt;/a&gt;&amp;nbsp;(ditto).&lt;/p&gt;
&lt;p&gt;I fixed &lt;a href="https://bugs.debian.org/1080724"&gt;python3-simpletal&lt;/a&gt; to tolerate
future versions of dh-python that will drop their dependency on&amp;nbsp;python3-setuptools.&lt;/p&gt;
&lt;p&gt;I fixed broken symlinks in &lt;a href="https://bugs.debian.org/988773"&gt;python-treq&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I removed (build-)depends on python3-pkg-resources from
&lt;a href="https://bugs.debian.org/1083301"&gt;alembic&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083309"&gt;autopep8&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083325"&gt;buildbot&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083331"&gt;celery&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083398"&gt;flufl.enum&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083400"&gt;flufl.lock&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083685"&gt;python-public&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083718"&gt;python-wadllib&lt;/a&gt; (&lt;a href="https://code.launchpad.net/~cjwatson/wadllib/+git/wadllib/+merge/474798"&gt;contributed
upstream&lt;/a&gt;),
&lt;a href="https://bugs.debian.org/1083732"&gt;pyvisa&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083757"&gt;routes&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1083983"&gt;vulture&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1084003"&gt;zodbpickle&lt;/a&gt; (&lt;a href="https://github.com/zopefoundation/zodbpickle/pull/99"&gt;contributed
upstream&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I upgraded astroid, asyncpg (fixing a &lt;a href="https://bugs.debian.org/1081995"&gt;Python 3.13
failure&lt;/a&gt; and a &lt;a href="https://bugs.debian.org/1084240"&gt;build
failure&lt;/a&gt;), buildbot (noticing an &lt;a href="https://github.com/buildbot/buildbot/pull/8137"&gt;upstream
test bug&lt;/a&gt; in the process),
dnsdiag, frozenlist, netmiko (fixing a &lt;a href="https://bugs.debian.org/1084527"&gt;Python 3.13
failure&lt;/a&gt;), psycopg3, pydantic-settings,
pylint, python-asyncssh, python-bleach, python-btrees, python-cytoolz,
python-django-pgtrigger, python-django-test-migrations, python-gssapi,
python-icalendar, python-json-log-formatter, python-pgbouncer,
python-pkginfo, python-plumbum, python-stdlib-list, python-tokenize-rt,
python-treq (fixing a &lt;a href="https://bugs.debian.org/1084541"&gt;Python 3.13
failure&lt;/a&gt;), python-typeguard, python-webargs
(fixing a &lt;a href="https://bugs.debian.org/1082393"&gt;build failure&lt;/a&gt;), pyupgrade,
&lt;a href="https://bugs.debian.org/1084175"&gt;pyvisa&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1084176"&gt;pyvisa-py&lt;/a&gt; (fixing a &lt;a href="https://bugs.debian.org/1084620"&gt;Python 3.13
failure&lt;/a&gt;), toolz, twisted, vulture,
waitress (fixing &lt;a href="https://bugs.debian.org/1086467"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-49768&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/1086468"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-49769&lt;/a&gt;), wtf-peewee, wtforms,
zodbpickle, zope.exceptions, zope.interface, zope.proxy, zope.security, and
zope.testrunner to new upstream&amp;nbsp;versions.&lt;/p&gt;
&lt;p&gt;I tried to fix a &lt;a href="https://bugs.debian.org/1081851"&gt;regression&lt;/a&gt; in
python-scruffy, but I need testing&amp;nbsp;feedback.&lt;/p&gt;
&lt;p&gt;I requested removal of
&lt;a href="https://bugs.debian.org/1018588"&gt;python-testing.mysqld&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in September 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-09.html" rel="alternate"/><published>2024-10-01T14:19:21+01:00</published><updated>2024-10-01T14:19:21+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-10-01:/~cjwatson/blog/activity-2024-09.html</id><summary type="html">&lt;p&gt;Pydantic v2, OpenSSH 9.9p1, YubiHSM improvements, and&amp;nbsp;more.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Almost all of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Pydantic&lt;/h2&gt;
&lt;p&gt;My main Debian project for the month turned out to be getting
&lt;a href="https://github.com/pydantic/pydantic"&gt;Pydantic&lt;/a&gt; back into a good state in
Debian testing.  I&amp;#8217;ve used Pydantic quite a bit in various projects, most
recently in &lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;Debusine&lt;/a&gt;, so
I have an interest in making sure it works well in Debian.  However, it had
been stalled on 1.10.17 for quite a while due to the complexities of getting
2.x packaged.  This was partly making sure everything else could cope with
the transition, but in practice mostly sorting out packaging of its &lt;a href="https://github.com/pydantic/pydantic-core"&gt;new
Rust dependencies&lt;/a&gt;.  Several
other people (notably Alexandre Detiste, Andreas Tille, Drew Parsons, and
Timo Röhling) had made some good progress on this, but nobody had quite got
it over the line and it seemed a bit&amp;nbsp;stuck.&lt;/p&gt;
&lt;p&gt;Learning Rust is on my to-do list, but merely not knowing a language &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/porting-ghc-a-tale-of-two-architectures.html"&gt;hasn&amp;#8217;t
stopped me before&lt;/a&gt;.
So I learned &lt;a href="https://salsa.debian.org/rust-team/debcargo-conf"&gt;how the Debian Rust team&amp;#8217;s packaging
works&lt;/a&gt;, upgraded a few
packages to new upstream versions (including
&lt;a href="https://salsa.debian.org/rust-team/debcargo-conf/-/merge_requests/716"&gt;rust-half&lt;/a&gt;
and &lt;a href="https://github.com/servo/rust-url/pull/963"&gt;upstream rust-idna&lt;/a&gt; test
fixes), and packaged &lt;a href="https://crates.io/crates/jiter"&gt;rust-jiter&lt;/a&gt;.  After a
lot of waiting around for various things and chasing some failures in other
packages I was eventually able to get current versions of both pydantic-core
and pydantic into&amp;nbsp;testing.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m looking forward to being able to drop our clunky v1 compatibility code
once debusine can rely on running on&amp;nbsp;trixie!&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I upgraded the Debian packaging to &lt;a href="https://www.openssh.com/releasenotes.html#9.9p1"&gt;OpenSSH
9.9p1&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;YubiHSM&lt;/h2&gt;
&lt;p&gt;I upgraded python-yubihsm, yubihsm-connector, and yubihsm-shell to new
upstream&amp;nbsp;versions.&lt;/p&gt;
&lt;p&gt;I noticed that I could enable some tests in python-yubihsm and
yubihsm-shell; I&amp;#8217;d previously thought the whole test suite required a real
YubiHSM device, but when I looked closer it turned out that this was only
true for some&amp;nbsp;tests.&lt;/p&gt;
&lt;p&gt;I fixed yubihsm-shell build failures on some 32-bit architectures (upstream
PRs &lt;a href="https://github.com/Yubico/yubihsm-shell/pull/431"&gt;#431&lt;/a&gt;,
&lt;a href="https://github.com/Yubico/yubihsm-shell/pull/432"&gt;#432&lt;/a&gt;), and also made it
&lt;a href="https://salsa.debian.org/pkg-security-team/yubihsm-shell/-/commit/b74e38e88bd6492381f67aebb4741083218dd163"&gt;build
reproducibly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks to Helmut Grohne, I fixed yubihsm-connector to &lt;a href="https://bugs.debian.org/1081398"&gt;apply udev rules to
existing devices when the package is
installed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As usual, bookworm-backports is up to date with all these&amp;nbsp;changes.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://setuptools.pypa.io/en/latest/history.html#v72-0-0"&gt;setuptools
72.0.0&lt;/a&gt; removed
the venerable &lt;code&gt;setup.py test&lt;/code&gt; command.  This caused some fallout in Debian,
some of which was quite non-obvious as packaging helpers sometimes fell back
to different ways of running test suites that didn&amp;#8217;t quite work.  I fixed
&lt;a href="https://bugs.debian.org/1080102"&gt;django-guardian&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1079748"&gt;manuel&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080278"&gt;python-autopage&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080280"&gt;python-flask-seeder&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080232"&gt;python-pgpdump&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080282"&gt;python-potr&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1079767"&gt;python-precis-i18n&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1079761"&gt;python-stopit&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080234"&gt;serpent&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080287"&gt;straight.plugin&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1079757"&gt;supervisor&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1080145"&gt;zope.i18nmessageid&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As usual for new language versions, the addition of Python 3.13 caused some
problems.  I fixed &lt;a href="https://bugs.debian.org/1081431"&gt;psycopg2&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1081477"&gt;python-time-machine&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1081478"&gt;python-traits&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I fixed build/autopkgtest failures in
&lt;a href="https://bugs.debian.org/1080857"&gt;keymapper&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1072607"&gt;python-django-test-migrations&lt;/a&gt;,
&lt;a href="https://salsa.debian.org/python-team/packages/python-rosettasciio/-/commit/879e9a18d2010f7386417b79326c9f39a007b0b8"&gt;python-rosettasciio&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1058236"&gt;routes&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1071724"&gt;transmissionrpc&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1081419"&gt;twisted&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;buildbot was in &lt;a href="https://bugs.debian.org/1073001"&gt;a bit of a mess&lt;/a&gt; due to
being incompatible with SQLAlchemy 2.0.  Fortunately by the time I got to it
upstream had committed a workable set of patches, and the main difficulty
was figuring out what to cherry-pick since they haven&amp;#8217;t made a new upstream
release with all of that yet.  I figured this out and got us up to&amp;nbsp;4.0.3.&lt;/p&gt;
&lt;p&gt;Adrian Bunk &lt;a href="https://bugs.debian.org/1081014"&gt;asked&lt;/a&gt; whether python-zipp
should be removed from trixie.  I spent some time investigating this and
concluded that the answer was no, but looking into it was an interesting
exercise&amp;nbsp;anyway.&lt;/p&gt;
&lt;p&gt;On the other hand, I looked into flask-appbuilder, concluded that it should
be removed, and filed a &lt;a href="https://bugs.debian.org/1081148"&gt;removal request&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I upgraded some embedded &lt;span class="caps"&gt;CSS&lt;/span&gt; files in
&lt;a href="https://bugs.debian.org/1082665"&gt;nbconvert&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I upgraded importlib-resources, ipywidgets, jsonpickle, pydantic-settings,
pylint (fixing a &lt;a href="https://bugs.debian.org/1079751"&gt;test failure&lt;/a&gt;),
python-aiohttp-session, python-apptools, python-asyncssh,
python-django-celery-beat, python-django-rules, python-limits,
python-multidict, python-persistent, python-pkginfo, python-rt, python-spur,
python-zipp, stravalib, transmissionrpc, vulture, zodbpickle,
zope.exceptions (&lt;a href="https://bugs.debian.org/948808"&gt;adopting it&lt;/a&gt;),
zope.i18nmessageid, zope.proxy, and zope.security to new upstream&amp;nbsp;versions.&lt;/p&gt;
&lt;h2&gt;debmirror&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;experimental&lt;/code&gt; and &lt;code&gt;*-proposed-updates&lt;/code&gt; suites used to not have
&lt;code&gt;Contents-*&lt;/code&gt; files, and a long time ago debmirror was changed to just skip
those files in those suites.  They were added to the Debian archive some
time ago, but debmirror carried on skipping them anyway.  Once I realized
what was going on, I removed these unnecessary special cases
(&lt;a href="https://bugs.debian.org/819925"&gt;#819925&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1080168"&gt;#1080168&lt;/a&gt;).&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in August 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-08.html" rel="alternate"/><published>2024-09-01T14:29:32+01:00</published><updated>2024-09-01T14:29:32+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-09-01:/~cjwatson/blog/activity-2024-08.html</id><summary type="html">&lt;p&gt;All but about four hours of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  (I ended up going a bit over my 20% billing limit this&amp;nbsp;month.)&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;man-db and&amp;nbsp;friends&lt;/h2&gt;
&lt;p&gt;I released &lt;a href="https://gitlab.com/libpipeline/libpipeline/-/releases/1.5.8"&gt;libpipeline
1.5.8&lt;/a&gt; and
&lt;a href="https://gitlab.com/man-db/man-db/-/releases/2.13.0"&gt;man-db 2.13 …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;All but about four hours of my Debian contributions this month were
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by
Freexian.  (I ended up going a bit over my 20% billing limit this&amp;nbsp;month.)&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;man-db and&amp;nbsp;friends&lt;/h2&gt;
&lt;p&gt;I released &lt;a href="https://gitlab.com/libpipeline/libpipeline/-/releases/1.5.8"&gt;libpipeline
1.5.8&lt;/a&gt; and
&lt;a href="https://gitlab.com/man-db/man-db/-/releases/2.13.0"&gt;man-db 2.13.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since autopkgtests are great for making sure we spot regressions caused by
changes in dependencies, I added one to man-db that runs the upstream tests
against the installed package.  This required some preparatory work
upstream, but otherwise was surprisingly easy to&amp;nbsp;do.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I fixed the various 9.8 regressions I mentioned &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-07.html"&gt;last
month&lt;/a&gt;: socket activation, libssh2, and
Twisted.  There were a few other regressions reported too: &lt;a href="https://bugs.debian.org/1077799"&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt; wrappers
support&lt;/a&gt;,
&lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/28"&gt;openssh-server-udeb&lt;/a&gt;,
and &lt;a href="https://bugs.debian.org/1078429"&gt;xinetd&lt;/a&gt; were all broken by changes
related to the listener/per-session binary split, and I fixed all of&amp;nbsp;those.&lt;/p&gt;
&lt;p&gt;Once all that had made it through to testing, I finally uploaded the first
stage of my &lt;a href="https://lists.debian.org/debian-devel/2024/04/msg00044.html"&gt;plan to split out &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt;
support&lt;/a&gt;: there
are now &lt;code&gt;openssh-client-gssapi&lt;/code&gt; and &lt;code&gt;openssh-server-gssapi&lt;/code&gt; packages in
unstable, and if you use either &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; authentication or key exchange then
you should install the corresponding package in order for upgrades to
trixie+1 to work correctly.  I&amp;#8217;ll write a release note once this has reached&amp;nbsp;testing.&lt;/p&gt;
&lt;h2&gt;Multiple identical results from&amp;nbsp;getaddrinfo&lt;/h2&gt;
&lt;p&gt;I expect this is really a bug in a chroot creation script somewhere, but I
haven&amp;#8217;t been able to track down what&amp;#8217;s causing it yet.  My sbuild chroots,
and apparently Lucas Nussbaum&amp;#8217;s as well, have an &lt;code&gt;/etc/hosts&lt;/code&gt; that looks
like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/var/lib/schroot/chroots/sid-amd64/etc/hosts
&lt;span class="go"&gt;127.0.0.1       localhost&lt;/span&gt;
&lt;span class="go"&gt;127.0.1.1       [...]&lt;/span&gt;
&lt;span class="go"&gt;127.0.0.1       localhost ip6-localhost ip6-loopback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last line clearly ought to be &lt;code&gt;::1&lt;/code&gt; rather than &lt;code&gt;127.0.0.1&lt;/code&gt;; but things
mostly work anyway, since most code doesn&amp;#8217;t really care which protocol it
uses to talk to localhost.  However, a few things try to set up test
listeners by calling &lt;code&gt;getaddrinfo("localhost", ...)&lt;/code&gt; and binding a socket
for each result.  This goes wrong if there are duplicates in the resulting
list, and the test output is typically very confusing: it looks just like
what you&amp;#8217;d see if a test isn&amp;#8217;t tearing down its resources correctly, which
is a much more common thing for a test suite to get wrong, so it took me a
while to spot the&amp;nbsp;problem.&lt;/p&gt;
&lt;p&gt;I ran into this in both python-asyncssh
(&lt;a href="https://bugs.debian.org/1052788"&gt;#1052788&lt;/a&gt;, &lt;a href="https://github.com/ronf/asyncssh/pull/679"&gt;upstream
&lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;) and Ruby
(&lt;a href="https://bugs.debian.org/1069399"&gt;ruby3.1/#1069399&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1064685"&gt;ruby3.2/#1064685&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1077462"&gt;ruby3.3/#1077462&lt;/a&gt;, &lt;a href="https://github.com/ruby/ruby/pull/11456"&gt;upstream
&lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;).  The latter took a while
since Ruby isn&amp;#8217;t one of my languages, but hey, I&amp;#8217;ve tackled &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/porting-ghc-a-tale-of-two-architectures.html"&gt;much harder
side quests&lt;/a&gt;.  I
NMUed ruby3.1 for this since it was showing up as a blocker for openssl
testing migration, but haven&amp;#8217;t done the other active versions (yet,&amp;nbsp;anyway).&lt;/p&gt;
&lt;h2&gt;OpenSSL vs.&amp;nbsp;cryptography&lt;/h2&gt;
&lt;p&gt;I tend to care about openssl migrating to testing promptly, since openssh
uploads have a habit of getting stuck on it&amp;nbsp;otherwise.&lt;/p&gt;
&lt;p&gt;Debian&amp;#8217;s OpenSSL packaging recently split out some legacy code (cryptography
that&amp;#8217;s no longer considered a good idea to use, but that&amp;#8217;s sometimes needed
for compatibility) to an &lt;code&gt;openssl-legacy-provider&lt;/code&gt; package, and added a
Recommends on it.  Most users install Recommends, but package build
processes don&amp;#8217;t; and the Python &lt;code&gt;cryptography&lt;/code&gt; package requires this code
unless you set the &lt;code&gt;CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1&lt;/code&gt; environment variable,
which caused a bunch of packages that build-depend on it to fail to&amp;nbsp;build.&lt;/p&gt;
&lt;p&gt;After playing whack-a-mole setting that environment variable in a few
packages&amp;#8217; build process, I decided I didn&amp;#8217;t want to be caught in the middle
here and filed an &lt;a href="https://github.com/pyca/cryptography/issues/11450"&gt;upstream
issue&lt;/a&gt; to see if I could
get Debian&amp;#8217;s OpenSSL team and cryptography&amp;#8217;s upstream talking to each other
directly.  There was some moderately spirited discussion and the issue
remains open, but for the time being the OpenSSL team has &lt;a href="https://tracker.debian.org/news/1557087/accepted-openssl-331-7-source-into-unstable/"&gt;effectively
reverted the
change&lt;/a&gt;
so it&amp;#8217;s no longer a pressing&amp;nbsp;problem.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;GCC&lt;/span&gt; 14&amp;nbsp;regressions&lt;/h2&gt;
&lt;p&gt;Continuing from &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-07.html"&gt;last month&lt;/a&gt;, I fixed build
failures in &lt;a href="https://bugs.debian.org/1075363"&gt;pccts&lt;/a&gt; (&lt;span class="caps"&gt;NMU&lt;/span&gt;) and
&lt;a href="https://bugs.debian.org/1078145"&gt;trn4&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I upgraded alembic, automat, gunicorn, incremental, referencing, pympler
(fixing &lt;a href="https://bugs.debian.org/1002173"&gt;compatibility with Python &amp;gt;=
3.10&lt;/a&gt;), python-aiohttp, python-asyncssh
(fixing &lt;a href="https://bugs.debian.org/1056000"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-46445&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1055999"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-46446&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1059007"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2023-48795&lt;/a&gt;), python-avro,
python-multidict (fixing a &lt;a href="https://bugs.debian.org/1075418"&gt;build failure with &lt;span class="caps"&gt;GCC&lt;/span&gt;
14&lt;/a&gt;), python-tokenize-rt, python-zipp,
pyupgrade, twisted (fixing &lt;a href="https://bugs.debian.org/1077679"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-41671&lt;/a&gt;
and &lt;a href="https://bugs.debian.org/1077680"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-41810&lt;/a&gt;), zope.exceptions,
zope.interface, zope.proxy, zope.security, and zope.testrunner to new
upstream versions.  In the process, I added myself to &lt;code&gt;Uploaders&lt;/code&gt; for
zope.interface; I&amp;#8217;m reasonably comfortable with the Zope Toolkit and I seem
to be gradually picking up much of its maintenance in&amp;nbsp;Debian.&lt;/p&gt;
&lt;p&gt;A few of these required their own bits of&amp;nbsp;yak-shaving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-aiohttp 3.10.0 needed fixes in blinkpy
   (&lt;a href="https://bugs.debian.org/1077981"&gt;#1077981&lt;/a&gt;, &lt;a href="https://github.com/fronzbot/blinkpy/pull/974"&gt;upstream
   &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;) and python-yalexs
   (&lt;a href="https://bugs.debian.org/1077985"&gt;#1077985&lt;/a&gt;, &lt;a href="https://github.com/bdraco/yalexs/pull/134"&gt;upstream
   &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;twisted 24.7.0 needed fixes in pytest-twisted (cherry-picked existing
   &lt;a href="https://github.com/pytest-dev/pytest-twisted/commit/ee97014a5b70977cc93d0a5c93e99b770c91ab7f"&gt;upstream
   commit&lt;/a&gt;),
   python-daphne (cherry-picked existing &lt;a href="https://github.com/django/daphne/pull/526"&gt;upstream
   &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;), and python-tornado
   (&lt;a href="https://bugs.debian.org/1078411"&gt;#1078411&lt;/a&gt;, &lt;a href="https://github.com/tornadoweb/tornado/pull/3417"&gt;upstream
   &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I improved some &lt;code&gt;Multi-Arch: foreign&lt;/code&gt; tagging
(&lt;a href="https://bugs.debian.org/1078041"&gt;python-importlib-metadata&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1078035"&gt;python-typing-extensions&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1078038"&gt;python-zipp&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I fixed build failures in &lt;a href="https://bugs.debian.org/1076903"&gt;pipenv&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1067325"&gt;python-stdlib-list&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1077918"&gt;psycopg3&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1067287"&gt;sen&lt;/a&gt;, and fixed autopkgtest failures in
&lt;a href="https://salsa.debian.org/python-team/packages/autoimport/-/commit/2669881195b78c66d6232d0518f61b69734ca8f4"&gt;autoimport&lt;/a&gt;
(&lt;a href="https://github.com/lyz-code/autoimport/pull/259"&gt;upstream &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;),
&lt;a href="https://salsa.debian.org/python-team/packages/python-semantic-release/-/commit/bafa7e7e51f79ec8268cc8bc24368e03c06d1eb4"&gt;python-semantic-release&lt;/a&gt;
and &lt;a href="https://bugs.debian.org/1061841"&gt;rstcheck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Upstream for zope.file (not in Debian) filed an issue about a &lt;a href="https://github.com/zopefoundation/zope.file/issues/13"&gt;test failure
with Python 3.12&lt;/a&gt;,
which I tracked down to a &lt;a href="https://github.com/zopefoundation/zope.security/pull/112"&gt;Python 3.12 compatibility
&lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt; in&amp;nbsp;zope.security.&lt;/p&gt;
&lt;p&gt;I made python-nacl build reproducibly (&lt;a href="https://github.com/pyca/pynacl/pull/836"&gt;upstream
&lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I moved aliased files from &lt;code&gt;/&lt;/code&gt; to &lt;code&gt;/usr&lt;/code&gt; in timekpr-next
(&lt;a href="https://bugs.debian.org/1073722"&gt;#1073722&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Installer&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I applied a patch from Ubuntu to make os-prober support building with the
&lt;code&gt;noudeb&lt;/code&gt; profile (&lt;a href="https://bugs.debian.org/983325"&gt;#983325&lt;/a&gt;).&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in July 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-07.html" rel="alternate"/><published>2024-08-02T13:27:07+01:00</published><updated>2024-08-02T13:27:07+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-08-02:/~cjwatson/blog/activity-2024-07.html</id><summary type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;At the start of the month, I uploaded a quick fix (via Salvatore Bonaccorso)
for a regression from
&lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-5051"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2006-5051&lt;/a&gt;,
found by
&lt;a href="https://www.qualys.com/2024/07/01/cve-2024-6387/regresshion.txt"&gt;Qualys&lt;/a&gt;;
this was because I expected it to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;At the start of the month, I uploaded a quick fix (via Salvatore Bonaccorso)
for a regression from
&lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-5051"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2006-5051&lt;/a&gt;,
found by
&lt;a href="https://www.qualys.com/2024/07/01/cve-2024-6387/regresshion.txt"&gt;Qualys&lt;/a&gt;;
this was because I expected it to take me a bit longer to merge OpenSSH
9.8, which had the full&amp;nbsp;fix.&lt;/p&gt;
&lt;p&gt;This turned out to be a good guess: it took me until the last day of the
month to get the merge done.  OpenSSH 9.8 included some substantial changes
to split the server into a listener binary and a per-session binary, which
required some corresponding changes in the &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; key exchange patch.  At
this point I was very grateful for the &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/24"&gt;&lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; integration
test&lt;/a&gt;
contributed by Andreas Hasenack a little while ago, because otherwise I
might very easily not have noticed my mistake: this patch adds some entries
to the key exchange algorithm proposal, and on the server side I&amp;#8217;d
accidentally moved that to after the point where the proposal is sent to the
client, which of course meant it didn&amp;#8217;t work at all.  Even with a failing
test, it took me quite a while to spot the problem, involving a lot of
staring at &lt;code&gt;strace&lt;/code&gt; output and comparing debug logs between&amp;nbsp;versions.&lt;/p&gt;
&lt;p&gt;There are still some regressions to sort out, including a &lt;a href="https://bugs.debian.org/1077765"&gt;problem with
socket activation&lt;/a&gt;, and problems in
&lt;a href="https://bugs.debian.org/1077735"&gt;libssh2&lt;/a&gt; and
&lt;a href="https://github.com/twisted/twisted/issues/12273"&gt;Twisted&lt;/a&gt; due to &lt;span class="caps"&gt;DSA&lt;/span&gt; now
being disabled at&amp;nbsp;compile-time.&lt;/p&gt;
&lt;p&gt;Speaking of &lt;span class="caps"&gt;DSA&lt;/span&gt;, I wrote a &lt;a href="https://salsa.debian.org/ddp-team/release-notes/-/merge_requests/209"&gt;release
note&lt;/a&gt;
for this change, which is now&amp;nbsp;merged.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;GCC&lt;/span&gt; 14&amp;nbsp;regressions&lt;/h2&gt;
&lt;p&gt;I fixed a number of build failures with &lt;span class="caps"&gt;GCC&lt;/span&gt; 14, mostly in my older packages:
&lt;a href="https://bugs.debian.org/1075047"&gt;grub (legacy)&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1075089"&gt;imaptool&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1075107"&gt;kali&lt;/a&gt;,
&lt;a href="https://bugs.debian.org/1075114"&gt;knews&lt;/a&gt;, and
&lt;a href="https://bugs.debian.org/1075619"&gt;vigor&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;autopkgtest&lt;/h2&gt;
&lt;p&gt;I contributed a change to &lt;a href="https://salsa.debian.org/ci-team/autopkgtest/-/merge_requests/371"&gt;allow maintaining Incus container and &lt;span class="caps"&gt;VM&lt;/span&gt; images
in
parallel&lt;/a&gt;.
I use both of these regularly (containers are faster, but some tests need
full machine isolation), and the build tools previously didn&amp;#8217;t handle that
very&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;I now have a script that just does this regularly to keep my images up to
date (although for now I&amp;#8217;m running this with &lt;code&gt;PATH&lt;/code&gt; pointing to autopkgtest
from git, since my change hasn&amp;#8217;t been released&amp;nbsp;yet):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;RELEASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sid&lt;span class="w"&gt; &lt;/span&gt;autopkgtest-build-incus&lt;span class="w"&gt; &lt;/span&gt;images:debian/trixie
&lt;span class="nv"&gt;RELEASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sid&lt;span class="w"&gt; &lt;/span&gt;autopkgtest-build-incus&lt;span class="w"&gt; &lt;/span&gt;--vm&lt;span class="w"&gt; &lt;/span&gt;images:debian/trixie
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Python&amp;nbsp;team&lt;/h2&gt;
&lt;p&gt;I fixed dnsdiag&amp;#8217;s uninstallability in unstable, and &lt;a href="https://github.com/farrokhi/dnsdiag/pull/116"&gt;contributed the fix
upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I reverted python-tenacity to an earlier version due to regressions in a
number of OpenStack packages, including
&lt;a href="https://bugs.debian.org/1074690"&gt;octavia&lt;/a&gt; and
&lt;a href="https://bugs.debian.org/1074730"&gt;ironic&lt;/a&gt;.  (This seems to be due to
&lt;a href="https://github.com/jd/tenacity/issues/486"&gt;#486&lt;/a&gt;&amp;nbsp;upstream.)&lt;/p&gt;
&lt;p&gt;I fixed a &lt;a href="https://bugs.debian.org/1074669"&gt;build failure&lt;/a&gt; in
python3-simpletal due to Python 3.12 removing the old &lt;code&gt;imp&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;I added non-superficial autopkgtests to a number of packages, including
httmock, py-macaroon-bakery, python-libnacl, six, and&amp;nbsp;storm.&lt;/p&gt;
&lt;p&gt;I switched a number of packages to build using &lt;a href="https://peps.python.org/pep-0517/"&gt;&lt;span class="caps"&gt;PEP&lt;/span&gt;
517&lt;/a&gt; rather than calling &lt;code&gt;setup.py&lt;/code&gt;
directly, including alembic, constantly, hyperlink, isort, khard,
python-cpuinfo, and python3-onelogin-saml2.  (Much of this was by working
through the
&lt;a href="https://udd.debian.org/lintian/?email1=team%2Bpython%40tracker.debian.org&amp;amp;lt_information=on&amp;amp;lintian_tag=missing-prerequisite-for-pyproject-backend"&gt;missing-prerequisite-for-pyproject-backend&lt;/a&gt;
Lintian tag, but there&amp;#8217;s still lots to&amp;nbsp;do.)&lt;/p&gt;
&lt;p&gt;I upgraded frozenlist, ipykernel, isort, langtable, python-exceptiongroup,
python-launchpadlib, python-typeguard, pyupgrade, sqlparse, storm, and
uncertainties to new upstream versions.  In the process, I added myself to
&lt;code&gt;Uploaders&lt;/code&gt; for isort, since the previous primary uploader has
&lt;a href="https://bugs.debian.org/1041185"&gt;retired&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Other odds and&amp;nbsp;ends&lt;/h2&gt;
&lt;p&gt;I applied a suggestion by Chris Hofstaedtler to &lt;a href="https://bugs.debian.org/1074121"&gt;create /etc/subuid and
/etc/subgid&lt;/a&gt; in base-passwd, since the
login package is no longer&amp;nbsp;essential.&lt;/p&gt;
&lt;p&gt;I fixed a &lt;a href="https://bugs.debian.org/1076623"&gt;wireless-tools regression&lt;/a&gt; due
to iproute2 dropping its &lt;code&gt;(/usr)/sbin/ip&lt;/code&gt; compatibility&amp;nbsp;symlink.&lt;/p&gt;
&lt;p&gt;I applied a suggestion by Petter Reinholdtsen to &lt;a href="https://bugs.debian.org/1077051"&gt;add AppStream
metainfo&lt;/a&gt; to&amp;nbsp;pcmciautils.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in June 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-06.html" rel="alternate"/><published>2024-07-02T13:02:27+01:00</published><updated>2024-07-02T13:02:27+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-07-02:/~cjwatson/blog/activity-2024-06.html</id><summary type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I switched man-db and putty to &lt;code&gt;Rules-Requires-Root: no&lt;/code&gt;, thanks to a
   &lt;a href="https://salsa.debian.org/debian/man-db/-/merge_requests/8"&gt;suggestion&lt;/a&gt;
   from Niels&amp;nbsp;Thykier.&lt;/li&gt;
&lt;li&gt;I moved some files in pcmciautils as part of the &lt;a href="https://wiki.debian.org/UsrMerge"&gt;/usr
   move&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I upgraded libfido2 to&amp;nbsp;1.15.0.&lt;/li&gt;
&lt;li&gt;I made an upstream release of …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I switched man-db and putty to &lt;code&gt;Rules-Requires-Root: no&lt;/code&gt;, thanks to a
   &lt;a href="https://salsa.debian.org/debian/man-db/-/merge_requests/8"&gt;suggestion&lt;/a&gt;
   from Niels&amp;nbsp;Thykier.&lt;/li&gt;
&lt;li&gt;I moved some files in pcmciautils as part of the &lt;a href="https://wiki.debian.org/UsrMerge"&gt;/usr
   move&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I upgraded libfido2 to&amp;nbsp;1.15.0.&lt;/li&gt;
&lt;li&gt;I made an upstream release of &lt;a href="https://github.com/defnull/multipart#changelog"&gt;multipart
   0.2.5&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I reviewed some security-update patches to&amp;nbsp;putty.&lt;/li&gt;
&lt;li&gt;I packaged &lt;a href="https://bugs.debian.org/1074007"&gt;yubihsm-connector&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1074215"&gt;yubihsm-shell&lt;/a&gt;, and
   &lt;a href="https://bugs.debian.org/1074420"&gt;python-yubihsm&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;openssh:&lt;ul&gt;
&lt;li&gt;I did a bit more planning for the &lt;a href="https://lists.debian.org/debian-devel/2024/04/msg00044.html"&gt;&lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; package
  split&lt;/a&gt;,
  though decided not to land it quite yet to avoid blocking other
  changes on &lt;span class="caps"&gt;NEW&lt;/span&gt; queue&amp;nbsp;review.&lt;/li&gt;
&lt;li&gt;I removed the &lt;code&gt;user_readenv&lt;/code&gt; option from &lt;span class="caps"&gt;PAM&lt;/span&gt; configuration
  (&lt;a href="https://bugs.debian.org/1018260"&gt;#1018260&lt;/a&gt;), and prepared a &lt;a href="https://salsa.debian.org/ddp-team/release-notes/-/merge_requests/204"&gt;release
  note&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python team:&lt;ul&gt;
&lt;li&gt;I packaged &lt;a href="https://bugs.debian.org/1072397"&gt;zope.deferredimport&lt;/a&gt;,
  needed for a new upstream version of&amp;nbsp;python-persistent.&lt;/li&gt;
&lt;li&gt;I fixed some incompatibilities with pytest 8:
  &lt;a href="https://bugs.debian.org/1070112"&gt;ipykernel&lt;/a&gt; and
  &lt;a href="https://bugs.debian.org/1071893"&gt;ipywidgets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I fixed a couple of &lt;span class="caps"&gt;RC&lt;/span&gt; or soon-to-be-&lt;span class="caps"&gt;RC&lt;/span&gt; bugs in khard
  (&lt;a href="https://bugs.debian.org/1065887"&gt;#1065887&lt;/a&gt; and
  &lt;a href="https://bugs.debian.org/1069838"&gt;#1069838&lt;/a&gt;), since I &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/new-address-book.html"&gt;use it for my
  address book&lt;/a&gt; and wanted to get it
  back into&amp;nbsp;testing.&lt;/li&gt;
&lt;li&gt;I fixed an &lt;span class="caps"&gt;RC&lt;/span&gt; bug in python-repoze.sphinx.autointerface
  (&lt;a href="https://bugs.debian.org/1057599"&gt;#1057599&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;I sponsored uploads of python-channels-redis (Dale Richards) and
  twisted (Florent &amp;#8216;Skia&amp;#8217;&amp;nbsp;Jacquet).&lt;/li&gt;
&lt;li&gt;I upgraded babelfish, django-favicon-plus-reloaded, dnsdiag,
  flake8-builtins, flufl.lock, ipywidgets, jsonpickle, langtable,
  nbconvert, requests, responses, partd, pytest-mock, python-aiohttp
  (fixing &lt;a href="https://bugs.debian.org/1062708"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-23829&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1062709"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-23334&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1070364"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-30251&lt;/a&gt;, and
  &lt;a href="https://bugs.debian.org/1070665"&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt;-2024-27306&lt;/a&gt;), python-amply,
  python-argcomplete, python-btrees, python-cups,
  python-django-health-check, python-fluent-logger, python-persistent,
  python-plumbum, python-rpaths, python-rt, python-sniffio,
  python-tenacity, python-tokenize-rt, python-typing-extensions,
  pyupgrade, sphinx-copybutton, sphinxcontrib-autoprogram,
  uncertainties, zodbpickle, zope.configuration, zope.proxy, and
  zope.security to new upstream&amp;nbsp;versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in May 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-05.html" rel="alternate"/><published>2024-06-02T11:53:01+01:00</published><updated>2024-06-02T11:53:01+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-06-02:/~cjwatson/blog/activity-2024-05.html</id><summary type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;The bulk of my Debian time this month went towards trying to haul more
Python packages up to current versions, but I got a few other bits and
pieces done as&amp;nbsp;well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did a little work on improving debbugs …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;p&gt;The bulk of my Debian time this month went towards trying to haul more
Python packages up to current versions, but I got a few other bits and
pieces done as&amp;nbsp;well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did a little work on improving debbugs&amp;#8217; autopkgtest&amp;nbsp;status.&lt;/li&gt;
&lt;li&gt;openssh:&lt;ul&gt;
&lt;li&gt;I fixed an &lt;a href="https://bugs.debian.org/1070403"&gt;OpenSSL version mismatch
  error&lt;/a&gt; in&amp;nbsp;openssh-ssh1.&lt;/li&gt;
&lt;li&gt;I finally tracked down a &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/commit/a980bf94a32f191a9e412eb0550c74ca6d96940b"&gt;baffling &lt;span class="caps"&gt;CI&lt;/span&gt;
  issue&lt;/a&gt;
  in openssh, unblocking several contributed merge requests that I&amp;#8217;d
  been sitting on until I could get &lt;span class="caps"&gt;CI&lt;/span&gt; to pass for them.  (Special
  thanks to Andreas Hasenack; &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/merge_requests/24"&gt;&lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; integration
  tests&lt;/a&gt;
  will make my life much&amp;nbsp;easier.)&lt;/li&gt;
&lt;li&gt;I removed the &lt;a href="https://bugs.debian.org/1018260"&gt;&lt;code&gt;user_readenv=1&lt;/code&gt;
  option&lt;/a&gt; from openssh&amp;#8217;s &lt;span class="caps"&gt;PAM&lt;/span&gt;
  configuration, and did some work on &lt;a href="https://salsa.debian.org/ddp-team/release-notes/-/merge_requests/204"&gt;release
  notes&lt;/a&gt;
  to document this change for affected&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;I started work on the first stage of my
  &lt;a href="https://lists.debian.org/debian-devel/2024/04/msg00044.html"&gt;plan&lt;/a&gt; to
  split out &lt;span class="caps"&gt;GSS&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; key exchange support to separate&amp;nbsp;packages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python team:&lt;ul&gt;
&lt;li&gt;I upgraded bitstruct, flufl.enum, flufl.testing, gunicorn, langtable,
  psycopg3, pygresql, pylint-flask, python-click-didyoumean,
  python-gssapi, python-httplib2, python-json-log-formatter,
  python-persistent, python-pgspecial, python-pyld, python-repoze.tm2,
  python-serializable, python-tenacity, python-typing-extensions,
  python-unidiff, responses, shortuuid (including an &lt;a href="https://github.com/skorokithakis/shortuuid/pull/105"&gt;upstream packaging
  tweak&lt;/a&gt;),
  sqlparse, vulture, zc.lockfile, and zope.interface to new upstream&amp;nbsp;versions.&lt;/li&gt;
&lt;li&gt;I cherry-picked an upstream &lt;span class="caps"&gt;PR&lt;/span&gt; to fix a &lt;a href="https://bugs.debian.org/1071893"&gt;pytest 8
  incompatibility&lt;/a&gt; in&amp;nbsp;ipywidgets.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I decided that fixing my old troffcvt package to &lt;a href="https://bugs.debian.org/1059802"&gt;support groff
   1.23.0&lt;/a&gt; wasn&amp;#8217;t worth the time
   investment, and filed a &lt;a href="https://bugs.debian.org/1071997"&gt;removal
   request&lt;/a&gt;&amp;nbsp;instead.&lt;/li&gt;
&lt;li&gt;I NMUed &lt;a href="https://bugs.debian.org/961964"&gt;bidentd&lt;/a&gt; and
   &lt;a href="https://bugs.debian.org/961967"&gt;linuxtv-dvb-apps&lt;/a&gt; to declare
   &lt;code&gt;Architecture: linux-any&lt;/code&gt; (and in the latter case also to fix a &lt;a href="https://bugs.debian.org/1066822"&gt;build
   failure due to 64-bit time&lt;/a&gt;), and worked
   with the buildd team to remove several of the other remaining entries
   from
   &lt;a href="https://salsa.debian.org/wb-team/packages-arch-specific"&gt;Packages-arch-specific&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Playing with rich</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/playing-with-rich.html" rel="alternate"/><published>2024-05-03T16:09:53+01:00</published><updated>2024-05-03T16:09:53+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-05-03:/~cjwatson/blog/playing-with-rich.html</id><summary type="html">&lt;p&gt;One of the things I do as a side project for Freexian is to work on
various bits of business automation: accounting tools, programs to help
contributors report their hours, invoicing, that kind of thing. While
it’s not quite my usual beat, this makes quite a good side project …&lt;/p&gt;</summary><content type="html">&lt;p&gt;One of the things I do as a side project for Freexian is to work on
various bits of business automation: accounting tools, programs to help
contributors report their hours, invoicing, that kind of thing. While
it’s not quite my usual beat, this makes quite a good side project as
the tools involved are mostly rather sensible and easy to deal with
(Python, git, &lt;a href="https://ledger-cli.org/"&gt;ledger&lt;/a&gt;, that sort of thing)
and it’s the kind of thing where I can dip into it for a day or so a
week and feel like I’m making useful contributions. The logic can be
quite complex, but there’s very little friction in the tools&amp;nbsp;themselves.&lt;/p&gt;
&lt;p&gt;A recent case where I did run into some friction in the tools was with
some commands that need to present small amounts of tabular data on the
terminal, using &lt;a href="https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda"&gt;&lt;span class="caps"&gt;OSC&lt;/span&gt;
8&lt;/a&gt;
hyperlinks if the terminal supports them: think customer-related
information with some links to issues. One of my colleagues had
previously done this using a
&lt;a href="https://github.com/foutaise/texttable/issues/87"&gt;hack&lt;/a&gt; on top of
&lt;a href="https://pypi.org/project/texttable/"&gt;texttable&lt;/a&gt;, which was perfectly
fine as far as it went. However, now I wanted to be able to add multiple
links in a single table cell in some cases, and that was really going to
stretch the limits of that approach: working out the width of the
displayed text in the cell was going to take an annoying amount of&amp;nbsp;bookkeeping.&lt;/p&gt;
&lt;p&gt;I started looking around to see whether any other approaches might be
easier, without too much effort (remember that “a day or so a week” bit
above). &lt;a href="https://pypi.org/project/ansiwrap/"&gt;ansiwrap&lt;/a&gt; looked
somewhat promising, but it isn’t currently packaged in Debian, and it
would have still left me with the problem of figuring out how to
integrate it into &lt;code&gt;texttable&lt;/code&gt;, which looked like it would be quite
complicated. Then I remembered that I’d heard good things about
&lt;a href="https://pypi.org/project/rich/"&gt;rich&lt;/a&gt;, and thought I’d take a&amp;nbsp;look.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rich&lt;/code&gt; turned out to be exactly what I wanted. Instead of something
like this based on the &lt;code&gt;texttable&lt;/code&gt; hack&amp;nbsp;above:&lt;/p&gt;
&lt;pre class="m-code"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;shutil&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pyxian.texttable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UrlTable&lt;/span&gt;

&lt;span class="n"&gt;termsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_terminal_size&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UrlTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;termsize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_deco&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UrlTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_cols_align&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;l&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_cols_dtype&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;u&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Issue&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="n"&gt;issue_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;#&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;issue_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;… now I can do this&amp;nbsp;instead:&lt;/p&gt;
&lt;pre class="m-code"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;box&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich.table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;

&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIMPLE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Issue&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[link=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;issue_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]#&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;issue_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;[/link]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rich&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;While this is a little shorter, the real bonus is that I can now just
put multiple &lt;code&gt;[link]&lt;/code&gt; tags in a single string, and it all just works.
No ceremony. In fact, once the relevant bits of code passed
type-checking (since the real code is a bit more complex than the
samples above), it worked first time. It’s a pleasure to work with a
library like&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;It looks like I’ve only barely scratched the surface of &lt;code&gt;rich&lt;/code&gt;, but I
expect I’ll reach for it more often&amp;nbsp;now.&lt;/p&gt;
</content><category term="columbiform"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in April 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-04.html" rel="alternate"/><published>2024-05-01T12:34:15+01:00</published><updated>2024-05-01T12:34:15+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-05-01:/~cjwatson/blog/activity-2024-04.html</id><summary type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;#8217;m trying to get back into bugs.debian.org administration, so I spent
   some time catching up on my &lt;code&gt;owner@bugs.debian.org&lt;/code&gt; mailbox and answering
   a number of support requests&amp;nbsp;there.&lt;/li&gt;
&lt;li&gt;I fixed a regression I&amp;#8217;d introduced …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;#8217;m trying to get back into bugs.debian.org administration, so I spent
   some time catching up on my &lt;code&gt;owner@bugs.debian.org&lt;/code&gt; mailbox and answering
   a number of support requests&amp;nbsp;there.&lt;/li&gt;
&lt;li&gt;I fixed a regression I&amp;#8217;d introduced last year where groff&amp;#8217;s &lt;span class="caps"&gt;PDF&lt;/span&gt; output
   had invalid date headers, both
   &lt;a href="https://git.savannah.gnu.org/cgit/groff.git/commit/?id=0815e503dba8d5c05921d68c6c718fe8f8440ee8"&gt;upstream&lt;/a&gt;
   and &lt;a href="https://bugs.debian.org/1069902"&gt;in Debian&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I released &lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2024-04/msg00000.html"&gt;man-db
   2.12.1&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;openssh:&lt;ul&gt;
&lt;li&gt;I did a little more testing of Luca Boccassi&amp;#8217;s
  &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=2641#c23"&gt;modifications&lt;/a&gt;
  to upstream&amp;#8217;s inline systemd notification&amp;nbsp;patch.&lt;/li&gt;
&lt;li&gt;I did an extensive
  &lt;a href="https://lists.debian.org/debian-devel/2024/04/msg00044.html"&gt;review&lt;/a&gt;
  of some of the choices in Debian&amp;#8217;s OpenSSH packaging, in light of last
  month&amp;#8217;s &lt;a href="https://tukaani.org/xz-backdoor/"&gt;xz-utils backdoor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I fixed a build failure on ppc64el, &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3673#c2"&gt;forwarded
  upstream&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I &lt;a href="https://bugs.debian.org/1068311"&gt;proposed&lt;/a&gt; reducing shared library
  linkage in tcp-wrappers; its maintainer accepted this by disabling &lt;span class="caps"&gt;NIS&lt;/span&gt;&amp;nbsp;support.&lt;/li&gt;
&lt;li&gt;I applied a &lt;a href="https://bugs.debian.org/1069706"&gt;suggestion&lt;/a&gt; to improve
  ordering of systemd services in relation to &lt;code&gt;nss-user-lookup.target&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I updated putty to&amp;nbsp;0.81.&lt;/li&gt;
&lt;li&gt;Python team:&lt;ul&gt;
&lt;li&gt;I fixed build/autopkgtest failures in
  &lt;a href="https://bugs.debian.org/1069360"&gt;cytoolz&lt;/a&gt; (&lt;a href="https://github.com/pytoolz/cytoolz/pull/205"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;), nbconvert (due to
  &lt;a href="https://bugs.debian.org/1042699"&gt;sphinx&lt;/a&gt; and
  &lt;a href="https://bugs.debian.org/1068349"&gt;lxml-html-clean&lt;/a&gt; changes),
  &lt;a href="https://bugs.debian.org/1069816"&gt;python-argcomplete&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1069817"&gt;python-exceptiongroup&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1069756"&gt;readability&lt;/a&gt;,
  &lt;a href="https://bugs.debian.org/1069818"&gt;toolz&lt;/a&gt; (&lt;a href="https://github.com/pytoolz/toolz/pull/578"&gt;upstream
  &lt;span class="caps"&gt;PR&lt;/span&gt;&lt;/a&gt;), and
  &lt;a href="https://bugs.debian.org/1069608"&gt;topplot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I made a &lt;a href="https://salsa.debian.org/science-team/pyferret/-/merge_requests/3"&gt;merge
  request&lt;/a&gt;
  to fix a &lt;a href="https://bugs.debian.org/1058888"&gt;build failure&lt;/a&gt; in&amp;nbsp;pyferret.&lt;/li&gt;
&lt;li&gt;I fixed a
  &lt;a href="https://salsa.debian.org/python-team/packages/python-ecdsa/-/commit/3a95d8623d28d73c8c7877e6c3ddd5ee43e33ca4"&gt;mistake&lt;/a&gt;
  in a Debian patch to python-ecdsa, noticed while updating&amp;nbsp;jsonpickle.&lt;/li&gt;
&lt;li&gt;I updated cachelib, dnsdiag, feedparser, jsonpickle, pywavelets
  (fixing a &lt;a href="https://bugs.debian.org/1068805"&gt;distutils dependency&lt;/a&gt;),
  python-aiohttp-session, python-avro, python-rstr, vine (including an
  &lt;a href="https://github.com/celery/vine/pull/109"&gt;upstream packaging tweak&lt;/a&gt;,
  and wtforms to new upstream&amp;nbsp;versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I did some inconclusive investigation of &lt;a href="https://bugs.debian.org/1057562"&gt;flaky tests in
   gcr4&lt;/a&gt;.  More work is needed&amp;nbsp;there.&lt;/li&gt;
&lt;li&gt;I proposed a patch for a build failure in gyoto, both
   &lt;a href="https://github.com/gyoto/Gyoto/pull/17"&gt;upstream&lt;/a&gt; and &lt;a href="https://bugs.debian.org/1066788"&gt;in
   Debian&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can support my work directly via
&lt;a href="https://liberapay.com/cjwatson"&gt;Liberapay&lt;/a&gt;.&lt;/p&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in March 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-03.html" rel="alternate"/><published>2024-04-01T14:10:41+01:00</published><updated>2024-04-01T14:10:41+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-04-01:/~cjwatson/blog/activity-2024-03.html</id><summary type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python team:&lt;ul&gt;
&lt;li&gt;I updated
  &lt;a href="https://tracker.debian.org/pkg/zope.testrunner"&gt;zope.testrunner&lt;/a&gt; to&amp;nbsp;6.4.&lt;/li&gt;
&lt;li&gt;I fixed a &lt;a href="https://bugs.debian.org/999908"&gt;build failure in
  celery-haystack-ng&lt;/a&gt;, which included an
  &lt;a href="https://edugit.org/AlekSIS/libs/celery-haystack-ng/-/merge_requests/2"&gt;upstream change to stop using
  &lt;code&gt;d2to1&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I backported an upstream change to fix a &lt;a href="https://bugs.debian.org/1061754"&gt;build failure in
  python-json-log-formatter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I updated python-typing-extensions …&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;My Debian contributions this month were all
&lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsored&lt;/a&gt; by&amp;nbsp;Freexian.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python team:&lt;ul&gt;
&lt;li&gt;I updated
  &lt;a href="https://tracker.debian.org/pkg/zope.testrunner"&gt;zope.testrunner&lt;/a&gt; to&amp;nbsp;6.4.&lt;/li&gt;
&lt;li&gt;I fixed a &lt;a href="https://bugs.debian.org/999908"&gt;build failure in
  celery-haystack-ng&lt;/a&gt;, which included an
  &lt;a href="https://edugit.org/AlekSIS/libs/celery-haystack-ng/-/merge_requests/2"&gt;upstream change to stop using
  &lt;code&gt;d2to1&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I backported an upstream change to fix a &lt;a href="https://bugs.debian.org/1061754"&gt;build failure in
  python-json-log-formatter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I updated python-typing-extensions to 4.10.0 to fix a &lt;a href="https://bugs.debian.org/1064739"&gt;build
  failure&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I updated wcwidth to 0.2.13 to fix a &lt;a href="https://bugs.debian.org/1042241"&gt;build
  failure&lt;/a&gt;, which included rewriting
  the Debian patches to &lt;code&gt;update-tables&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I updated jsonpickle to 3.0.3 to fix a &lt;a href="https://bugs.debian.org/1064705"&gt;build
  failure&lt;/a&gt;.  As part of this I also
  needed to &lt;a href="https://github.com/jsonpickle/jsonpickle/pull/479"&gt;fix its tests for new timezone name
  policies&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;man-db:&lt;ul&gt;
&lt;li&gt;I updated man(1) with &lt;a href="https://gitlab.com/man-db/man-db/-/issues/34"&gt;updated information about
  groff&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I &lt;a href="https://gitlab.com/man-db/man-db/-/issues/35"&gt;documented italic
  support&lt;/a&gt; in&amp;nbsp;man(1).&lt;/li&gt;
&lt;li&gt;I started on a 2.12.1 release (currently waiting for&amp;nbsp;translations).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;openssh:&lt;ul&gt;
&lt;li&gt;I added an &lt;a href="https://bugs.debian.org/1061516"&gt;&lt;code&gt;sshd@.service&lt;/code&gt; template&lt;/a&gt;
  to help newer versions of &lt;code&gt;systemd&lt;/code&gt; make containers and VMs
  &lt;span class="caps"&gt;SSH&lt;/span&gt;-accessible over &lt;code&gt;AF_VSOCK&lt;/code&gt; sockets.&lt;/li&gt;
&lt;li&gt;I upgraded openssh to 9.7p1.  As part of this I noticed a &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3671"&gt;small bug
  in the PuTTY version detection in its regression
  tests&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I helped with the 64-bit &lt;code&gt;time_t&lt;/code&gt; transition by applying a patch from
  Simon McVittie to &lt;a href="https://bugs.debian.org/1066847"&gt;temporarily disable &lt;code&gt;ssh-askpass-gnome&lt;/code&gt; on the
  affected architectures&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=3676"&gt;re-enabled interoperability tests with Twisted
  Conch&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Following the &lt;a href="https://tukaani.org/xz-backdoor/"&gt;xz-utils backdoor&lt;/a&gt;, I
  spent some time testing OpenSSH upstream&amp;#8217;s proposed &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=2641#c13"&gt;inline systemd
  notification
  patch&lt;/a&gt; and
  suggested a small&amp;nbsp;adjustment.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;debconf:&lt;ul&gt;
&lt;li&gt;I fixed &lt;code&gt;dpkg-preconfigure&lt;/code&gt; to not &lt;a href="https://bugs.debian.org/1043465"&gt;produce errors when run from a
  non-existing directory&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;parted:&lt;ul&gt;
&lt;li&gt;I applied a patch from Helmut Grohne to &lt;a href="https://bugs.debian.org/1067772"&gt;move files to
  /usr&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I fixed an &lt;a href="https://github.com/neovim/neovim/pull/27780"&gt;off-by-one error in
   neovim&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I fixed a number of &lt;code&gt;-Werror=implicit-function-declaration&lt;/code&gt; failures
   (&lt;a href="https://bugs.debian.org/1066389"&gt;db1-compat&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1066562"&gt;kali&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1066692"&gt;knews&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1065757"&gt;openssh-ssh1&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1067013"&gt;trn4&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1066078"&gt;vigor&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;I fixed a &lt;a href="https://bugs.debian.org/1064761"&gt;build failure&lt;/a&gt; in
   libsdl-perl, including a &lt;a href="https://github.com/PerlGameDev/SDL/pull/308"&gt;reference-counting
   fix&lt;/a&gt; contributed&amp;nbsp;upstream.&lt;/li&gt;
&lt;li&gt;I suggested an &lt;a href="https://github.com/WayneD/rsync/pull/586"&gt;&lt;code&gt;rrsync&lt;/code&gt;
   change&lt;/a&gt; to make it easier to
   use it with&amp;nbsp;rsbackup.&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>apt install everything?</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ubuntu-install-everything.html" rel="alternate"/><published>2024-03-19T07:05:27+00:00</published><updated>2024-03-19T07:05:27+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-03-19:/~cjwatson/blog/ubuntu-install-everything.html</id><summary type="html">&lt;p&gt;On Mastodon, the
&lt;a href="https://mastodon.social/@Hacksaw/112118031428498349"&gt;question&lt;/a&gt; came up of
how Ubuntu would deal with something like the &lt;a href="https://boehs.org/node/npm-everything"&gt;npm install
everything&lt;/a&gt; situation.  I&amp;nbsp;replied:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ubuntu is curated, so it probably wouldn&amp;#8217;t get this far.  If it did, then
the worst case is that it would get in the way of &lt;span class="caps"&gt;CI&lt;/span&gt; allowing …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;On Mastodon, the
&lt;a href="https://mastodon.social/@Hacksaw/112118031428498349"&gt;question&lt;/a&gt; came up of
how Ubuntu would deal with something like the &lt;a href="https://boehs.org/node/npm-everything"&gt;npm install
everything&lt;/a&gt; situation.  I&amp;nbsp;replied:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ubuntu is curated, so it probably wouldn&amp;#8217;t get this far.  If it did, then
the worst case is that it would get in the way of &lt;span class="caps"&gt;CI&lt;/span&gt; allowing other
packages to be removed (again from a curated system, so people are used to
removal not being self-service); but the release team would have no
hesitation in removing a package like this to fix that, and it certainly
wouldn&amp;#8217;t cause this amount of&amp;nbsp;angst.&lt;/p&gt;
&lt;p&gt;If you did this in a &lt;a href="https://help.launchpad.net/Packaging/PPA"&gt;&lt;span class="caps"&gt;PPA&lt;/span&gt;&lt;/a&gt;, then
I can&amp;#8217;t think of any particular negative&amp;nbsp;effects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class="caps"&gt;OK&lt;/span&gt;, if you added lots of build-dependencies (as well as run-time
dependencies) then you might be able to take out a builder.  But Launchpad
builders already run arbitrary user-submitted code by design and are
therefore very carefully sandboxed and treated as ephemeral, so this is
hardly&amp;nbsp;novel.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a lot to be said for the arrangement of having a curated system for
the stuff people actually care about plus an ecosystem of add-on
repositories.  PPAs cover a wide range of levels of developer activity, from
throwaway experiments to quasi-official distribution methods; there are
certainly problems that arise from it being difficult to tell the difference
between those extremes and from there being no systematic confinement, but
for this particular kind of problem they&amp;#8217;re very nearly ideal.  (Canonical
has tried various other approaches to software distribution, and while they
address some of the problems, they &lt;a href="https://popey.com/blog/2024/03/exodus-wallet-part-three/"&gt;aren&amp;#8217;t obviously
better&lt;/a&gt; at helping
people make reliable social judgements about code they don&amp;#8217;t&amp;nbsp;know.)&lt;/p&gt;
&lt;p&gt;For a hypothetical package with a huge number of dependencies, to even try
to upload it directly to Ubuntu you&amp;#8217;d need to be an Ubuntu developer with
upload rights (or to go via Debian, where you&amp;#8217;d have to clear a similar
hurdle).  If you have those, then the first upload has to pass manual review
by an archive administrator.  If your package passes that, then it still has
to build and get through
&lt;a href="https://wiki.ubuntu.com/ProposedMigration"&gt;proposed-migration&lt;/a&gt; &lt;span class="caps"&gt;CI&lt;/span&gt; before it
reaches anything that humans typically care&amp;nbsp;about.&lt;/p&gt;
&lt;p&gt;On the other hand, if you were inclined to try this sort of experiment,
you&amp;#8217;d almost certainly try it in a &lt;span class="caps"&gt;PPA&lt;/span&gt;, and that would trouble nobody but&amp;nbsp;yourself.&lt;/p&gt;</content><category term="ubuntu"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Free software activity in January/February 2024</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2024-02.html" rel="alternate"/><published>2024-03-04T10:39:50+00:00</published><updated>2024-03-04T10:39:50+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-03-04:/~cjwatson/blog/activity-2024-02.html</id><summary type="html">&lt;p&gt;Two months into my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/going-freelance.html"&gt;new gig&lt;/a&gt; and it&amp;#8217;s going
great!  &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/task-management.html"&gt;Tracking my time&lt;/a&gt; has taken a bit of
getting used to, but having something that amounts to a queryable database
of everything I&amp;#8217;ve done has also allowed some helpful&amp;nbsp;introspection.&lt;/p&gt;
&lt;p&gt;Freexian &lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsors&lt;/a&gt; up
to 20% of my time …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Two months into my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/going-freelance.html"&gt;new gig&lt;/a&gt; and it&amp;#8217;s going
great!  &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/task-management.html"&gt;Tracking my time&lt;/a&gt; has taken a bit of
getting used to, but having something that amounts to a queryable database
of everything I&amp;#8217;ve done has also allowed some helpful&amp;nbsp;introspection.&lt;/p&gt;
&lt;p&gt;Freexian &lt;a href="https://www.freexian.com/about/debian-contributions/"&gt;sponsors&lt;/a&gt; up
to 20% of my time on Debian tasks of my choice.  In fact I&amp;#8217;ve been spending
the bulk of my time on
&lt;a href="https://freexian-team.pages.debian.net/debusine/"&gt;debusine&lt;/a&gt; which is itself
intended to accelerate work on Debian, but more details on that later.
While I contribute to Freexian&amp;#8217;s
&lt;a href="https://www.freexian.com/tags/debian-contributions/"&gt;summaries&lt;/a&gt; now, I&amp;#8217;ve
also decided to start writing monthly posts about my free software activity
as many others do, to get into some more&amp;nbsp;detail.&lt;/p&gt;
&lt;h2&gt;January&amp;nbsp;2024&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I &lt;a href="https://salsa.debian.org/ci-team/autopkgtest/-/merge_requests/272"&gt;added Incus
   support&lt;/a&gt;
   to autopkgtest.  &lt;a href="https://linuxcontainers.org/incus/"&gt;Incus&lt;/a&gt; is a system
   container and virtual machine manager, forked from &lt;a href="https://github.com/canonical/lxd"&gt;Canonical&amp;#8217;s
   &lt;span class="caps"&gt;LXD&lt;/span&gt;&lt;/a&gt;.  I switched my laptop over to it
   and then quickly found that it was inconvenient not to be able to run
   Debian package test suites using
   &lt;a href="https://manpages.debian.org/man/autopkgtest"&gt;autopkgtest&lt;/a&gt;, so I tweaked
   autopkgtest&amp;#8217;s existing &lt;span class="caps"&gt;LXD&lt;/span&gt; integration to support using either &lt;span class="caps"&gt;LXD&lt;/span&gt; or&amp;nbsp;Incus.&lt;/li&gt;
&lt;li&gt;I discovered &lt;a href="https://metacpan.org/dist/Perl-Critic"&gt;Perl::Critic&lt;/a&gt; and
   used it to tidy up some poor practices in several of my packages,
   including debconf.  Perl used to be my language of choice but I&amp;#8217;ve been
   mostly using Python for over a decade now, so I&amp;#8217;m not as fluent as I used
   to be and some mechanical assistance with spotting common errors is
   helpful; besides, I&amp;#8217;m generally a big fan of applying static analysis to
   everything possible in the hope of reducing bug density.  Of course, this
   did result in a couple of regressions
   (&lt;a href="https://salsa.debian.org/pkg-debconf/debconf/-/commit/4f8b9f969679fa4a38aca8da2702057ea861ffae"&gt;1&lt;/a&gt;,
   &lt;a href="https://salsa.debian.org/pkg-debconf/debconf/-/commit/7274bf66e82b2557156813f93ed0592539a2ac1c"&gt;2&lt;/a&gt;),
   but at least we caught them fairly&amp;nbsp;quickly.&lt;/li&gt;
&lt;li&gt;I did some overdue debconf maintenance, mainly around tidying up error
   message handling in several places (&lt;a href="https://bugs.debian.org/797071"&gt;1&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/754123"&gt;2&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/682508"&gt;3&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;I did some routine maintenance to move several of my upstream projects to
   a new &lt;a href="https://www.gnu.org/software/gnulib/manual/html_node/Stable-Branches.html"&gt;Gnulib stable
   branch&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://salsa.debian.org/debian/debmirror"&gt;debmirror&lt;/a&gt; includes a &lt;a href="https://salsa.debian.org/debian/debmirror/-/blob/master/mirror_size"&gt;useful
   summary&lt;/a&gt;
   of how big a Debian mirror is, but it hadn&amp;#8217;t been updated since 2010 and
   the script to do so had bitrotted quite badly.  I &lt;a href="https://salsa.debian.org/debian/debmirror/-/commit/7ae93742377d9205c57b7e47ef96d4663110f0ff"&gt;fixed
   that&lt;/a&gt;
   and added a recurring task for myself to refresh this every six&amp;nbsp;months.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;February&amp;nbsp;2024&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some time back I added AppArmor and seccomp confinement to man-db.  This
   was mainly motivated by a desire to &lt;a href="https://forum.snapcraft.io/t/support-for-man-pages/2299/24"&gt;support manual pages in
   snaps&lt;/a&gt; (which
   is &lt;a href="https://bugs.launchpad.net/snapd/+bug/1575593"&gt;still open&lt;/a&gt; several
   years later &amp;#8230;), but since reading manual pages involves a &lt;a href="https://www.gnu.org/software/groff/"&gt;non-trivial
   text processing toolchain mostly written in
   C++&lt;/a&gt;, I thought it was reasonable to
   assume that some day it might have a vulnerability even though its track
   record has been good; so &lt;code&gt;man&lt;/code&gt; now restricts the system calls that
   &lt;code&gt;groff&lt;/code&gt; can execute and the parts of the file system that it can access.
   I stand by this, but it did cause some problems that have needed a
   succession of small fixes over the years.  This month I issued
   &lt;a href="https://lists.debian.org/debian-lts-announce/2024/02/msg00001.html"&gt;&lt;span class="caps"&gt;DLA&lt;/span&gt;-3731-1&lt;/a&gt;,
   backporting some of those fixes to&amp;nbsp;buster.&lt;/li&gt;
&lt;li&gt;I spent some time chasing a &lt;a href="https://bugs.debian.org/1063413"&gt;console-setup build
   failure&lt;/a&gt; following the removal of
   kFreeBSD support, which was uploaded by mistake.  I suggested a &lt;a href="https://salsa.debian.org/holgerw/console-setup/-/merge_requests/1"&gt;set of
   fixes&lt;/a&gt;
   for this, but the author of the change to remove kFreeBSD support decided
   to take a different approach (fair enough), so I&amp;#8217;ve abandoned&amp;nbsp;this.&lt;/li&gt;
&lt;li&gt;I updated the &lt;a href="https://tracker.debian.org/pkg/zope.testrunner"&gt;Debian zope.testrunner
   package&lt;/a&gt; to&amp;nbsp;6.3.1.&lt;/li&gt;
&lt;li&gt;openssh:&lt;ul&gt;
&lt;li&gt;A Freexian collaborator had a problem with automating installations
  involving changes to &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;.  This turned out to be
  resolvable without any changes, but in the process of investigating I
  noticed that my dodgy arrangements to avoid
  &lt;a href="https://manpages.debian.org/man/ucf"&gt;ucf&lt;/a&gt; prompts in certain cases
  had bitrotted slightly, which meant that some people might be prompted
  unnecessarily.  I &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/commit/b9671cc74475922fa61e9ebdba56ec84446d19ac"&gt;fixed this and arranged for it not to happen
  again&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Following a &lt;a href="https://lists.debian.org/debian-devel/2024/02/msg00239.html"&gt;recent debian-devel
  discussion&lt;/a&gt;,
  I realized that some particularly awkward code in the OpenSSH
  packaging was now obsolete, and &lt;a href="https://salsa.debian.org/ssh-team/openssh/-/commit/a6c7b9ef532489671e3a654ad38102cc30d94b5a"&gt;removed
  it&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I backported a &lt;a href="https://bugs.debian.org/1027387"&gt;python-channels-redis
   fix&lt;/a&gt; to bookworm.  I wasn&amp;#8217;t the first
   person to run into this, but I rediscovered it while working on debusine
   and it was confusing enough that it seemed worth fixing in&amp;nbsp;stable.&lt;/li&gt;
&lt;li&gt;I fixed a &lt;a href="https://bugs.debian.org/1064699"&gt;simple build failure in
   storm&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I dug into a very confusing cluster of celery build failures
   (&lt;a href="https://bugs.debian.org/1056232"&gt;1&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1058317"&gt;2&lt;/a&gt;,
   &lt;a href="https://bugs.debian.org/1063345"&gt;3&lt;/a&gt;), and tracked the hardest bit down
   to a &lt;a href="https://github.com/python/cpython/issues/115874"&gt;Python 3.12
   regression&lt;/a&gt;, now fixed
   in unstable thanks to Stefano Rivera.  Getting celery back into testing
   is blocked on the &lt;a href="https://wiki.debian.org/ReleaseGoals/64bit-time"&gt;64-bit &lt;code&gt;time_t&lt;/code&gt;
   transition&lt;/a&gt; for now, but
   once that&amp;#8217;s out of the way it should flow smoothly&amp;nbsp;again.&lt;/li&gt;
&lt;/ul&gt;</content><category term="columbiform"/><category term="activity"/><category term="columbiform"/><category term="freexian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Task management</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/task-management.html" rel="alternate"/><published>2024-01-17T13:28:19+00:00</published><updated>2024-01-17T13:28:19+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-01-17:/~cjwatson/blog/task-management.html</id><summary type="html">&lt;p&gt;Now that I&amp;#8217;m &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/going-freelance.html"&gt;freelancing&lt;/a&gt;, I need to
actually track my time, which is something I&amp;#8217;ve had the luxury of not having
to do before.  That meant something of a rethink of the way I&amp;#8217;ve been
keeping track of my to-do list.  Up to now that was a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Now that I&amp;#8217;m &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/going-freelance.html"&gt;freelancing&lt;/a&gt;, I need to
actually track my time, which is something I&amp;#8217;ve had the luxury of not having
to do before.  That meant something of a rethink of the way I&amp;#8217;ve been
keeping track of my to-do list.  Up to now that was a combination of things
like the bug lists for the projects I&amp;#8217;m working on at the moment, whatever
task tracking system Canonical was using at the moment (Jira when I left),
and a giant flat text file in which I recorded logbook-style notes of what
I&amp;#8217;d done each day plus a few extra notes at the bottom to remind myself of
particularly urgent tasks.  I &lt;em&gt;could&lt;/em&gt; have started manually adding times to
each logbook entry, but ugh, let&amp;#8217;s&amp;nbsp;not.&lt;/p&gt;
&lt;p&gt;In general, I had the following goals (which were a bit reminiscent of my
&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/new-address-book.html"&gt;address book&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;free software&amp;nbsp;throughout&lt;/li&gt;
&lt;li&gt;storage under my&amp;nbsp;control&lt;/li&gt;
&lt;li&gt;ability to annotate tasks with URLs (especially bugs and merge&amp;nbsp;requests)&lt;/li&gt;
&lt;li&gt;lightweight time tracking (I&amp;#8217;m &lt;span class="caps"&gt;OK&lt;/span&gt; with having to explicitly tell it when
   I start and stop&amp;nbsp;tasks)&lt;/li&gt;
&lt;li&gt;ability to drive everything from the command&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;decent filtering so I don&amp;#8217;t have to look at my entire to-do list all the&amp;nbsp;time&lt;/li&gt;
&lt;li&gt;ability to easily generate billing information for multiple&amp;nbsp;clients&lt;/li&gt;
&lt;li&gt;optionally, integration with Android (mainly so I can tick off personal
   tasks like &amp;#8220;change bedroom lightbulb&amp;#8221; or whatever that don&amp;#8217;t involve
   being near a&amp;nbsp;computer)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I didn&amp;#8217;t do an elaborate evaluation of multiple options, because I&amp;#8217;m not
trying to come up with the best possible solution for a client here.  Also,
there are a bazillion to-do list trackers out there and if I tried to
evaluate them all I&amp;#8217;d never do anything else.  I just wanted something that
works well enough for&amp;nbsp;me.&lt;/p&gt;
&lt;p&gt;Since it &lt;a href="https://fosstodon.org/@dondelelcaro/111682622624262162"&gt;came up on
Mastodon&lt;/a&gt;: a bunch
of people swear by &lt;a href="https://orgmode.org/"&gt;Org mode&lt;/a&gt;, which I know can do at
least some of this sort of thing.  However, I don&amp;#8217;t use Emacs and don&amp;#8217;t plan
to use Emacs.  &lt;a href="https://github.com/nvim-orgmode/orgmode"&gt;nvim-orgmode&lt;/a&gt; does
have some support for time tracking, but when I&amp;#8217;ve tried &lt;code&gt;vim&lt;/code&gt;-based
versions of Org mode in the past I&amp;#8217;ve found they haven&amp;#8217;t really fitted my
brain very&amp;nbsp;well.&lt;/p&gt;
&lt;h2&gt;Taskwarrior and&amp;nbsp;Timewarrior&lt;/h2&gt;
&lt;p&gt;One of the other Freexian collaborators mentioned
&lt;a href="https://taskwarrior.org/"&gt;Taskwarrior&lt;/a&gt; and
&lt;a href="https://timewarrior.net/"&gt;Timewarrior&lt;/a&gt;, so I had a look at&amp;nbsp;those.&lt;/p&gt;
&lt;p&gt;The basic idea of Taskwarrior is that you have a &lt;code&gt;task&lt;/code&gt; command that tracks
each task as a blob of &lt;span class="caps"&gt;JSON&lt;/span&gt; and provides subcommands to let you add, modify,
and remove tasks with a minimum of friction.  &lt;code&gt;task add&lt;/code&gt; adds a task, and
you can add metadata like &lt;code&gt;project:Personal&lt;/code&gt; (I always make sure every task
has a project, for ease of filtering).  Just running &lt;code&gt;task&lt;/code&gt; shows you a task
list sorted by Taskwarrior&amp;#8217;s idea of urgency, with an &lt;span class="caps"&gt;ID&lt;/span&gt; for each task, and
there are various other reports with different filtering and verbosity.
&lt;code&gt;task &amp;lt;id&amp;gt; annotate&lt;/code&gt; lets you attach more information to a task.  &lt;code&gt;task &amp;lt;id&amp;gt;
done&lt;/code&gt; marks it as done.  So far so good, so a redacted version of my to-do
list looks like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;task&lt;span class="w"&gt; &lt;/span&gt;ls

ID&lt;span class="w"&gt; &lt;/span&gt;A&lt;span class="w"&gt; &lt;/span&gt;Project&lt;span class="w"&gt;     &lt;/span&gt;Tags&lt;span class="w"&gt;                 &lt;/span&gt;Description
&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Freexian&lt;span class="w"&gt;                         &lt;/span&gt;Add&lt;span class="w"&gt; &lt;/span&gt;Incus&lt;span class="w"&gt; &lt;/span&gt;support&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;autopkgtest&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Columbiform&lt;span class="w"&gt;                      &lt;/span&gt;Figure&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="w"&gt; &lt;/span&gt;Lloyds&lt;span class="w"&gt; &lt;/span&gt;online&lt;span class="w"&gt; &lt;/span&gt;banking&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Debian&lt;span class="w"&gt;                           &lt;/span&gt;Fix&lt;span class="w"&gt; &lt;/span&gt;troffcvt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;groff&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.23.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;Personal&lt;span class="w"&gt;                         &lt;/span&gt;Replace&lt;span class="w"&gt; &lt;/span&gt;living&lt;span class="w"&gt; &lt;/span&gt;room&lt;span class="w"&gt; &lt;/span&gt;curtain&lt;span class="w"&gt; &lt;/span&gt;rail
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once I got comfortable with it, this was already a big improvement.  I
haven&amp;#8217;t bothered to learn all the filtering gadgets yet, but it was easy
enough to see that I could do something like &lt;code&gt;task all project:Personal&lt;/code&gt; and
it&amp;#8217;d show me both pending and completed tasks in that project, and that all
the data was stored in &lt;code&gt;~/.task&lt;/code&gt; - though I have to say that there are
enough reporting bells and whistles that I haven&amp;#8217;t needed to poke around
manually.  In combination with the regular backups that I do anyway (you do
too, right?), this gave me enough confidence to abandon my previous
text-file logbook&amp;nbsp;approach.&lt;/p&gt;
&lt;p&gt;Next was time tracking.  Timewarrior integrates with Taskwarrior, albeit in
&lt;a href="https://timewarrior.net/docs/taskwarrior/"&gt;an only semi-packaged way&lt;/a&gt;, and
it was easy enough to set that up.  Now I can&amp;nbsp;do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;task&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;start
Starting&lt;span class="w"&gt; &lt;/span&gt;task&lt;span class="w"&gt; &lt;/span&gt;00a9516f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Write blog post about task tracking&amp;#39;&lt;/span&gt;.
Started&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;task.
Note:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;quot;Write blog post about task tracking&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;tag.
Tracking&lt;span class="w"&gt; &lt;/span&gt;Columbiform&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Write blog post about task tracking&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;Started&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2024&lt;/span&gt;-01-10T11:28:38
&lt;span class="w"&gt;  &lt;/span&gt;Current&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="m"&gt;38&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;Total&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;:00:00
You&lt;span class="w"&gt; &lt;/span&gt;have&lt;span class="w"&gt; &lt;/span&gt;more&lt;span class="w"&gt; &lt;/span&gt;urgent&lt;span class="w"&gt; &lt;/span&gt;tasks.
Project&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Columbiform&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tasks&lt;span class="w"&gt; &lt;/span&gt;remaining&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When I stop work on something, I do &lt;code&gt;task active&lt;/code&gt; to find the &lt;span class="caps"&gt;ID&lt;/span&gt;, then &lt;code&gt;task
&amp;lt;id&amp;gt; stop&lt;/code&gt;.  Timewarrior does the tedious stopwatch business for me, and I
can manually enter times if I forget to start/stop a task.  Then the really
useful bit: I can do something like &lt;code&gt;timew summary :month &amp;lt;name-of-client&amp;gt;&lt;/code&gt;
and it tells me how much to bill that client for this month.&amp;nbsp;Perfect.&lt;/p&gt;
&lt;p&gt;I also started using &lt;a href="https://github.com/vit-project/vit"&gt;&lt;span class="caps"&gt;VIT&lt;/span&gt;&lt;/a&gt; to simplify
the day-to-day flow a little, which means I&amp;#8217;m normally just using one or two
keystrokes rather than typing longer commands.  That isn&amp;#8217;t really necessary
from my point of view, but it does save some&amp;nbsp;time.&lt;/p&gt;
&lt;h2&gt;Android&amp;nbsp;integration&lt;/h2&gt;
&lt;p&gt;I left Android integration for a bit later since it wasn&amp;#8217;t essential.  When
I got round to it, I have to say that it felt a bit clumsy, but it did
eventually&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;The first step was to &lt;a href="https://gothenburgbitfactory.github.io/taskserver-setup/"&gt;set up a
taskserver&lt;/a&gt;.  Most
of the setup procedure was &lt;span class="caps"&gt;OK&lt;/span&gt;, but I wanted to use Let&amp;#8217;s Encrypt to minimize
the amount of messing around with CAs I had to do.  Getting this to work
involved hitting things with sticks a bit, and there&amp;#8217;s still a local &lt;span class="caps"&gt;CA&lt;/span&gt;
involved for client certificates.  What I ended up with was a &lt;code&gt;certbot&lt;/code&gt;
setup with the &lt;code&gt;webroot&lt;/code&gt; authenticator and a custom deploy hook as follows
(with &lt;code&gt;cert_name&lt;/code&gt; replaced by a &lt;span class="caps"&gt;DNS&lt;/span&gt; name in my house&amp;nbsp;domain):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#! /bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-eu

&lt;span class="nv"&gt;cert_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;taskd.example.org

&lt;span class="nv"&gt;found&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;domain&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$RENEWED_DOMAINS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;$cert_name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;found&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="nv"&gt;$found&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;

install&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;644&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/etc/letsencrypt/live/&lt;/span&gt;&lt;span class="nv"&gt;$cert_name&lt;/span&gt;&lt;span class="s2"&gt;/fullchain.pem&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/var/lib/taskd/pki/fullchain.pem
install&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;640&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;Debian-taskd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/etc/letsencrypt/live/&lt;/span&gt;&lt;span class="nv"&gt;$cert_name&lt;/span&gt;&lt;span class="s2"&gt;/privkey.pem&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;/var/lib/taskd/pki/privkey.pem

systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;taskd.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I could then set this in &lt;code&gt;/etc/taskd/config&lt;/code&gt; (&lt;code&gt;server.crl.pem&lt;/code&gt; and
&lt;code&gt;ca.cert.pem&lt;/code&gt; were generated using the documented taskserver setup&amp;nbsp;procedure):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;taskd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;taskd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fullchain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crl&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;taskd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;
&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;=/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;taskd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I could set &lt;code&gt;taskd.ca&lt;/code&gt; on my laptop to
&lt;code&gt;/usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt&lt;/code&gt; and otherwise follow
the client setup instructions, run &lt;code&gt;task sync init&lt;/code&gt; to get things started,
and then &lt;code&gt;task sync&lt;/code&gt; every so often to sync changes between my laptop and
the&amp;nbsp;taskserver.&lt;/p&gt;
&lt;p&gt;I used &lt;a href="https://play.google.com/store/apps/details?id=com.ccextractor.taskwarriorflutter"&gt;TaskWarrior
Mobile&lt;/a&gt;
as the client.  I have to say I wouldn&amp;#8217;t want to use that client as my
primary task tracking interface: the setup procedure is clunky even beyond
the necessity of copying a client certificate around, it expects you to give
it a &lt;code&gt;.taskrc&lt;/code&gt; rather than having a proper settings interface for that, and
it only seems to let you add a task if you specify a due date for it.  It
also lacks Timewarrior integration, so I can only really use it when I don&amp;#8217;t
care about time tracking, e.g. personal tasks.  But that&amp;#8217;s really all I
need, so it meets my minimum&amp;nbsp;requirements.&lt;/p&gt;
&lt;h2&gt;Next?&lt;/h2&gt;
&lt;p&gt;Considering this is literally the first thing I tried, I have to say I&amp;#8217;m
pretty happy with it.  There are a bunch of optional extras I haven&amp;#8217;t tried
yet, but in general it kind of has the &lt;code&gt;vim&lt;/code&gt; nature for me: if I need
something it&amp;#8217;s very likely to exist or easy enough to build, but the
features I don&amp;#8217;t use don&amp;#8217;t get in my&amp;nbsp;way.&lt;/p&gt;
&lt;p&gt;I wouldn&amp;#8217;t recommend any of this to somebody who didn&amp;#8217;t already spend most
of their time in a terminal - but I do.  I&amp;#8217;m glad people have gone to all
the effort to build this so I didn&amp;#8217;t have&amp;nbsp;to.&lt;/p&gt;</content><category term="columbiform"/><category term="columbiform"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>OpenUK New Year’s Honours</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/openuk-new-years-honours.html" rel="alternate"/><published>2024-01-15T16:15:49+00:00</published><updated>2024-01-15T16:15:49+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-01-15:/~cjwatson/blog/openuk-new-years-honours.html</id><summary type="html">&lt;p&gt;Apparently I got an &lt;a href="https://openuk.uk/2024-honours-list/"&gt;honour&lt;/a&gt; from&amp;nbsp;OpenUK.&lt;/p&gt;
&lt;p&gt;There are a bunch of people I know on that list.  Chris Lamb and Mark Brown
are familiar names from &lt;a href="https://www.debian.org/"&gt;Debian&lt;/a&gt;.  Colin King and
Jonathan Riddell are people I know from past work in
&lt;a href="https://ubuntu.com/"&gt;Ubuntu&lt;/a&gt;.  I&amp;#8217;ve admired David MacIver&amp;#8217;s work on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Apparently I got an &lt;a href="https://openuk.uk/2024-honours-list/"&gt;honour&lt;/a&gt; from&amp;nbsp;OpenUK.&lt;/p&gt;
&lt;p&gt;There are a bunch of people I know on that list.  Chris Lamb and Mark Brown
are familiar names from &lt;a href="https://www.debian.org/"&gt;Debian&lt;/a&gt;.  Colin King and
Jonathan Riddell are people I know from past work in
&lt;a href="https://ubuntu.com/"&gt;Ubuntu&lt;/a&gt;.  I&amp;#8217;ve admired David MacIver&amp;#8217;s work on
&lt;a href="https://hypothesis.works/"&gt;Hypothesis&lt;/a&gt; and Richard Hughes&amp;#8217; work on
&lt;a href="https://fwupd.org/"&gt;firmware updates&lt;/a&gt; from afar.  And there are a bunch of
other excellent projects represented there:
&lt;a href="https://www.openstreetmap.org/"&gt;OpenStreetMap&lt;/a&gt;,
&lt;a href="https://www.textualize.io/"&gt;Textualize&lt;/a&gt;, and my alma mater of
&lt;a href="https://www.cam.ac.uk/"&gt;Cambridge&lt;/a&gt; to name but a&amp;nbsp;few.&lt;/p&gt;
&lt;p&gt;My friend Stuart Langridge
&lt;a href="https://www.kryogenix.org/days/2021/01/10/openuk-honours/"&gt;wrote&lt;/a&gt; about
being on a similar list a few years ago, and I can&amp;#8217;t do much better than to
echo it: in particular he wrote about the way the open source development
community is often at best unwelcoming to people who don&amp;#8217;t look like Stuart
and I do.  I can&amp;#8217;t tell a whole lot about demographic distribution just by
looking at a list of names, but while these honours still seem to be skewed
somewhat male, I&amp;#8217;m fairly sure they&amp;#8217;re doing a lot better in terms of gender
balance than my &amp;#8220;home&amp;#8221; project of Debian is, for one.  I hope this is a sign
of improvement for the future, and I&amp;#8217;ll do what I can to pay it&amp;nbsp;forward.&lt;/p&gt;</content><category term="misc"/><category term="columbiform"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Going freelance</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/going-freelance.html" rel="alternate"/><published>2024-01-10T09:50:23+00:00</published><updated>2024-01-10T09:50:23+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2024-01-10:/~cjwatson/blog/going-freelance.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve mentioned this in a
&lt;a href="https://mastodon.ie/@cjwatson/111348289616136892"&gt;couple&lt;/a&gt; of
&lt;a href="https://www.linkedin.com/posts/colin-watson-79535025b_columbiform-activity-7138117110676779008-ooSD"&gt;other&lt;/a&gt;
places, but I realized I never got round to posting about it on my own blog
rather than on other people&amp;#8217;s services.  How remiss of&amp;nbsp;me.&lt;/p&gt;
&lt;p&gt;Anyway: after much soul-searching, I decided a few months ago that it was
time …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve mentioned this in a
&lt;a href="https://mastodon.ie/@cjwatson/111348289616136892"&gt;couple&lt;/a&gt; of
&lt;a href="https://www.linkedin.com/posts/colin-watson-79535025b_columbiform-activity-7138117110676779008-ooSD"&gt;other&lt;/a&gt;
places, but I realized I never got round to posting about it on my own blog
rather than on other people&amp;#8217;s services.  How remiss of&amp;nbsp;me.&lt;/p&gt;
&lt;p&gt;Anyway: after much soul-searching, I decided a few months ago that it was
time for me to move on from &lt;a href="https://canonical.com/"&gt;Canonical&lt;/a&gt; and the
&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; team there.  Nearly 20 years is a long
time to spend at any company, and although there are a bunch of people I&amp;#8217;ll
miss, Launchpad is in a reasonable state where I can let other people have a&amp;nbsp;turn.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m now in business for myself as a freelance developer!  My new company is
&lt;a href="https://www.columbiform.co.uk/"&gt;Columbiform&lt;/a&gt;, and I&amp;#8217;m focusing on Debian
packaging and custom Python development.  My
&lt;a href="https://www.columbiform.co.uk/services.html"&gt;services&lt;/a&gt; page has some
self-promotion on the sorts of things I can&amp;nbsp;do.&lt;/p&gt;
&lt;p&gt;My first gig, and the one that made it viable to make this jump, is at
&lt;a href="https://www.freexian.com/"&gt;Freexian&lt;/a&gt; where I&amp;#8217;m helping with an exciting
infrastructure project that we hope will start making Debian developers&amp;#8217;
lives easier in the near future.  This is likely to take up most of my time
at least through to the end of 2024, but I may have some spare cycles.
&lt;a href="https://www.columbiform.co.uk/contact.html"&gt;Drop me a line&lt;/a&gt; if you have
something where you think I could be a good fit, and we can have a talk
about&amp;nbsp;it.&lt;/p&gt;</content><category term="columbiform"/><category term="columbiform"/><category term="debian"/><category term="freexian"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Reproducible man-db databases</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/reproducible-man-db-databases.html" rel="alternate"/><published>2022-10-16T16:54:32+01:00</published><updated>2022-10-16T16:54:32+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2022-10-16:/~cjwatson/blog/reproducible-man-db-databases.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve released man-db 2.11.0
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2022-10/msg00000.html"&gt;announcement&lt;/a&gt;,
&lt;a href="https://gitlab.com/cjwatson/man-db/-/blob/2.11.0/NEWS.md"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;), and
uploaded it to Debian&amp;nbsp;unstable.&lt;/p&gt;
&lt;p&gt;The biggest chunk of work here was fixing some extremely long-standing
issues with how the database is built.  Despite being in the package name,
man-db&amp;#8217;s database is much less important than it used to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve released man-db 2.11.0
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2022-10/msg00000.html"&gt;announcement&lt;/a&gt;,
&lt;a href="https://gitlab.com/cjwatson/man-db/-/blob/2.11.0/NEWS.md"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;), and
uploaded it to Debian&amp;nbsp;unstable.&lt;/p&gt;
&lt;p&gt;The biggest chunk of work here was fixing some extremely long-standing
issues with how the database is built.  Despite being in the package name,
man-db&amp;#8217;s database is much less important than it used to be: most uses of
&lt;code&gt;man(1)&lt;/code&gt; haven&amp;#8217;t required it in a long time, and both hardware and
&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-K.html"&gt;software&lt;/a&gt;
&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2022-02/msg00000.html"&gt;improvements&lt;/a&gt;
mean that even some searches can be done by brute force without needing
prior indexing.  However, the database is still needed for the &lt;code&gt;whatis(1)&lt;/code&gt;
and &lt;code&gt;apropos(1)&lt;/code&gt; commands.&lt;/p&gt;
&lt;p&gt;The database has a simple format - no relational structure here, it&amp;#8217;s just a
simple key-value database using old-fashioned &lt;span class="caps"&gt;DBM&lt;/span&gt;-like interfaces and
composing a few fields to form values - but there are a number of subtleties
involved.  The issues tend to amount to this: what does a manual page name
mean?  At first glance it might seem simple, because you have file names
that look something like &lt;code&gt;/usr/share/man/man1/ls.1.gz&lt;/code&gt; and that&amp;#8217;s obviously
&lt;code&gt;ls(1)&lt;/code&gt;.  Some pages are symlinks to other pages (which we track separately
because it makes it easier to figure out which entries to update when the
contents of the file system change), and sometimes multiple pages are even
hard links to the same&amp;nbsp;file.&lt;/p&gt;
&lt;p&gt;The real complications come with &amp;#8220;whatis references&amp;#8221;.  Pages can list a
bunch of names in their &lt;code&gt;NAME&lt;/code&gt; section, and the historical expectation is
that it should be possible to use those names as arguments to &lt;code&gt;man(1)&lt;/code&gt; even
if they don&amp;#8217;t also appear in the file system (although Debian policy has
&lt;a href="https://www.debian.org/doc/debian-policy/ch-docs.html#manual-pages"&gt;deprecated relying on
this&lt;/a&gt;
for some time).  Not only does that mean that &lt;code&gt;man(1)&lt;/code&gt; sometimes needs to
consult the database, but it also means that the database is inherently more
complicated, since a page might list something in its &lt;code&gt;NAME&lt;/code&gt; section that
conflicts with an actual file name in the file system, and now you need a
priority system to resolve ambiguities.  There are some other possible
causes of ambiguity as&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;The people working on &lt;a href="https://reproducible-builds.org/"&gt;reproducible
builds&lt;/a&gt; in Debian branched out to the
related challenge of reproducible installations some time ago: can you take
a collection of packages, bootstrap a file system image from them, and
reproduce that exact same image somewhere else?  This is useful for the same
sorts of reasons that reproducible builds are useful: it lets you verify
that an image is built from the components it&amp;#8217;s supposed to be built from,
and doesn&amp;#8217;t contain any other skulduggery by accident or design.  One of the
people working on this &lt;a href="https://bugs.debian.org/1010957"&gt;noticed&lt;/a&gt; that
man-db&amp;#8217;s database files were an obstacle to that: in particular, the exact
contents of the database seemed to depend on the order in which files were
scanned when building it.  The reporter proposed solving this by processing
files in sorted order, but I wasn&amp;#8217;t keen on that approach: firstly because
it would mean we could no longer process files in an order that makes it
more efficient to read them all from disk (still valuable on rotational
disks), but mostly because the differences seemed to point to other&amp;nbsp;bugs.&lt;/p&gt;
&lt;p&gt;Having understood this, there then followed several late nights of very
fiddly work on the details of how the database is maintained.  None of this
was conceptually difficult: it mainly amounted to ensuring that we maintain
a consistent &lt;a href="https://en.wikipedia.org/wiki/Well-order"&gt;well-order&lt;/a&gt; for
different entries that we might want to insert for a given database key, and
that we consider the same names for insertion regardless of the order in
which we encounter files.  As usual, the tricky bit is making sure that we
have the right data structures to support this.  man-db is written in C
which is not very well-supplied with built-in data structures, and
originally much of the code was written in a style that tried to minimize
memory allocations; this came at the cost of ownership and lifetime often
being rather unclear, and it was often difficult to make changes without
causing leaks or double-frees.  Over the years I&amp;#8217;ve been gradually
introducing better encapsulation to make things easier to follow, and I had
to do another round of that here.  There were also some problems with
caching being done at slightly the wrong layer: we need to make use of a
&amp;#8220;trace&amp;#8221; of the chain of links followed to resolve a page to its ultimate
source file, but we were incorrectly caching that trace and reusing it for
any link to the same file, with incorrect results in many&amp;nbsp;cases.&lt;/p&gt;
&lt;p&gt;Oh, and after doing all that I found that the on-disk representation of a
&lt;span class="caps"&gt;GDBM&lt;/span&gt; database is insertion-order-dependent, so I ended up having to manually
reorganize the database at the end by reading it all in and writing it all
back out in sorted order, which feels really weird to me coming from
spending most of my time with PostgreSQL these days.  Fortunately the
database is small so this takes negligible&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;None of this is particularly glamorous work, but it paid&amp;nbsp;off:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;# &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SOURCE_DATE_EPOCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%s&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="gp"&gt;# &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;emptydir&lt;span class="w"&gt; &lt;/span&gt;disorder
&lt;span class="gp"&gt;# &lt;/span&gt;disorderfs&lt;span class="w"&gt; &lt;/span&gt;--multi-user&lt;span class="o"&gt;=&lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;--shuffle-dirents&lt;span class="o"&gt;=&lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;--reverse-dirents&lt;span class="o"&gt;=&lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;emptydir&lt;span class="w"&gt; &lt;/span&gt;disorder
&lt;span class="gp"&gt;# &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TMPDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/disorder&amp;quot;&lt;/span&gt;
&lt;span class="gp"&gt;# &lt;/span&gt;mmdebstrap&lt;span class="w"&gt; &lt;/span&gt;--variant&lt;span class="o"&gt;=&lt;/span&gt;standard&lt;span class="w"&gt; &lt;/span&gt;--hook-dir&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/mmdebstrap/hooks/merged-usr&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;unstable&lt;span class="w"&gt; &lt;/span&gt;out1.tar
&lt;span class="gp"&gt;# &lt;/span&gt;mmdebstrap&lt;span class="w"&gt; &lt;/span&gt;--variant&lt;span class="o"&gt;=&lt;/span&gt;standard&lt;span class="w"&gt; &lt;/span&gt;--hook-dir&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/mmdebstrap/hooks/merged-usr&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;unstable&lt;span class="w"&gt; &lt;/span&gt;out2.tar
&lt;span class="gp"&gt;# &lt;/span&gt;cmp&lt;span class="w"&gt; &lt;/span&gt;out1.tar&lt;span class="w"&gt; &lt;/span&gt;out2.tar
&lt;span class="gp"&gt;# &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="go"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Launchpad now supports SSH Ed25519 keys and RSA SHA-2 signatures</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-new-ssh-features.html" rel="alternate"/><published>2022-02-18T13:49:59+00:00</published><updated>2022-02-18T13:49:59+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2022-02-18:/~cjwatson/blog/lp-new-ssh-features.html</id><summary type="html">&lt;p&gt;As of 2022-02-16, Launchpad supports a couple of features on its &lt;span class="caps"&gt;SSH&lt;/span&gt;
endpoints (&lt;code&gt;git.launchpad.net&lt;/code&gt;, &lt;code&gt;bazaar.launchpad.net&lt;/code&gt;, &lt;code&gt;ppa.launchpad.net&lt;/code&gt;,
and &lt;code&gt;upload.ubuntu.com&lt;/code&gt;) that it previously didn&amp;#8217;t: &lt;a href="https://bugs.launchpad.net/bugs/907675"&gt;Ed25519 public
keys&lt;/a&gt; (a well-regarded format,
supported by OpenSSH since 6.5 in 2014) and &lt;a href="https://bugs.launchpad.net/bugs/1933722"&gt;signatures with existing &lt;span class="caps"&gt;RSA …&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;As of 2022-02-16, Launchpad supports a couple of features on its &lt;span class="caps"&gt;SSH&lt;/span&gt;
endpoints (&lt;code&gt;git.launchpad.net&lt;/code&gt;, &lt;code&gt;bazaar.launchpad.net&lt;/code&gt;, &lt;code&gt;ppa.launchpad.net&lt;/code&gt;,
and &lt;code&gt;upload.ubuntu.com&lt;/code&gt;) that it previously didn&amp;#8217;t: &lt;a href="https://bugs.launchpad.net/bugs/907675"&gt;Ed25519 public
keys&lt;/a&gt; (a well-regarded format,
supported by OpenSSH since 6.5 in 2014) and &lt;a href="https://bugs.launchpad.net/bugs/1933722"&gt;signatures with existing &lt;span class="caps"&gt;RSA&lt;/span&gt;
public keys using &lt;span class="caps"&gt;SHA&lt;/span&gt;-2 rather than
&lt;span class="caps"&gt;SHA&lt;/span&gt;-1&lt;/a&gt; (supported by OpenSSH since
7.2 in&amp;nbsp;2016).&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m hesitant to call these features &amp;#8220;new&amp;#8221;, since they&amp;#8217;ve been around for a
long time elsewhere, and people might quite reasonably ask why it&amp;#8217;s taken us
so long.  The problem has always been that Launchpad can&amp;#8217;t really use a
normal &lt;span class="caps"&gt;SSH&lt;/span&gt; server such as OpenSSH because it needs features that aren&amp;#8217;t
practical to implement that way, such as virtual filesystems and dynamic
user key authorization against the Launchpad database.  Instead, we use
&lt;a href="https://twistedmatrix.com/trac/wiki/TwistedConch"&gt;Twisted Conch&lt;/a&gt;, which is
a very extensible Python &lt;span class="caps"&gt;SSH&lt;/span&gt; implementation that has generally served us
well.  The downside is that, because it&amp;#8217;s an independent implementation and
one that occupies a relatively small niche, it often lags behind in terms of
newer protocol&amp;nbsp;features.&lt;/p&gt;
&lt;p&gt;Catching up to this point has been something we&amp;#8217;ve been working on for
around five years, although it&amp;#8217;s taken a painfully long time for a variety
of reasons which I thought some people might find interesting to go into, at
least people who have the patience for details of the &lt;span class="caps"&gt;SSH&lt;/span&gt; protocol.  Many of
the delays were my own responsibility, although realistically we probably
couldn&amp;#8217;t have added Ed25519 support before OpenSSL/&lt;code&gt;cryptography&lt;/code&gt; work that
landed in&amp;nbsp;2019.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In 2015, we did some similar work on &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ssh-sha-2-support-in-twisted.html"&gt;&lt;span class="caps"&gt;SHA&lt;/span&gt;-2 key exchange and &lt;span class="caps"&gt;MAC&lt;/span&gt;
   algorithms&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In 2016, various other contributors were working on &lt;span class="caps"&gt;ECDSA&lt;/span&gt; and Ed25519
   support (e.g. &lt;a href="https://github.com/twisted/twisted/pull/533"&gt;#533&lt;/a&gt; and
   &lt;a href="https://github.com/twisted/twisted/pull/644"&gt;#644&lt;/a&gt;).  At the time, it
   seemed best to keep an eye on this but mainly leave them to it.  I&amp;#8217;m very
   glad that some people worked on this before me - studying their PRs
   helped a lot, even parts that didn&amp;#8217;t end up being merged&amp;nbsp;directly.&lt;/li&gt;
&lt;li&gt;In 2017, it became clear that this was likely to need some more
   attention, but before we could do anything else we had to revamp
   Launchpad&amp;#8217;s build system to use &lt;a href="https://pip.pypa.io/en/stable/"&gt;pip&lt;/a&gt;
   rather than &lt;a href="https://www.buildout.org/en/latest/"&gt;buildout&lt;/a&gt;, since
   without that we couldn&amp;#8217;t upgrade to any newer versions of Twisted.  That
   proved to be a substantial piece of yak-shaving: first we had to upgrade
   Launchpad off Ubuntu 12.04, and then the actual &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/virtualenv-pip/+merge/331388"&gt;build system
   rewrite&lt;/a&gt;
   was a complicated project of its&amp;nbsp;own.&lt;/li&gt;
&lt;li&gt;In 2018, I fixed an &lt;a href="https://bugs.launchpad.net/bugs/830679"&gt;authentication
   hang&lt;/a&gt; that happened if a client
   even tried to offer &lt;span class="caps"&gt;ECDSA&lt;/span&gt; or Ed25519 public keys to Launchpad, and we got
   &lt;span class="caps"&gt;ECDSA&lt;/span&gt; support fully working in Launchpad.  We also discovered as a result
   of automated interoperability tests run as part of the Debian OpenSSH
   packaging that Twisted needed to gain support for the new
   &lt;code&gt;openssh-key-v1&lt;/code&gt; private key format, which became a prerequisite for
   Ed25519 support since OpenSSH only ever writes those keys in the new
   format, and so I &lt;a href="https://github.com/twisted/twisted/pull/1193"&gt;fixed
   that&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In 2019, Python&amp;#8217;s &lt;a href="https://pypi.org/project/cryptography/"&gt;cryptography&lt;/a&gt;
   package gained support for X25519 (the Diffie-Hellman key exchange
   function based on &lt;a href="https://en.wikipedia.org/wiki/Curve25519"&gt;Curve25519&lt;/a&gt;)
   and Ed25519, and it became somewhat practical to add support to Twisted
   on top of that.  However, it required OpenSSL 1.1.1b, and it seemed
   unlikely that we would be in a position to upgrade all the relevant bits
   of Launchpad&amp;#8217;s infrastructure to use that in the near term.  I at least
   managed to add &lt;a href="https://github.com/twisted/twisted/pull/1202"&gt;curve25519-sha256 key exchange
   support&lt;/a&gt; to Twisted based
   on some &lt;a href="https://github.com/twisted/twisted/pull/644"&gt;previous work&lt;/a&gt; by
   another contributor, and I prepared &lt;a href="https://github.com/twisted/twisted/pull/1210"&gt;support for Ed25519
   keys&lt;/a&gt; in Twisted even
   though I knew we weren&amp;#8217;t going to be able to use it&amp;nbsp;yet.&lt;/li&gt;
&lt;li&gt;2020 was &amp;#8230; well, everyone knows what 2020 was like, plus we had a new
   baby.  I did some experimentation in spare moments, but I didn&amp;#8217;t really
   have the focus to be able to move this sort of complex problem&amp;nbsp;forward.&lt;/li&gt;
&lt;li&gt;In 2021, I bit the bullet and started seriously working on &lt;a href="https://github.com/twisted/twisted/pull/1607"&gt;fallback
   mechanisms to allow us to use
   Ed25519&lt;/a&gt; even on systems
   lacking a sufficient version of OpenSSL, though found myself blocked on
   figuring out type-checking issues following a code review.  It then
   became clear on the release of &lt;a href="https://www.openssh.com/releasenotes.html#8.8p1"&gt;OpenSSH
   8.8&lt;/a&gt; that we were going
   to have to deal with &lt;span class="caps"&gt;RSA&lt;/span&gt; &lt;span class="caps"&gt;SHA&lt;/span&gt;-2 signatures as well, since otherwise
   OpenSSH in Ubuntu soon wouldn&amp;#8217;t be able to authenticate to Launchpad by
   default (which also caused me to delay &lt;a href="https://bugs.debian.org/996391"&gt;uploading 8.8 to Debian
   unstable&lt;/a&gt; for a while).  To deal with
   that, I first had to add &lt;a href="https://github.com/twisted/twisted/pull/1666"&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; extension
   negotiation&lt;/a&gt; to&amp;nbsp;Twisted.&lt;/li&gt;
&lt;li&gt;Finally, in 2022, I added &lt;a href="https://github.com/twisted/twisted/pull/1692"&gt;&lt;span class="caps"&gt;RSA&lt;/span&gt; &lt;span class="caps"&gt;SHA&lt;/span&gt;-2 signature
   support&lt;/a&gt; to Twisted,
   finally unblocked myself on the type-checking issue with the Ed25519
   fallback mechanism, quickly put together a &lt;a href="https://git.launchpad.net/~launchpad/twisted/+git/twisted/commit/?id=536a8934be619044fc95f51822139b96edea9dcc"&gt;similar fallback mechanism
   for
   X25519&lt;/a&gt;,
   backported the whole mess to Twisted 20.3.0 since we currently can&amp;#8217;t use
   anything newer due to the somewhat old version of Python 3 that we&amp;#8217;re
   running, promptly ran into and fixed a
   &lt;a href="https://github.com/twisted/twisted/pull/1696"&gt;regression&lt;/a&gt; that affected
   &lt;span class="caps"&gt;SFTP&lt;/span&gt; uploads to &lt;code&gt;ppa.launchpad.net&lt;/code&gt; and &lt;code&gt;upload.ubuntu.com&lt;/code&gt;, and finally
   added Ed25519 as a permissible key type in Launchpad&amp;#8217;s&amp;nbsp;authserver.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Phew!  Thanks to everyone who works on Twisted, &lt;code&gt;cryptography&lt;/code&gt;, and OpenSSL
- it&amp;#8217;s been really useful to be able to build on solid lower-level
cryptographic primitives - and to those who helped with code&amp;nbsp;review.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/><category term="twisted"/></entry><entry><title>Launchpad now runs on Python 3!</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3.html" rel="alternate"/><published>2021-08-02T11:34:29+01:00</published><updated>2021-08-02T11:34:29+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2021-08-02:/~cjwatson/blog/lp-python3.html</id><summary type="html">&lt;p&gt;After a &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3-progress.html"&gt;very long porting journey&lt;/a&gt;,
&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; is finally running on Python 3 across
all of our&amp;nbsp;systems.&lt;/p&gt;
&lt;p&gt;I wanted to take a bit of time to reflect on why my emotional responses to
this port differ so much from those of some others who&amp;#8217;ve done large ports,
such …&lt;/p&gt;</summary><content type="html">&lt;p&gt;After a &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3-progress.html"&gt;very long porting journey&lt;/a&gt;,
&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; is finally running on Python 3 across
all of our&amp;nbsp;systems.&lt;/p&gt;
&lt;p&gt;I wanted to take a bit of time to reflect on why my emotional responses to
this port differ so much from those of some others who&amp;#8217;ve done large ports,
such as the &lt;a href="https://gregoryszorc.com/blog/2020/01/13/mercurial%27s-journey-to-and-reflections-on-python-3/"&gt;Mercurial
maintainers&lt;/a&gt;.
It&amp;#8217;s hard to deny that we&amp;#8217;ve had to burn a lot of time on this, which I&amp;#8217;m
sure has had an opportunity cost, and from one point of view it&amp;#8217;s
essentially running to stand still: there is no single compelling feature
that we get solely by porting to Python 3, although it&amp;#8217;s clearly a
prerequisite for tidying up old compatibility code and being able to use
modern language facilities in the future.  And yet, on the whole, I found
this a rewarding project and enjoyed doing&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Some of this may be because by inclination I&amp;#8217;m a maintenance programmer and
actually enjoy this sort of thing.  My default view tends to be that
software version upgrades may be a pain but it&amp;#8217;s much better to get that
pain over with as soon as you can rather than trying to hold back the tide;
you can certainly get involved and try to shape where things end up, but
rightly or wrongly I can&amp;#8217;t think of many cases when a righteously indignant
user base managed to arrange for the old version to be maintained in
perpetuity so that they never had to deal with the new thing (&lt;span class="caps"&gt;OK&lt;/span&gt;, maybe Perl
5 counts&amp;nbsp;here).&lt;/p&gt;
&lt;p&gt;I think a more compelling difference between Launchpad and Mercurial,
though, may be that very few other people really had a vested interest in
what Python version Launchpad happened to be running, because it&amp;#8217;s all
server-side code (aside from some client libraries such as
&lt;a href="https://pypi.org/project/launchpadlib"&gt;&lt;code&gt;launchpadlib&lt;/code&gt;&lt;/a&gt;, which were ported
years ago).  As such, we weren&amp;#8217;t trying to do this with the internet having
Strong Opinions at us.  We were doing this because it was obviously the only
long-term-maintainable path forward, and in more recent times because some
of our library dependencies were starting to drop support for Python 2 and
so it was obviously going to become a practical problem for us sooner or
later; but if we&amp;#8217;d just stayed on Python 2 forever then fundamentally hardly
anyone else would really have cared directly, only maybe about some indirect
consequences of that.  I don&amp;#8217;t follow Mercurial development so I may be
entirely off-base, but if other people were yelling at me about how late my
project was to finish its port, that &lt;em&gt;in itself&lt;/em&gt; would make me feel more
negatively about the project even if I thought it was a good idea.  Having
most of the pressure come from ourselves rather than from outside meant that
wasn&amp;#8217;t an issue for&amp;nbsp;us.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m somewhat inclined to think of the process as an extreme version of
paying down technical debt.  Moving from Python 2.7 to 3.5, as we just did,
means skipping over multiple language versions in one go, and if similar
changes had been made more gradually it would probably have felt a lot more
like the typical dependency update treadmill.  I appreciate why not everyone
might want to think of it this way: maybe this is just my own&amp;nbsp;rationalization.&lt;/p&gt;
&lt;h2&gt;Reflections on porting to Python&amp;nbsp;3&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m not going to defend the Python 3 migration process; it was pretty rough
in a lot of ways.  Nor am I going to spend much effort relitigating it here,
as it&amp;#8217;s already been done to death elsewhere, and as I understand it the
core Python developers have got the message loud and clear by now.  At a
bare minimum, a lot of valuable time was lost early in Python 3&amp;#8217;s lifetime
hanging on to flag-day-type porting strategies that were impractical for
large projects, when it should have been providing for &amp;#8220;bilingual&amp;#8221;
strategies (code that runs in both Python 2 and 3 for a transitional period)
which is where most libraries and most large migrations ended up in
practice.  For instance, the early advice to library maintainers to maintain
two parallel versions or perhaps translate dynamically with &lt;code&gt;2to3&lt;/code&gt; was
entirely impractical in most non-trivial cases and wasn&amp;#8217;t what most people
ended up doing, and yet the idea that &lt;code&gt;2to3&lt;/code&gt; is all you need still floats
around Stack Overflow and the like as a result.  (These days, I would
probably point people towards something more like &lt;a href="https://eev.ee/blog/2016/07/31/python-faq-how-do-i-port-to-python-3/"&gt;Eevee&amp;#8217;s porting
&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/a&gt;
as somewhere to&amp;nbsp;start.)&lt;/p&gt;
&lt;p&gt;There are various fairly straightforward things that people often suggest
could have been done to smooth the path, and I largely agree: not removing
the &lt;code&gt;u''&lt;/code&gt; string prefix only to put it back in 3.3, fewer gratuitous
compatibility breaks in the name of tidiness, and so on.  But if I had a
time machine, the number one thing I would ask to have been done differently
would be introducing type annotations in Python 2 before Python 3 branched
off.  It&amp;#8217;s true that it&amp;#8217;s &lt;a href="https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code"&gt;technically
possible&lt;/a&gt;
to do type annotations in Python 2, but the fact that it&amp;#8217;s a different
syntax that would have to be fixed later is offputting, and in practice it
wasn&amp;#8217;t widely used in Python 2 code.  To make a significant difference to
the ease of porting, annotations would need to have been introduced early
enough that lots of Python 2 library code used them so that porting code
didn&amp;#8217;t have to be quite so much of an exercise of manually figuring out the
exact nature of string types from&amp;nbsp;context.&lt;/p&gt;
&lt;p&gt;Launchpad is a complex piece of software that interacts with multiple
domains: for example, it deals with a database, &lt;span class="caps"&gt;HTTP&lt;/span&gt;, web page rendering,
Debian-format archive publishing, and multiple revision control systems, and
there&amp;#8217;s often overlap between domains.  Each of these tends to imply
different kinds of string handling.  Web page rendering is normally done
mainly in Unicode, converting to bytes as late as possible; revision control
systems normally want to spend most of their time working with bytes,
although the exact details vary; &lt;span class="caps"&gt;HTTP&lt;/span&gt; is of course bytes on the wire, but
Python&amp;#8217;s &lt;span class="caps"&gt;WSGI&lt;/span&gt; interface has some &lt;a href="https://www.python.org/dev/peps/pep-3333/#a-note-on-string-types"&gt;string type
subtleties&lt;/a&gt;.
In practice I found myself thinking about at least four string-like &amp;#8220;types&amp;#8221;
(that is, things that in a language with a stricter type system I might well
want to define as distinct types and restrict conversion between them):
bytes, text, &amp;#8220;ordinary&amp;#8221; native strings (&lt;code&gt;str&lt;/code&gt; in either language, encoded to
&lt;span class="caps"&gt;UTF&lt;/span&gt;-8 in Python 2), and native strings with &lt;span class="caps"&gt;WSGI&lt;/span&gt;&amp;#8217;s encoding rules.  Some of
these are emergent properties of writing in the intersection of Python 2 and
3, which is effectively a specialized language of its own without coherent
official documentation whose users must intuit its behaviour by comparing
multiple sources of information, or by referring to unofficial porting
guides: not a very satisfactory situation.  Fortunately much of the
complexity collapses once it becomes possible to write solely in Python&amp;nbsp;3.&lt;/p&gt;
&lt;p&gt;Some of the difficulties we ran into are not ones that are typically thought
of as Python 2-to-3 porting issues, because they were changed later in
Python 3&amp;#8217;s development process.  For instance, the &lt;code&gt;email&lt;/code&gt; module was
substantially improved in around the 3.2/3.3 timeframe to handle Python 3&amp;#8217;s
bytes/text model more correctly, and since Launchpad sends quite a few
different kinds of email messages and has some quite picky tests for exactly
what it emits, this entailed a lot of work in our email sending code and in
our test suite to account for that.  (It took me a while to work out whether
we should be treating raw email messages as bytes or as text; bytes turned
out to work best.)  3.4 made some tweaks to the implementation of
quoted-printable encoding that broke a number of our tests in ways that took
some effort to fix, because the tests needed to work on both 2.7 and 3.5.
The list goes on.  I got quite proficient at digging through Python&amp;#8217;s git
history to figure out when and why some particular bit of behaviour had&amp;nbsp;changed.&lt;/p&gt;
&lt;p&gt;One of the thorniest problems was parsing &lt;span class="caps"&gt;HTTP&lt;/span&gt; form data.  We mainly rely on
&lt;a href="https://pypi.org/project/zope.publisher"&gt;&lt;code&gt;zope.publisher&lt;/code&gt;&lt;/a&gt; for this, which
in turn relied on
&lt;a href="https://docs.python.org/3/library/cgi.html"&gt;&lt;code&gt;cgi.FieldStorage&lt;/code&gt;&lt;/a&gt;; but
&lt;code&gt;cgi.FieldStorage&lt;/code&gt; is &lt;a href="https://bugs.python.org/issue27777"&gt;badly broken in some
situations&lt;/a&gt; on Python 3.  Even if that
bug were fixed in a more recent version of Python, we can&amp;#8217;t easily use
anything newer than 3.5 for the first stage of our port due to the version
of the base &lt;span class="caps"&gt;OS&lt;/span&gt; we&amp;#8217;re currently running, so it wouldn&amp;#8217;t help much.  In the
end I fixed some minor issues in the
&lt;a href="https://pypi.org/project/multipart"&gt;&lt;code&gt;multipart&lt;/code&gt;&lt;/a&gt; module (and was kindly
given co-maintenance of it) and &lt;a href="https://github.com/zopefoundation/zope.publisher/pull/55"&gt;converted &lt;code&gt;zope.publisher&lt;/code&gt; to use
it&lt;/a&gt;.  Although
this took a while to sort out, it seems to have gone very&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;A couple of other interesting late-arriving issues were around
&lt;a href="https://docs.python.org/3/library/pickle.html"&gt;&lt;code&gt;pickle&lt;/code&gt;&lt;/a&gt;.  For most things
we normally prefer safer formats such as &lt;span class="caps"&gt;JSON&lt;/span&gt;, but there are a few cases
where we use pickle, particularly for our session databases.  One of my
colleagues pointed out that I needed to remember to tell &lt;code&gt;pickle&lt;/code&gt; to &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398534"&gt;stick
to protocol
2&lt;/a&gt;,
so that we&amp;#8217;d be able to switch back and forward between Python 2 and 3 for a
while; quite right, and we later ran into a similar problem with
&lt;a href="https://docs.python.org/3/library/marshal.html"&gt;&lt;code&gt;marshal&lt;/code&gt;&lt;/a&gt; too.  A more
surprising problem was that &lt;code&gt;datetime.datetime&lt;/code&gt; objects pickled on Python 2
&lt;a href="https://bugs.python.org/issue22005"&gt;require special care&lt;/a&gt; when unpickling
on Python 3; rather than the approach that ended up being implemented and
&lt;a href="https://docs.python.org/3/library/pickle.html#pickle.Unpickler"&gt;documented&lt;/a&gt;
for Python 3.6, though, I preferred a &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/399133"&gt;custom
unpickler&lt;/a&gt;,
both so that things would work on Python 3.5 and so that I wouldn&amp;#8217;t have to
risk affecting the decoding of other pickled strings in the session&amp;nbsp;database.&lt;/p&gt;
&lt;h2&gt;General&amp;nbsp;lessons&lt;/h2&gt;
&lt;p&gt;Writing this over a year after Python 2&amp;#8217;s end-of-life date, and certainly
nowhere near the leading edge of Python 3 porting work, it&amp;#8217;s perhaps more
useful to look at this in terms of the lessons it has for other large
technical debt&amp;nbsp;projects.&lt;/p&gt;
&lt;p&gt;I mentioned in my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3-progress.html"&gt;previous article&lt;/a&gt; that
I used the approach of an enormous and frequently-rebased git branch as a
working area for the port, committing often and sometimes combining and
extracting commits for review once they seemed to be ready.  A port of this
scale would have been entirely intractable without a tool of similar power
to &lt;code&gt;git rebase&lt;/code&gt;, so I&amp;#8217;m very glad that we finished migrating to git in 2019.
I relied on this right up to the end of the port, and it also allowed for
quick assessments of how much more there was to land.  &lt;a href="https://git-scm.com/docs/git-worktree"&gt;git
worktree&lt;/a&gt; was also helpful, in that I
could easily maintain working trees built for each of Python 2 and 3 for&amp;nbsp;comparison.&lt;/p&gt;
&lt;p&gt;As is usual for most multi-developer projects, all changes to Launchpad need
to go through code review, although we sometimes make exceptions for very
simple and obvious changes that can be self-reviewed.  Since I knew from the
outset that this was going to generate a lot of changes for review, I
therefore structured my work from the outset to try to make it as easy as
possible for my colleagues to review it.  This generally involved keeping
most changes to a somewhat manageable size of 800 lines or less (although
this wasn&amp;#8217;t always possible), and arranging commits mainly according to the
kind of change they made rather than their location.  For example, when I
needed to fix issues with &lt;code&gt;/&lt;/code&gt; in Python 3 being true division rather than
floor division, I did so in &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/396326"&gt;one
commit&lt;/a&gt;
across the various places where it mattered and took care not to mix it with
other unrelated changes.  This is good practice for nearly any kind of
development, but it was especially important here since it allowed reviewers
to consider a clear explanation of what I was doing in the commit message
and then skim-read the rest of it much more&amp;nbsp;quickly.&lt;/p&gt;
&lt;p&gt;It was vital to keep the codebase in a working state at all times, and
deploy to production reasonably often: this way if something went wrong the
amount of code we had to debug to figure out what had happened was always
tractable.  (Although I can&amp;#8217;t seem to find it now to link to it, I saw an
account a while back of a company that had taken a flag-day approach instead
with a large codebase.  It seemed to work for them, but I&amp;#8217;m certain we
couldn&amp;#8217;t have made it work for&amp;nbsp;Launchpad.)&lt;/p&gt;
&lt;p&gt;I can&amp;#8217;t speak too highly of Launchpad&amp;#8217;s test suite, much of which originated
before my time.  Without a great deal of extensive coverage of all sorts of
interesting edge cases at both the unit and functional level, and a
corresponding culture of maintaining that test suite well when making new
changes, it would have been impossible to be anything like as confident of
the port as we&amp;nbsp;were.&lt;/p&gt;
&lt;p&gt;As part of the porting work, we split out a couple of substantial chunks of
the Launchpad codebase that could easily be decoupled from the core: its
&lt;a href="https://launchpad.net/lp-mailman"&gt;Mailman integration&lt;/a&gt; and its &lt;a href="https://launchpad.net/lp-codeimport"&gt;code import
worker&lt;/a&gt;.  Both of these had substantial
dependencies with complex requirements for porting to Python 3, and
arranging to be able to do these separately on their own schedule was
absolutely worth it.  Like disentangling balls of wool, any opportunity you
can take to make things less tightly-coupled is probably going to make it
easier to disentangle the rest.  (I can see a tractable way forward to
porting the code import worker, so we may well get that done soon.  Our
Mailman integration will need to be rewritten, though, since it currently
depends on the Python-2-only Mailman 2, and Mailman 3 has a different&amp;nbsp;architecture.)&lt;/p&gt;
&lt;h2&gt;Python&amp;nbsp;lessons&lt;/h2&gt;
&lt;p&gt;Our &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/storm-py3.html"&gt;database layer&lt;/a&gt; was already in pretty good
shape for a port, since at least the modern bits of its table modelling
interface were already strict about using Unicode for text columns.  If you
have any kind of pervasive low-level framework like this, then making it be
pedantic at you in advance of a Python 3 port will probably incur much less
swearing in the long run, as you won&amp;#8217;t be trying to deal with quite so many
bytes/text issues at the same time as everything&amp;nbsp;else.&lt;/p&gt;
&lt;p&gt;Early in our port, we established a standard set of
&lt;a href="https://docs.python.org/3/library/__future__.html"&gt;&lt;code&gt;__future__&lt;/code&gt;&lt;/a&gt; imports
and started incrementally converting files over to them, mainly because we
weren&amp;#8217;t yet sure what else to do and it seemed likely to be helpful.
&lt;code&gt;absolute_import&lt;/code&gt; was definitely reasonable (and not often a problem in our
code), and &lt;code&gt;print_function&lt;/code&gt; was annoying but necessary.  In hindsight I&amp;#8217;m
not sure about &lt;code&gt;unicode_literals&lt;/code&gt;, though.  For files that only deal with
bytes and text it was reasonable enough, but as I mentioned above there were
also a number of cases where we needed literals of the language&amp;#8217;s native
&lt;code&gt;str&lt;/code&gt; type, i.e. bytes in Python 2 and text in Python 3: this was
particularly noticeable in &lt;span class="caps"&gt;WSGI&lt;/span&gt; contexts, but also cropped up in &lt;a href="https://github.com/zopefoundation/zope.configuration/pull/19"&gt;some other
surprising
places&lt;/a&gt;.  We
generally either omitted &lt;code&gt;unicode_literals&lt;/code&gt; or used &lt;code&gt;six.ensure_str&lt;/code&gt; in such
cases, but it was definitely a bit awkward and maybe I should have listened
more to people telling me it might be a bad&amp;nbsp;idea.&lt;/p&gt;
&lt;p&gt;A lot of Launchpad&amp;#8217;s early tests used
&lt;a href="https://docs.python.org/3/library/doctest.html"&gt;doctest&lt;/a&gt;, mainly in the
&lt;a href="https://docs.python.org/3/library/doctest.html#simple-usage-checking-examples-in-a-text-file"&gt;style&lt;/a&gt;
where you have text files that interleave narrative commentary with
examples.  The development team later reached consensus that this was best
avoided in most cases, but by then there were far too many doctests to
conveniently rewrite in some other form.  Porting doctests to Python 3 is
really annoying.  You run into all the little changes in how objects are
represented as text (particularly &lt;code&gt;u'...'&lt;/code&gt; versus &lt;code&gt;'...'&lt;/code&gt;, but plenty of
other cases as well); you have next to no tools to do anything useful like
skipping individual bits of a doctest that don&amp;#8217;t apply; using &lt;code&gt;__future__&lt;/code&gt;
imports requires the rather obscure approach of adding the relevant names to
the doctest&amp;#8217;s globals in the relevant &lt;code&gt;DocFileSuite&lt;/code&gt; or &lt;code&gt;DocTestSuite&lt;/code&gt;;
dealing with many exception tracebacks requires something like
&lt;a href="https://github.com/zopefoundation/zope.testing/blob/master/src/zope/testing/renormalizing.py"&gt;&lt;code&gt;zope.testing.renormalizing&lt;/code&gt;&lt;/a&gt;;
and whatever code refactoring tools you&amp;#8217;re using probably don&amp;#8217;t work
properly.  Basically, don&amp;#8217;t have done that.  It did all turn out to be
tractable for us in the end, and I managed to avoid using much in the way of
fragile doctest extensions aside from the aforementioned
&lt;code&gt;zope.testing.renormalizing&lt;/code&gt;, but it was not an enjoyable&amp;nbsp;experience.&lt;/p&gt;
&lt;h2&gt;Regressions&lt;/h2&gt;
&lt;p&gt;I know of nine regressions that reached Launchpad&amp;#8217;s production systems as a
result of this porting work; of course there were various other regressions
caught by &lt;span class="caps"&gt;CI&lt;/span&gt; or in manual testing.  (Considering the size of this project, I
count it as a resounding success that there were only nine production
issues, and that for the most part we were able to fix them&amp;nbsp;quickly.)&lt;/p&gt;
&lt;h3&gt;Equality testing of removed database&amp;nbsp;objects&lt;/h3&gt;
&lt;p&gt;One of the things we had to do while porting to Python 3 was to
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398087"&gt;implement&lt;/a&gt;
the &lt;code&gt;__eq__&lt;/code&gt;, &lt;code&gt;__ne__&lt;/code&gt;, and &lt;code&gt;__hash__&lt;/code&gt; special methods for all our database
objects.  This was quite conceptually fiddly, because doing this requires
knowing each object&amp;#8217;s primary key, and that may not yet be available if
we&amp;#8217;ve created an object in Python but not yet flushed the actual &lt;code&gt;INSERT&lt;/code&gt;
statement to the database (most of our primary keys are auto-incrementing
sequences).  We thus had to take care to flush pending &lt;span class="caps"&gt;SQL&lt;/span&gt; statements in
such cases in order to ensure that we know the primary&amp;nbsp;keys.&lt;/p&gt;
&lt;p&gt;However, it&amp;#8217;s possible to have a problem at the other end of the object
lifecycle: that is, a Python object might still be reachable in memory even
though the underlying row has been &lt;code&gt;DELETE&lt;/code&gt;d from the database.  In most
cases we don&amp;#8217;t keep removed objects around for obvious reasons, but it can
happen in caching code, and buildd-manager
&lt;a href="https://bugs.launchpad.net/launchpad/+bug/1916522"&gt;crashed&lt;/a&gt; as a result (in
fact while it was still running on Python 2).  We had to &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398498"&gt;take extra
care&lt;/a&gt;
to avoid this&amp;nbsp;problem.&lt;/p&gt;
&lt;h3&gt;Debian imports crashed on non-&lt;span class="caps"&gt;UTF&lt;/span&gt;-8&amp;nbsp;filenames&lt;/h3&gt;
&lt;p&gt;Python 2 has some &lt;a href="https://bugs.launchpad.net/launchpad/+bug/1917449"&gt;unfortunate
behaviour&lt;/a&gt; around passing
bytes or Unicode strings (depending on the platform) to &lt;code&gt;shutil.rmtree&lt;/code&gt;, and
the combination of some &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398367"&gt;porting
work&lt;/a&gt;
and a particular source package in Debian that contained a non-&lt;span class="caps"&gt;UTF&lt;/span&gt;-8 file
name caused us to run into this.  The
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398971"&gt;fix&lt;/a&gt;
was to ensure that the argument passed to &lt;code&gt;shutil.rmtree&lt;/code&gt; is a &lt;code&gt;str&lt;/code&gt;
regardless of Python&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;d actually run into &lt;a href="https://code.launchpad.net/~cjwatson/turnip/+git/turnip/+merge/359051"&gt;something
similar&lt;/a&gt;
before: it&amp;#8217;s a subtle porting gotcha, since it&amp;#8217;s quite easy to end up
passing Unicode strings to &lt;code&gt;shutil.rmtree&lt;/code&gt; if you&amp;#8217;re in the process of
porting your code to Python 3, and you might easily not notice if the file
names in your tests are all encoded using &lt;span class="caps"&gt;UTF&lt;/span&gt;-8.&lt;/p&gt;
&lt;h3&gt;lazr.restful&amp;nbsp;ETags&lt;/h3&gt;
&lt;p&gt;We eventually got far enough along that we could switch one of our four
appserver machines (we have quite a number of other machines too, but the
appservers handle web and &lt;span class="caps"&gt;API&lt;/span&gt; requests) to Python 3 and see what happened.
By this point our extensive test suite had shaken out the vast majority of
the things that could go wrong, but there was always going to be room for
some interesting edge&amp;nbsp;cases.&lt;/p&gt;
&lt;p&gt;One of the Ubuntu kernel team reported that they were seeing an increase in
&lt;a href="https://httpstatusdogs.com/412-precondition-failed"&gt;412 Precondition
Failed&lt;/a&gt; errors in some
of their scripts that use our webservice &lt;span class="caps"&gt;API&lt;/span&gt;.  These can happen when you&amp;#8217;re
trying to modify an existing resource: the underlying protocol involves
sending an &lt;code&gt;If-Match&lt;/code&gt; header with the &lt;code&gt;ETag&lt;/code&gt; that the client thinks the
resource has, and if this doesn&amp;#8217;t match the &lt;code&gt;ETag&lt;/code&gt; that the server calculates
for the resource then the client has to refresh its copy of the resource and
try again.  We initially thought that this might be legitimate since it can
happen in normal operation if you collide with another client making changes
to the same resource, but it soon became clear that something stranger was
going on: we were getting inconsistent &lt;code&gt;ETag&lt;/code&gt;s for the same object even when
it was unchanged.  Since we&amp;#8217;d recently switched a quarter of our appservers
to Python 3, that was a natural&amp;nbsp;suspect.&lt;/p&gt;
&lt;p&gt;Our &lt;code&gt;lazr.restful&lt;/code&gt; package provides the framework for our webservice &lt;span class="caps"&gt;API&lt;/span&gt;,
and roughly speaking it generates &lt;code&gt;ETag&lt;/code&gt;s by serializing objects into some
kind of canonical form and hashing the result.  Unfortunately the
serialization was dependent on the Python version in a few ways, and in
particular it serialized lists of strings such as lists of bug tags
differently: Python 2 used &lt;code&gt;[u'foo', u'bar', u'baz']&lt;/code&gt; where Python 3 used
&lt;code&gt;['foo', 'bar', 'baz']&lt;/code&gt;.  In &lt;code&gt;lazr.restful&lt;/code&gt; 1.0.3 we &lt;a href="https://code.launchpad.net/~cjwatson/lazr.restful/etag-json/+merge/402920"&gt;switched to using
&lt;span class="caps"&gt;JSON&lt;/span&gt;&lt;/a&gt;
for this, removing the Python version dependency and ensuring consistent
behaviour between&amp;nbsp;appservers.&lt;/p&gt;
&lt;h3&gt;Memory&amp;nbsp;leaks&lt;/h3&gt;
&lt;p&gt;This problem took the longest to solve.  We noticed fairly quickly from our
graphs that the appserver machine we&amp;#8217;d switched to Python 3 had a serious
memory leak.  Our appservers had always been a bit leaky, but now it wasn&amp;#8217;t
so much &amp;#8220;a small hole that we can bail occasionally&amp;#8221; as &amp;#8220;the boat is sinking&amp;nbsp;rapidly&amp;#8221;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A serious memory leak" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/chaenomeles-leak.png"&gt;&lt;/p&gt;
&lt;p&gt;(Yes, this got in the way of working out what was going on with &lt;code&gt;ETag&lt;/code&gt;s for
a&amp;nbsp;while.)&lt;/p&gt;
&lt;p&gt;I spent ages messing around with various attempts to fix this.  Since only
a quarter of our appservers were affected, and we could get by on 75%
capacity for a while, it wasn&amp;#8217;t urgent but it was definitely annoying.
After spending some quality time with
&lt;a href="https://mg.pov.lt/objgraph/"&gt;objgraph&lt;/a&gt;, for
some time I thought &lt;a href="https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/"&gt;traceback reference
cycles&lt;/a&gt;
might be at fault, and I sent a number of fixes to various upstream projects
for those (e.g.
&lt;a href="https://github.com/zopefoundation/zope.pagetemplate/pull/27"&gt;zope.pagetemplate&lt;/a&gt;).
Those didn&amp;#8217;t help the leaks much though, and after a while it became clear
to me that this couldn&amp;#8217;t be the sole problem: Python has a cyclic garbage
collector that will eventually collect reference cycles as long as there are
no strong references to any objects in them, although it might not happen
very quickly.  Something else must be going&amp;nbsp;on.&lt;/p&gt;
&lt;p&gt;Debugging reference leaks in any non-trivial and long-running Python program
is extremely arduous, especially with ORMs that naturally tend to end up
with lots of cycles and caches.  After a while I formed a hypothesis that
&lt;a href="https://pypi.org/project/zope.server"&gt;zope.server&lt;/a&gt; might be keeping a
strong reference to something, although I never managed to nail it down more
firmly than that.  This was an attractive theory as we were already in the
process of migrating to &lt;a href="https://docs.gunicorn.org/en/stable/"&gt;Gunicorn&lt;/a&gt; for
other reasons anyway, and Gunicorn also has a convenient
&lt;a href="https://docs.gunicorn.org/en/stable/settings.html#max-requests"&gt;&lt;code&gt;max_requests&lt;/code&gt;&lt;/a&gt;
setting that&amp;#8217;s good at mitigating memory leaks.  Getting this all in place
took some time, but once we did we found that everything was much more&amp;nbsp;stable:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A rather flat memory graph" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/chaenomeles-stable.png"&gt;&lt;/p&gt;
&lt;p&gt;This isn&amp;#8217;t completely satisfying as we never quite got to the bottom of the
leak itself, and it&amp;#8217;s entirely possible that we&amp;#8217;ve only papered over it
using &lt;code&gt;max_requests&lt;/code&gt;: I expect we&amp;#8217;ll gradually back off on how frequently we
restart workers over time to try to track this down.  However,
pragmatically, it&amp;#8217;s no longer an operational&amp;nbsp;concern.&lt;/p&gt;
&lt;h3&gt;Mirror prober &lt;span class="caps"&gt;HTTPS&lt;/span&gt; proxy&amp;nbsp;handling&lt;/h3&gt;
&lt;p&gt;After we switched our script servers to Python 3, we had several reports of
&lt;a href="https://bugs.launchpad.net/launchpad/+bug/1935999"&gt;mirror probing
failures&lt;/a&gt;.  (Launchpad
keeps lists of Ubuntu archive and image mirrors, and probes them every so
often to check that they&amp;#8217;re reasonably complete and up to date.)  This only
affected &lt;span class="caps"&gt;HTTPS&lt;/span&gt; mirrors when probed via a proxy server, support for which is
a relatively recent feature in Launchpad and involved some code that we
never managed to unit-test properly: of course this is exactly the code that
went wrong.  Sadly I wasn&amp;#8217;t able to sort out that gap, but at least the
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/405688"&gt;fix&lt;/a&gt;
was&amp;nbsp;simple.&lt;/p&gt;
&lt;h3&gt;Non-&lt;span class="caps"&gt;MIME&lt;/span&gt;-encoded email&amp;nbsp;headers&lt;/h3&gt;
&lt;p&gt;As I mentioned above, there were substantial changes in the &lt;code&gt;email&lt;/code&gt; package
between Python 2 and 3, and indeed between minor versions of Python 3.  Our
test coverage here is pretty good, but it&amp;#8217;s an area where it&amp;#8217;s very easy to
have gaps.  We noticed that a script that processes incoming email was
crashing on messages with headers that were non-&lt;span class="caps"&gt;ASCII&lt;/span&gt; but not
&lt;a href="https://datatracker.ietf.org/doc/html/rfc2047.html"&gt;&lt;span class="caps"&gt;MIME&lt;/span&gt;-encoded&lt;/a&gt; (and
indeed then crashing again when it tried to send a notification of the
crash!).  The only examples of these I looked at were spam, but we still
didn&amp;#8217;t want to crash on&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;The
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/405924"&gt;fix&lt;/a&gt;
involved being somewhat more careful about both the handling of headers
returned by Python&amp;#8217;s email parser and the building of outgoing email
notifications.  This seems to be working well so far, although I wouldn&amp;#8217;t be
surprised to find the odd other incorrect detail in this sort of&amp;nbsp;area.&lt;/p&gt;
&lt;h3&gt;Failure to handle non-&lt;span class="caps"&gt;ISO&lt;/span&gt;-8859-1 &lt;span class="caps"&gt;URL&lt;/span&gt;-encoded form&amp;nbsp;input&lt;/h3&gt;
&lt;p&gt;Remember how I said that parsing &lt;span class="caps"&gt;HTTP&lt;/span&gt; form data was thorny?  After we
finished upgrading all our appservers to Python 3, people started reporting
that they &lt;a href="https://bugs.launchpad.net/launchpad/+bug/1937345"&gt;couldn&amp;#8217;t post Unicode comments to
bugs&lt;/a&gt;, which turned out
to be only if the attempt was made using JavaScript, and was because I
hadn&amp;#8217;t quite managed to get &lt;span class="caps"&gt;URL&lt;/span&gt;-encoded form data working properly with
&lt;code&gt;zope.publisher&lt;/code&gt; and &lt;code&gt;multipart&lt;/code&gt;.  The current standard describes the
&lt;span class="caps"&gt;URL&lt;/span&gt;-encoded format for form data as &lt;a href="https://url.spec.whatwg.org/#application/x-www-form-urlencoded"&gt;&amp;#8220;in many ways an aberrant
monstrosity&amp;#8221;&lt;/a&gt;,
so this was no great&amp;nbsp;surprise.&lt;/p&gt;
&lt;p&gt;Part of the problem was some &lt;a href="https://github.com/zopefoundation/zope.publisher/issues/65"&gt;very strange
choices&lt;/a&gt; in
&lt;code&gt;zope.publisher&lt;/code&gt; dating back to 2004 or earlier, which I attempted to &lt;a href="https://github.com/zopefoundation/zope.publisher/pull/66"&gt;clean
up and simplify&lt;/a&gt;.
The rest was that Python 2&amp;#8217;s &lt;code&gt;urlparse.parse_qs&lt;/code&gt; unconditionally decodes
percent-encoded sequences as &lt;span class="caps"&gt;ISO&lt;/span&gt;-8859-1 if they&amp;#8217;re passed in as part of a
Unicode string, so &lt;code&gt;multipart&lt;/code&gt; needs to &lt;a href="https://github.com/defnull/multipart/pull/36"&gt;work around
this&lt;/a&gt; on Python&amp;nbsp;2.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m still not completely confident that this is correct in all situations,
but at least now that we&amp;#8217;re on Python 3 everywhere the matrix of cases we
need to care about is&amp;nbsp;smaller.&lt;/p&gt;
&lt;h3&gt;Inconsistent marshalling of Loggerhead&amp;#8217;s disk&amp;nbsp;cache&lt;/h3&gt;
&lt;p&gt;We use &lt;a href="https://pypi.org/project/loggerhead"&gt;Loggerhead&lt;/a&gt; for providing web
browsing of Bazaar branches.  When we upgraded one of its two servers to
Python 3, we immediately noticed that the one still on Python 2 was failing
to read back its revision information cache, which it stores in a database
on disk.  (We noticed this because it caused a deployment to fail: when we
tried to roll out new code to the instance still on Python 2, Nagios checks
had already caused an incompatible cache to be written for one branch from
the Python 3&amp;nbsp;instance.)&lt;/p&gt;
&lt;p&gt;This turned out to be a similar problem to the &lt;code&gt;pickle&lt;/code&gt; issue mentioned
above, except this one was with &lt;code&gt;marshal&lt;/code&gt;, which I didn&amp;#8217;t think to look for
because it&amp;#8217;s a relatively obscure module mostly used for internal purposes
by Python itself; I&amp;#8217;m not sure that Loggerhead should really be using it in
the first place.  The fix was
&lt;a href="https://code.launchpad.net/~cjwatson/loggerhead/marshal-version/+merge/406291"&gt;relatively&lt;/a&gt;
&lt;a href="https://code.launchpad.net/~cjwatson/loggerhead/fix-marshal-version/+merge/406308"&gt;straightforward&lt;/a&gt;,
complicated mainly by now needing to cope with throwing away unreadable
cache&amp;nbsp;data.&lt;/p&gt;
&lt;p&gt;Ironically, if we&amp;#8217;d just gone ahead and taken the nominally riskier path of
upgrading both servers at the same time, we might never have had a problem&amp;nbsp;here.&lt;/p&gt;
&lt;h3&gt;Intermittent bzr&amp;nbsp;failures&lt;/h3&gt;
&lt;p&gt;Finally, after we upgraded one of our two Bazaar codehosting servers to
Python 3, we had a
&lt;a href="https://bugs.launchpad.net/launchpad/+bug/1938335"&gt;report&lt;/a&gt; of intermittent
&lt;code&gt;bzr branch&lt;/code&gt; hangs.  After some digging I found this in our&amp;nbsp;logs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c"&gt;...&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/bazaar.launchpad.net/production/codehosting1-rev-20124175fa98fcb4b43973265a1561174418f4bd/env/lib/python3.5/site-packages/twisted/conch/ssh/channel.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;136&lt;/span&gt;, in &lt;span class="n"&gt;addWindowBytes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startWriting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/bazaar.launchpad.net/production/codehosting1-rev-20124175fa98fcb4b43973265a1561174418f4bd/env/lib/python3.5/site-packages/lazr/sshserver/session.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;88&lt;/span&gt;, in &lt;span class="n"&gt;startWriting&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;resumeProducing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/bazaar.launchpad.net/production/codehosting1-rev-20124175fa98fcb4b43973265a1561174418f4bd/env/lib/python3.5/site-packages/twisted/internet/process.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;894&lt;/span&gt;, in &lt;span class="n"&gt;resumeProducing&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;itervalues&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="gr"&gt;builtins.AttributeError&lt;/span&gt;: &lt;span class="n"&gt;&amp;#39;dict&amp;#39; object has no attribute &amp;#39;itervalues&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I&amp;#8217;d seen this before in our git hosting service: it was a bug in Twisted&amp;#8217;s
Python 3 port, &lt;a href="https://github.com/twisted/twisted/pull/1478"&gt;fixed&lt;/a&gt; after
20.3.0 but unfortunately after the last release that supported Python 2, so
we had to backport that patch.  Using the same backport dealt with&amp;nbsp;this.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://eev.ee/blog/2016/07/31/python-faq-why-should-i-use-python-3/"&gt;Onwards!&lt;/a&gt;&lt;/h2&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>SSH quoting</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ssh-quoting.html" rel="alternate"/><published>2021-06-11T11:22:21+01:00</published><updated>2021-06-11T11:22:21+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2021-06-11:/~cjwatson/blog/ssh-quoting.html</id><summary type="html">&lt;p&gt;A while back there was a thread on one of our company mailing lists about
&lt;span class="caps"&gt;SSH&lt;/span&gt; quoting, and I posted a long answer to it.  Since then a few people have
asked me questions that caused me to reach for it, so I thought it might be
helpful if I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;A while back there was a thread on one of our company mailing lists about
&lt;span class="caps"&gt;SSH&lt;/span&gt; quoting, and I posted a long answer to it.  Since then a few people have
asked me questions that caused me to reach for it, so I thought it might be
helpful if I were to anonymize the original question and post my answer&amp;nbsp;here.&lt;/p&gt;
&lt;p&gt;The question was why a sequence of commands involving &lt;code&gt;ssh&lt;/code&gt; and fiddly
quoting produced the output they did.  The first example was&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;user@machine.local&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-lc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cd /tmp;pwd&amp;quot;&lt;/span&gt;
/home/user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Oh hi, my dubious life choices have been such that this is my specialist&amp;nbsp;subject!&lt;/p&gt;
&lt;p&gt;This is because &lt;span class="caps"&gt;SSH&lt;/span&gt; command-line parsing is not quite what you&amp;nbsp;expect.&lt;/p&gt;
&lt;p&gt;First, recall that your local shell will apply its usual parsing, and the
actual &lt;span class="caps"&gt;OS&lt;/span&gt;-level execution of &lt;code&gt;ssh&lt;/code&gt; will be like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="nv"&gt;@machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bash&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lc&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, the &lt;span class="caps"&gt;SSH&lt;/span&gt; wire protocol only takes a single string as the command, with
the expectation that it should be passed to a shell by the remote end.  The
OpenSSH client deals with this by taking all its arguments after things like
options and the target, which in this case&amp;nbsp;are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[0]: bash
[1]: -lc
[2]: cd /tmp;pwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It then joins them with a single&amp;nbsp;space:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;bash -lc cd /tmp;pwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is passed as a string to the server, which then passes that entire
string to a shell for evaluation, so as if you&amp;#8217;d typed this directly on the&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sh -c &amp;#39;bash -lc cd /tmp;pwd&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The shell then parses this as two&amp;nbsp;commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;bash -lc cd /tmp
pwd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The directory change thus happens in a subshell (actually it doesn&amp;#8217;t quite
even do that, because &lt;code&gt;bash -lc cd /tmp&lt;/code&gt; in fact ends up just calling &lt;code&gt;cd&lt;/code&gt;
because of the way &lt;code&gt;bash -c&lt;/code&gt; parses multiple arguments), and then that
subshell exits, then &lt;code&gt;pwd&lt;/code&gt; is called in the outer shell which still has the
original working&amp;nbsp;directory.&lt;/p&gt;
&lt;p&gt;The second example was&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;user@machine.local&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-lc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;pwd;cd /tmp;pwd&amp;quot;&lt;/span&gt;
/home/user
/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Following the logic above, this ends up as if you&amp;#8217;d run this on the&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sh -c &amp;#39;bash -lc pwd; cd /tmp; pwd&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The third example was&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;user@machine.local&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-lc&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cd /tmp;cd /tmp;pwd&amp;quot;&lt;/span&gt;
/tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And this is as if you&amp;#8217;d&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sh -c &amp;#39;bash -lc cd /tmp; cd /tmp; pwd&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, I wouldn&amp;#8217;t have implemented the &lt;span class="caps"&gt;SSH&lt;/span&gt; client this way, because I agree
that it&amp;#8217;s confusing.  But &lt;code&gt;/usr/bin/ssh&lt;/code&gt; is used as a transport for other
things so much that changing its behaviour now would be enormously
disruptive, so it&amp;#8217;s probably impossible to fix.  (I have occasionally
agitated on openssh-unix-dev@ for at least documenting this better, but
haven&amp;#8217;t made much headway yet; I need to get round to preparing a
documentation patch.)  Once you know about it you can use the proper
quoting, though.  In this case that would simply&amp;nbsp;be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="nv"&gt;@machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cd /tmp;pwd&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or if you do need to specifically invoke &lt;code&gt;bash -l&lt;/code&gt; there for some reason
(I&amp;#8217;m assuming that the original example was reduced from something more
complicated), then you can minimise your confusion by passing the whole
thing as a single string in the form you want the remote &lt;code&gt;sh -c&lt;/code&gt; to see, in
a way that ensures that the quotes are preserved and sent to the server
rather than being removed by your local&amp;nbsp;shell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="nv"&gt;@machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bash -lc &amp;quot;cd /tmp;pwd&amp;quot;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Shell parsing is&amp;nbsp;hard.&lt;/p&gt;</content><category term="debian"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Porting Launchpad to Python 3: progress report</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/lp-python3-progress.html" rel="alternate"/><published>2020-09-25T12:01:40+01:00</published><updated>2020-09-25T12:01:40+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2020-09-25:/~cjwatson/blog/lp-python3-progress.html</id><summary type="html">&lt;p&gt;&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; still requires Python 2, which in 2020
is &lt;a href="https://www.python.org/doc/sunset-python-2/"&gt;a bit of a problem&lt;/a&gt;.
Unlike a lot of the rest of 2020, though, there&amp;#8217;s good reason to be
optimistic about&amp;nbsp;progress.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been porting Python 2 code to Python 3 on and off for a long time, from …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; still requires Python 2, which in 2020
is &lt;a href="https://www.python.org/doc/sunset-python-2/"&gt;a bit of a problem&lt;/a&gt;.
Unlike a lot of the rest of 2020, though, there&amp;#8217;s good reason to be
optimistic about&amp;nbsp;progress.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been porting Python 2 code to Python 3 on and off for a long time, from
back when I was on the Ubuntu Foundations team and maintaining things like
the &lt;a href="https://launchpad.net/ubiquity"&gt;Ubiquity installer&lt;/a&gt;.  When I moved to
Launchpad in 2015 it was certainly on my mind that this was a large body of
code still stuck on Python 2.  One option would have been to just accept
that and leave it as it is, maybe doing more backporting work over time as
support for Python 2 fades away.  I&amp;#8217;ve long been of the opinion that this
would doom Launchpad to being unmaintainable in the long run, and since I
genuinely love working on Launchpad - I find it an incredibly rewarding
project - this wasn&amp;#8217;t something I was willing to accept.  We&amp;#8217;re already
seeing some of our important dependencies dropping support for Python 2,
which is perfectly reasonable on their terms but which is starting to become
a genuine obstacle to delivering important features when we need new
features from newer versions of those dependencies.  It also looks as though
it may be difficult for us to run on Ubuntu 20.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; (we&amp;#8217;re currently on
16.04, with an upgrade to 18.04 in progress) as long as we still require
Python 2, since we have some system dependencies that 20.04 no longer
provides.  And then there are exciting new features like &lt;a href="https://docs.python.org/3/library/typing.html"&gt;type
hints&lt;/a&gt; and
&lt;a href="https://docs.python.org/3/library/asyncio.html"&gt;async/await&lt;/a&gt; that we&amp;#8217;d like
to be able to&amp;nbsp;use.&lt;/p&gt;
&lt;p&gt;However, until last year there were so many blockers that even considering a
port was barely conceivable.  What changed in 2019 was sorting out a
trifecta of core dependencies.  We &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/storm-py3.html"&gt;ported&lt;/a&gt; our
database layer, &lt;a href="https://storm.canonical.com/"&gt;Storm&lt;/a&gt;.  We
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/376781"&gt;upgraded&lt;/a&gt;
to modern versions of our &lt;a href="https://www.zope.org/"&gt;Zope&lt;/a&gt; Toolkit dependencies
(after contributing various fixes upstream, including some substantial
changes to Zope&amp;#8217;s &lt;a href="https://pypi.org/project/zope.testrunner/"&gt;test runner&lt;/a&gt;
that we&amp;#8217;d carried as local patches for some years).  And we
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/373805"&gt;ported&lt;/a&gt;
our Bazaar code hosting infrastructure to
&lt;a href="https://www.breezy-vcs.org/"&gt;Breezy&lt;/a&gt;.  With all that in place, a port
seemed more of a realistic&amp;nbsp;possibility.&lt;/p&gt;
&lt;p&gt;Still, even with this, it was never going to be a matter of just following
some &lt;a href="http://python3porting.com/"&gt;standard porting advice&lt;/a&gt; and calling it
good.  Launchpad has almost a million lines of Python code in its &lt;a href="https://git.launchpad.net/launchpad"&gt;main git
tree&lt;/a&gt;, and around 250 dependencies of
which a number are quite Launchpad-specific.  In a project that size, not
only is following standard porting advice an extremely time-consuming task
in its own right, but just about every strange corner case is going to show
up somewhere.  (Did you know that &lt;code&gt;StringIO.StringIO(None)&lt;/code&gt; and
&lt;code&gt;io.StringIO(None)&lt;/code&gt; do different things even after you account for the
native string vs. Unicode text difference?  How about &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/385711"&gt;the behaviour of
&lt;code&gt;.union()&lt;/code&gt; on a subclass of
&lt;code&gt;frozenset&lt;/code&gt;&lt;/a&gt;?)
Launchpad&amp;#8217;s test suite is fortunately extremely thorough, but even just
starting up the test suite involves importing most of the data model code,
so before you can start taking advantage of it you have to make a large
fraction of the codebase be at least syntactically-correct Python 3 code and
use only modules that exist in Python 3 while still working in Python 2; in
a project this size that turns out to be a large effort on its own, and can
be quite
&lt;a href="https://blog.launchpad.net/general/login-regression-for-users-with-non-ascii-names"&gt;risky&lt;/a&gt;
in&amp;nbsp;places.&lt;/p&gt;
&lt;p&gt;Canonical&amp;#8217;s product engineering teams work on a six-month cycle, but it just
isn&amp;#8217;t possible to cram this sort of thing into six months unless you do
literally nothing else, and &amp;#8220;please can we put all feature development on
hold while we run to stand still&amp;#8221; is a pretty tough sell to even the most
understanding management.  Fortunately, we&amp;#8217;ve been able to grow the
&lt;a href="https://launchpad.net/~launchpad"&gt;Launchpad team&lt;/a&gt; in the last year or so,
and so it&amp;#8217;s been possible to put &amp;#8220;Python 3&amp;#8221; on our roadmap on the
understanding that we aren&amp;#8217;t going to get all the way there in one cycle,
while still being able to do other substantial feature development work as&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;So, with all that preamble, what have we done this cycle?  We&amp;#8217;ve taken a
two-pronged approach.  From one end, we identified 147 classes that needed
to be ported away from some compatibility code in our database layer that
was substantially less friendly to Python 3: we&amp;#8217;ve ported 38 of those, so
there&amp;#8217;s clearly a fair bit more to do, but we were able to distribute this
work out among the team quite effectively.  From the other end, it was clear
that it would be very inefficient to do general porting work when any
attempt to even run the test suite would run straight into the same crashes
in the same order, so I set myself a target of getting the test suite to
start up, and started hacking on an &lt;a href="https://git.launchpad.net/~cjwatson/launchpad?h=py3"&gt;enormous git
branch&lt;/a&gt; that I never
expected to try to land directly: instead, I felt free to commit just about
anything that looked reasonable and moved things forward even if it was very
rough, and every so often went back to tidy things up and cherry-pick
individual commits into a form that included some kind of explanation and
passed existing tests so that I could propose them for&amp;nbsp;review.&lt;/p&gt;
&lt;p&gt;This strategy has been dramatically more successful than anything I&amp;#8217;ve tried
before at this scale.  So far this cycle, considering only Launchpad&amp;#8217;s main
git tree, we&amp;#8217;ve landed 137 Python-3-relevant merge proposals for a total of
39552 lines of &lt;code&gt;git diff&lt;/code&gt; output, keeping our existing tests passing along
the way and deploying incrementally to production.  We have about 27000 more
lines of patch at varying degrees of quality to tidy up and merge.  Our main
development branch is only perhaps 10 or 20 more patches away from the test
suite being able to start up, at which point we&amp;#8217;ll be able to get a buildbot
running so that multiple developers can work on this much more easily and
see the effect of their work.  With the full unlanded patch stack, about 75%
of the test suite passes on Python 3!  This still leaves a long tail of
several thousand tests to figure out and fix, but it&amp;#8217;s a much more
incrementally-tractable kind of problem than where we&amp;nbsp;started.&lt;/p&gt;
&lt;p&gt;Finally: the funniest (to me) bug I&amp;#8217;ve encountered in this effort was the
one I encountered in the test runner and fixed in
&lt;a href="https://github.com/zopefoundation/zope.testrunner/pull/106"&gt;zopefoundation/zope.testrunner#106&lt;/a&gt;:
IDs of failing tests were written to a pipe, so if you have a test suite
that&amp;#8217;s large enough and broken enough then eventually that pipe would reach
its capacity and your test runner would just give up and hang.  Pretty
annoying when it meant an overnight test run didn&amp;#8217;t give useful results, but
also eloquent commentary of&amp;nbsp;sorts.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Porting Storm to Python 3</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/storm-py3.html" rel="alternate"/><published>2019-09-22T08:56:42+01:00</published><updated>2019-09-22T08:56:42+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2019-09-22:/~cjwatson/blog/storm-py3.html</id><summary type="html">&lt;p&gt;We released &lt;a href="https://storm.canonical.com/"&gt;Storm&lt;/a&gt; 0.21 on Friday (the
release announcement seems to be stuck in moderation, but you can look at
the &lt;a href="https://bazaar.launchpad.net/+branch/storm/view/head:/NEWS"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt; file
directly).  For me, the biggest part of this release was adding Python 3&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;Storm is a really nice and lightweight &lt;span class="caps"&gt;ORM&lt;/span&gt; (object-relational mapper) for
Python …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We released &lt;a href="https://storm.canonical.com/"&gt;Storm&lt;/a&gt; 0.21 on Friday (the
release announcement seems to be stuck in moderation, but you can look at
the &lt;a href="https://bazaar.launchpad.net/+branch/storm/view/head:/NEWS"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt; file
directly).  For me, the biggest part of this release was adding Python 3&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;Storm is a really nice and lightweight &lt;span class="caps"&gt;ORM&lt;/span&gt; (object-relational mapper) for
Python, developed by Canonical.  We use it for some major products
(&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; and
&lt;a href="https://landscape.canonical.com/"&gt;Landscape&lt;/a&gt; are the ones I know of), and
it&amp;#8217;s also free software and used by some other folks as well.  Other popular
ORMs for Python include &lt;a href="http://sqlobject.org/"&gt;SQLObject&lt;/a&gt;,
&lt;a href="https://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; and the
&lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; &lt;span class="caps"&gt;ORM&lt;/span&gt;; we use those in various places
too depending on the context, but personally I&amp;#8217;ve always preferred Storm for
the readability of code that uses it and for how easy it is to debug and
extend&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been a problem for a while that Storm only worked with Python 2.  It&amp;#8217;s
one of a handful of major blockers to getting Launchpad running on Python 3,
which we definitely want to do; &lt;a href="https://github.com/stoq/stoq"&gt;stoq&lt;/a&gt; ended
up with a local fork of Storm to cope with this; and it was recently
&lt;a href="https://bugs.debian.org/933983"&gt;removed from Debian&lt;/a&gt; for this and other
reasons.  None of that was great.  So, with significant assistance from a
large patch contributed by Thiago Bellini, and with patient code review from
Simon Poirier and some of my other colleagues, we finally managed to get
that sorted out in this&amp;nbsp;release.&lt;/p&gt;
&lt;p&gt;In many ways, Storm was in fairly good shape already for a project that
hadn&amp;#8217;t yet been ported to Python 3: while its internal idea of which strings
were bytes and which text required quite a bit of untangling in the way that
Python 2 code usually does, its normal class used for text database columns
was already &lt;code&gt;Unicode&lt;/code&gt; which only accepted text input (&lt;code&gt;unicode&lt;/code&gt; in Python
2), so it could have been a lot worse; this also means that applications
that use Storm tend to get at least this part right even in Python 2.  Aside
from the bytes/text thing, many of the required changes were just the usual
largely-mechanical ones that anyone who&amp;#8217;s done 2-to-3 porting will be
familiar with.  But there were some areas that required non-trivial thought,
and I&amp;#8217;d like to talk about some of those&amp;nbsp;here.&lt;/p&gt;
&lt;h2&gt;Exception&amp;nbsp;types&lt;/h2&gt;
&lt;p&gt;Concrete database implementations such as
&lt;a href="http://initd.org/psycopg/"&gt;psycopg2&lt;/a&gt; raise implementation-specific
exception types.  The inheritance hierarchy for these is defined by the
&lt;a href="https://www.python.org/dev/peps/pep-0249/"&gt;Python Database &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; (&lt;span class="caps"&gt;DB&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt;),
but the actual exception classes aren&amp;#8217;t in a common place; rather, you might
get an instance of &lt;code&gt;psycopg2.errors.IntegrityError&lt;/code&gt; when using PostgreSQL
but an instance of &lt;code&gt;sqlite3.IntegrityError&lt;/code&gt; when using SQLite.  To make
things easier for applications that don&amp;#8217;t have a strict requirement for a
particular database backend, Storm arranged to inject its own virtual
exception types as additional base classes of these concrete exceptions by
patching their &lt;code&gt;__bases__&lt;/code&gt; attribute, so for example, you could import
&lt;code&gt;IntegrityError&lt;/code&gt; from &lt;code&gt;storm.exceptions&lt;/code&gt; and catch that rather than having
to catch each backend-specific&amp;nbsp;possibility.&lt;/p&gt;
&lt;p&gt;Although this was always a bit of a cheat, it worked well in practice for a
while, but the first sign of trouble even before porting to Python 3 was
with psycopg2 2.5.  This release started implementing its &lt;span class="caps"&gt;DB&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; exception
types in a C extension, which meant that it was no longer possible to patch
&lt;code&gt;__bases__&lt;/code&gt;.  To get around that, a few years ago I landed a
&lt;a href="https://code.launchpad.net/~cjwatson/storm/psycopg-2.5/+merge/278330"&gt;patch&lt;/a&gt;
to Storm to use &lt;code&gt;abc.ABCMeta.register&lt;/code&gt; instead to register the &lt;span class="caps"&gt;DB&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt;
exceptions as virtual subclasses of Storm&amp;#8217;s exceptions, which solved the
problem for Python 2.  However, even at the time I landed that, I knew that
it would be a porting obstacle due to &lt;a href="https://bugs.python.org/issue12029"&gt;Python issue
12029&lt;/a&gt;; Django ran into that as&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;In the end, I opted to
&lt;a href="https://code.launchpad.net/~cjwatson/storm/refactor-exception-wrapping/+merge/369319"&gt;refactor&lt;/a&gt;
how Storm handles exceptions: it now wraps cursor and connection objects in
such a way as to catch &lt;span class="caps"&gt;DB&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt; exceptions raised by their methods and
properties and re-raise them using wrapper exception types that inherit from
both the appropriate subclass of &lt;code&gt;StormError&lt;/code&gt; and the original &lt;span class="caps"&gt;DB&lt;/span&gt;-&lt;span class="caps"&gt;API&lt;/span&gt;
exception type, and with some care I even managed to avoid this being
painfully repetitive.  Out-of-tree database backends will need to make some
minor adjustments (removing &lt;code&gt;install_exceptions&lt;/code&gt;, adding an
&lt;code&gt;_exception_module&lt;/code&gt; property to their &lt;code&gt;Database&lt;/code&gt; subclass, adjusting the
&lt;code&gt;raw_connect&lt;/code&gt; method of their &lt;code&gt;Database&lt;/code&gt; subclass to do exception wrapping,
and possibly implementing &lt;code&gt;_make_combined_exception_type&lt;/code&gt; and/or
&lt;code&gt;_wrap_exception&lt;/code&gt; if they need to add extra attributes to the wrapper
exceptions).  Applications that follow the usual Storm idiom of catching
&lt;code&gt;StormError&lt;/code&gt; or any of its subclasses should continue to work without
needing any&amp;nbsp;changes.&lt;/p&gt;
&lt;h2&gt;SQLObject&amp;nbsp;compatibility&lt;/h2&gt;
&lt;p&gt;Storm includes some &lt;span class="caps"&gt;API&lt;/span&gt; compatibility with SQLObject; this was from before
my time, but I believe it was mainly because Launchpad and possibly
Landscape previously used SQLObject and this made the port to Storm very
much easier.  It still works fine for the parts of Launchpad that haven&amp;#8217;t
been ported to Storm, but I wouldn&amp;#8217;t be surprised if there were newer
features of SQLObject that it doesn&amp;#8217;t&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;The main question here was what to do with &lt;code&gt;StringCol&lt;/code&gt; and its associated
&lt;code&gt;AutoUnicodeVariable&lt;/code&gt;.  I opted to make these explicitly only accept text on
Python 3, since the main reason for them to accept bytes was to allow using
them with Python 2 native strings (i.e. &lt;code&gt;str&lt;/code&gt;), and on Python 3 &lt;code&gt;str&lt;/code&gt; is
already text so there&amp;#8217;s much less need for the porting affordance in that&amp;nbsp;case.&lt;/p&gt;
&lt;p&gt;Since releasing 0.21 I realised that the &lt;code&gt;StringCol&lt;/code&gt; implementation in
SQLObject itself in fact accepts both bytes and text even on Python 3, so
it&amp;#8217;s possible that we&amp;#8217;ll need to change this in the future, although we
haven&amp;#8217;t yet found any real code using Storm&amp;#8217;s SQLObject compatibility layer
that might rely on this.  Still, it&amp;#8217;s much easier for Storm to start out on
the stricter side and perhaps become more lenient than it is to go the other
way&amp;nbsp;round.&lt;/p&gt;
&lt;h2&gt;inspect.getargspec&lt;/h2&gt;
&lt;p&gt;Storm had some fairly complicated use of &lt;code&gt;inspect.getargspec&lt;/code&gt; on Python 2 as
part of its test mocking arrangements.  This didn&amp;#8217;t work in Python 3 due to
some subtleties relating to bound methods.  I
&lt;a href="https://code.launchpad.net/~cjwatson/storm/py3-mocker-inspect/+merge/371174"&gt;switched&lt;/a&gt;
to the modern &lt;code&gt;inspect.signature&lt;/code&gt; &lt;span class="caps"&gt;API&lt;/span&gt; in Python 3 to fix this, which in any
case is rather simpler with the exception of a wrinkle in how method
descriptors&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;(It&amp;#8217;s possible that these mocking arrangements could be simplified nowadays
by using some more off-the-shelf mocking library; I haven&amp;#8217;t looked into that
in any&amp;nbsp;detail.)&lt;/p&gt;
&lt;h2&gt;What&amp;#8217;s&amp;nbsp;next?&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m &lt;a href="https://bugs.debian.org/940876"&gt;working on getting Storm back into
Debian&lt;/a&gt; now, which will be with Python 3
support only since Debian is in the process of gradually removing Python 2
module support.  Other than that I don&amp;#8217;t really have any particular plans
for Storm at the moment (although of course I&amp;#8217;m not the only person with an
interest in it), aside from ideally avoiding leaving six years between
releases again.  I expect we can go back into bug-fixing mode there for a&amp;nbsp;while.&lt;/p&gt;
&lt;p&gt;From the Launchpad side, I&amp;#8217;ve recently made progress on one of the other
major Python 3 blockers (porting Bazaar code hosting to
&lt;a href="https://www.breezy-vcs.org/"&gt;Breezy&lt;/a&gt;, coming soon).  There are still some
other significant blockers, the largest being migrating to Mailman 3,
subvertpy fixes so that we can port code importing to Breezy as well, and
porting the lazr.restful stack; but we may soon be able to reach the point
where it&amp;#8217;s possible to start running interesting subsets of the test suite
using Python 3 and categorising the failures, at which point we&amp;#8217;ll be able
to get a much better idea of how far we still have to go.  Porting a project
with the best part of a million lines of code and around three hundred
dependencies is always going to take a while, but I&amp;#8217;m happy to be making
progress there, both due to Python 2&amp;#8217;s impending end of upstream support and
so that eventually we can start using new language&amp;nbsp;facilities.&lt;/p&gt;</content><category term="misc"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/><category term="storm"/></entry><entry><title>man-db 2.8.7</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-2.8.7.html" rel="alternate"/><published>2019-08-27T06:55:25+01:00</published><updated>2019-08-27T06:55:25+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2019-08-27:/~cjwatson/blog/man-db-2.8.7.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve released man-db 2.8.7
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2019-08/msg00002.html"&gt;announcement&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS?id=2.8.7"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;),
and uploaded it to Debian&amp;nbsp;unstable.&lt;/p&gt;
&lt;p&gt;There are a few things of note that I wanted to talk about here.  Firstly, I
made some further improvements to the seccomp sandbox originally introduced
in 2.8.0.  I do still think it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve released man-db 2.8.7
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2019-08/msg00002.html"&gt;announcement&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS?id=2.8.7"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;),
and uploaded it to Debian&amp;nbsp;unstable.&lt;/p&gt;
&lt;p&gt;There are a few things of note that I wanted to talk about here.  Firstly, I
made some further improvements to the seccomp sandbox originally introduced
in 2.8.0.  I do still think it&amp;#8217;s correct to try to confine subprocesses this
way as a defence against malicious documents, but it&amp;#8217;s also been a pretty
rough ride for some users, especially those who use various kinds of VPNs or
antivirus programs that install themselves using &lt;code&gt;/etc/ld.so.preload&lt;/code&gt; and
cause other programs to perform additional system calls.  As well as a few
specific tweaks, a &lt;a href="https://lwn.net/Articles/796108/"&gt;recent discussion on
&lt;span class="caps"&gt;LWN&lt;/span&gt;&lt;/a&gt; reminded me that it would be better
to make seccomp return &lt;code&gt;EPERM&lt;/code&gt; rather than raising &lt;code&gt;SIGSYS&lt;/code&gt;, since that&amp;#8217;s
easier to handle gracefully: in particular, it fixes &lt;a href="https://bugs.debian.org/902257"&gt;an odd corner case
related to glibc&amp;#8217;s nscd handling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Secondly, there was a &lt;a href="https://savannah.nongnu.org/bugs/?56734"&gt;build failure on
macOS&lt;/a&gt; that took a while to figure
out, not least because I don&amp;#8217;t have a macOS test system myself.  In 2.8.6 I
tried to make life easier for people on this platform with a &lt;a href="https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=056e8c7c012b00261133259d6438ff8303a8c36c"&gt;&lt;code&gt;CFLAGS&lt;/code&gt;
tweak&lt;/a&gt;,
but I made it a bit too general and accidentally took away configure&amp;#8217;s
ability to detect undefined symbols properly, which caused very confusing
failures.  More importantly, I hadn&amp;#8217;t really thought through why this change
was necessary and whether it was a good idea.  man-db uses private shared
libraries to keep its executable size down, and it passes &lt;code&gt;-no-undefined&lt;/code&gt; to
&lt;code&gt;libtool&lt;/code&gt; to declare that those shared libraries have no undefined symbols
after linking, which is necessary to build shared libraries on some
platforms.  But the &lt;code&gt;CFLAGS&lt;/code&gt; tweak above directly contradicts this!  So,
instead of playing core wars with my own build system, I did some
refactoring so that the assertion that man-db&amp;#8217;s shared libraries have no
undefined symbols after linking is actually true: this involved &lt;a href="https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=2519d2ffe769a4059bfe475a092afa40722eb38d"&gt;moving
decompression code out of
&lt;code&gt;libman&lt;/code&gt;&lt;/a&gt;,
and arranging for the code in &lt;code&gt;libmandb&lt;/code&gt; to take the database path as a
parameter rather than as a global variable (something I&amp;#8217;ve meant to fix for
ages anyway;
&lt;a href="https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=252d7cbc2328b27457aafcbd6fa5958a8be9fded"&gt;252d7cbc23&lt;/a&gt;,
&lt;a href="https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=036aa910ea000d716bcf0f4bcbcee3a54a848be7"&gt;036aa910ea&lt;/a&gt;,
&lt;a href="https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=a97d977b0bfc1ed34c3021b8d6702b047e8251af"&gt;a97d977b0b&lt;/a&gt;).
Lesson: don&amp;#8217;t make build system changes you don&amp;#8217;t quite&amp;nbsp;understand.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Buster upgrade</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/buster-upgrade.html" rel="alternate"/><published>2019-05-05T01:10:48+01:00</published><updated>2019-05-05T01:10:48+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2019-05-05:/~cjwatson/blog/buster-upgrade.html</id><summary type="html">&lt;p&gt;I upgraded my home server from Debian stretch to buster recently, which is
something I normally do once we&amp;#8217;re frozen: this is a system that was first
installed in 1999 and has a lot of complicated stuff on it, and while I try
to keep it as cleanly-maintained as …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I upgraded my home server from Debian stretch to buster recently, which is
something I normally do once we&amp;#8217;re frozen: this is a system that was first
installed in 1999 and has a lot of complicated stuff on it, and while I try
to keep it as cleanly-maintained as I can it still often runs into some
interesting problems.  Things went largely &lt;span class="caps"&gt;OK&lt;/span&gt; this time round, although
there were a few snags of various degrees of severity, some of which weren&amp;#8217;t
Debian&amp;#8217;s&amp;nbsp;fault.&lt;/p&gt;
&lt;p&gt;As ever, &lt;code&gt;etckeeper&lt;/code&gt; made it much more comfortable to make non-trivial
configuration file changes without fearing that I was going to lose&amp;nbsp;information.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The first &lt;code&gt;apt full-upgrade&lt;/code&gt; failed part-way through with &amp;#8220;dependency
   problems prevent processing triggers for desktop-file-utils&amp;#8221; for what
   didn&amp;#8217;t seem like a particularly good reason; &lt;code&gt;dpkg --configure -a&lt;/code&gt; sorted
   it out and I was able to resume the upgrade from there.  I think I&amp;#8217;ve
   seen a report of this somewhere recently as it rang a bell, though I
   haven&amp;#8217;t yet found&amp;nbsp;it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I had a number of truly annoying configuration file resolutions to
   perform.  There&amp;#8217;s not much to be done about that except try to gradually
   move things to &lt;code&gt;.d&lt;/code&gt; directories where available, and other such
   strategies to minimise the local differences I&amp;#8217;m&amp;nbsp;maintaining.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I had an old backup disk that had failed some time ago but was still
   plugged in and occasionally generating &lt;span class="caps"&gt;ATA&lt;/span&gt; errors.  These made some parts
   of the upgrade excruciatingly slow, so as soon as I got to a point where
   I had to reboot anyway I took the opportunity to open up the case and
   unplug&amp;nbsp;it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I hit &lt;a href="https://bugs.debian.org/919621"&gt;#919621 &amp;#8220;lvm2: Update unexpectedly activates system &lt;span class="caps"&gt;ID&lt;/span&gt; check,
   bypassing impossible&amp;#8221;&lt;/a&gt;.  Fortunately I
   noticed the problem before rebooting due to warning messages from various
   things, and I adjusted my &lt;span class="caps"&gt;LVM&lt;/span&gt; configuration to set a system &lt;span class="caps"&gt;ID&lt;/span&gt; matching
   the one in my volume group.  Unfortunately I forgot to run
   &lt;code&gt;update-initramfs -u&lt;/code&gt; after doing so, and so I ended up having to use
   &lt;code&gt;break=premount&lt;/code&gt; on the kernel command line and fix things up in the same
   way in the initramfs until I could update it properly.  I&amp;#8217;m not sure what
   the right fix for this is, although it probably only affects some rather
   old VGs; I created mine in&amp;nbsp;2004.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I ran into &lt;a href="https://bugs.debian.org/924881"&gt;#924881 &amp;#8220;postgresql: buster upgrade breaks older postgresql
   (9.6) and newer postgresql (11) is also
   inoperative&amp;#8221;&lt;/a&gt; (in fact a bug in
   &lt;code&gt;ssl-cert&lt;/code&gt;).  It was correct to reject the snakeoil certificate, but the
   upgrade failure mode was pretty graceless and it would have been helpful
   for something to notice the situation and prompt me to regenerate the&amp;nbsp;certificate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My networking wasn&amp;#8217;t happy after the upgrade; I ended up with some
   missing addresses, which I&amp;#8217;m prepared to believe was the fault of my very
   old and badly-organised &lt;code&gt;/etc/network/interfaces&lt;/code&gt; file, so I rearranged
   it to follow what seems to be the modern best practice of handling
   multiple addresses on an interface by just having one &lt;code&gt;iface&lt;/code&gt; stanza per
   address using the same interface name, rather than &lt;code&gt;pre-up ip addr add&lt;/code&gt;
   lines or alias interfaces or anything like that.  After that, the
   interface sometimes refused to come up at all with &amp;#8220;&lt;span class="caps"&gt;ADDRCONF&lt;/span&gt;(NETDEV_UP):
   eth0: link is not ready&amp;#8221; messages.  Some web-searching and grepping of
   the kernel source led me to the idea that listing &lt;code&gt;inet6&lt;/code&gt; stanzas before
   &lt;code&gt;inet&lt;/code&gt; stanzas for a given interface name was likely to be helpful, and
   so it proved: I now have an &lt;code&gt;/etc/network/interfaces&lt;/code&gt; that both works and
   is much easier to&amp;nbsp;read.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I had to do some manual steps to get Icinga Web 2 authentication working
   again: I followed the &lt;a href="https://icinga.com/docs/icingaweb2/latest/doc/80-Upgrading/#upgrading-pgsql-db"&gt;upstream directions to upgrade the database
   schema&lt;/a&gt;,
   and I had to run &lt;code&gt;a2enmod php7.3&lt;/code&gt; manually since the previous enablement
   of &lt;code&gt;php7.0&lt;/code&gt; wasn&amp;#8217;t carried over.  (I&amp;#8217;m not completely sure if the first
   step was required, but the second certainly&amp;nbsp;was.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other than that, everything seems to be working well&amp;nbsp;now.&lt;/p&gt;</content><category term="debian"/><category term="debian"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>binfmt-support 2.2.0</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/binfmt-support-2.2.0.html" rel="alternate"/><published>2019-01-25T11:21:57+00:00</published><updated>2019-01-25T11:21:57+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2019-01-25:/~cjwatson/blog/binfmt-support-2.2.0.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve released binfmt-support 2.2.0.  These are the major changes since&amp;nbsp;2.1.8:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove support for the old procfs interface, which has been unused since
   Linux 2.4.13 and which caused trouble in environments where we can&amp;#8217;t use
   modprobe.  Thanks to Bastian&amp;nbsp;Blank.&lt;/li&gt;
&lt;li&gt;Sort formats …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve released binfmt-support 2.2.0.  These are the major changes since&amp;nbsp;2.1.8:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove support for the old procfs interface, which has been unused since
   Linux 2.4.13 and which caused trouble in environments where we can&amp;#8217;t use
   modprobe.  Thanks to Bastian&amp;nbsp;Blank.&lt;/li&gt;
&lt;li&gt;Sort formats by name in the output of &lt;code&gt;update-binfmts --display&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Building binfmt-support now requires Autoconf &amp;gt;=&amp;nbsp;2.63.&lt;/li&gt;
&lt;li&gt;Add a new &lt;code&gt;--unimport&lt;/code&gt; action, which is the inverse of &lt;code&gt;--import&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Don&amp;#8217;t enable formats on import or disable them on unimport unless
   &lt;code&gt;/proc/sys/fs/binfmt_misc&lt;/code&gt; is already mounted.  This avoids causing
   cleanup problems in&amp;nbsp;chroots.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--fix-binary yes&lt;/code&gt; is incompatible with detectors.  Warn the user if they
   try to use both at once.  Thanks to Stefan&amp;nbsp;Agner.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the corresponding Debian upload (2.2.0-1), I&amp;#8217;ve changed &lt;span class="caps"&gt;README&lt;/span&gt;.Debian to
recommend using &lt;code&gt;update-binfmts --unimport &amp;lt;name&amp;gt;&lt;/code&gt; in the prerm rather than
a more complicated &lt;code&gt;update-binfmts --package &amp;lt;package&amp;gt; --remove &amp;lt;name&amp;gt;
&amp;lt;path&amp;gt;&lt;/code&gt; command.  I don&amp;#8217;t intend to push for existing packages to switch
over to this before buster, though, since the stricter package relationships
needed to arrange for a new enough version of binfmt-support to be present
when the prerm runs would make the upgrade path more complicated, and it
isn&amp;#8217;t an urgent&amp;nbsp;change.&lt;/p&gt;</content><category term="misc"/><category term="binfmt-support"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Deploying Swift</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/deploying-swift.html" rel="alternate"/><published>2018-12-04T01:37:11+00:00</published><updated>2018-12-04T01:37:11+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2018-12-04:/~cjwatson/blog/deploying-swift.html</id><summary type="html">&lt;p&gt;Sometimes I want to deploy &lt;a href="https://docs.openstack.org/swift/"&gt;Swift&lt;/a&gt;, the
OpenStack object storage&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Well, no, that&amp;#8217;s not true.  I basically never actually want to deploy Swift
as such.  What I generally want to do is to debug some bit of production
service deployment machinery that relies on Swift for getting build …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Sometimes I want to deploy &lt;a href="https://docs.openstack.org/swift/"&gt;Swift&lt;/a&gt;, the
OpenStack object storage&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Well, no, that&amp;#8217;s not true.  I basically never actually want to deploy Swift
as such.  What I generally want to do is to debug some bit of production
service deployment machinery that relies on Swift for getting build
artifacts into the right place, or maybe the parts of the
&lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; librarian (our blob storage service)
that use Swift.  I could find an existing private or public cloud that
offers the right &lt;span class="caps"&gt;API&lt;/span&gt; and test with that, but sometimes I need to test with
particular versions, and in any case I have a terribly slow internet
connection and shuffling large build artifacts back and forward over the
relevant bit of wet string makes it painfully slow to test&amp;nbsp;things.&lt;/p&gt;
&lt;p&gt;For a while I&amp;#8217;ve had an Ubuntu 12.04 &lt;span class="caps"&gt;VM&lt;/span&gt; lying around with an
&lt;a href="https://releases.openstack.org/icehouse/"&gt;Icehouse&lt;/a&gt;-based Swift deployment
that I put together by hand.  It works, but I didn&amp;#8217;t keep good notes and
have no real idea how to reproduce it, not that I really want to keep
limping along with manually-constructed VMs for this kind of thing anyway;
and I don&amp;#8217;t want to be dependent on obsolete releases forever.  For the
sorts of things I&amp;#8217;m doing I need to make sure that authentication works
broadly the same way as it does in a real production deployment, so I want
to have &lt;a href="https://docs.openstack.org/keystone/"&gt;Keystone&lt;/a&gt; too.  At the same
time, I definitely don&amp;#8217;t want to do anything close to a full OpenStack
deployment of my own: it&amp;#8217;s much too big a sledgehammer for this particular
nut, and I don&amp;#8217;t really have the hardware for&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s my solution to this, which is compact enough that I can run it on my
laptop, and while it isn&amp;#8217;t completely automatic it&amp;#8217;s close enough that I can
spin it up for a test and discard it when I&amp;#8217;m finished (so I haven&amp;#8217;t worried
very much about producing something that runs efficiently).  It relies on
&lt;a href="https://docs.jujucharms.com/"&gt;Juju&lt;/a&gt; and
&lt;a href="https://linuxcontainers.org/lxd/"&gt;&lt;span class="caps"&gt;LXD&lt;/span&gt;&lt;/a&gt;.  I&amp;#8217;ve only tested it on Ubuntu
18.04, using &lt;a href="https://releases.openstack.org/queens/"&gt;Queens&lt;/a&gt;; for anything
else you&amp;#8217;re on your own.  In general, I probably can&amp;#8217;t help you if you run
into trouble with the directions here: this is provided &amp;#8220;as is&amp;#8221;, without
warranty of any kind, and all that kind of&amp;nbsp;thing.&lt;/p&gt;
&lt;p&gt;First, install Juju and &lt;span class="caps"&gt;LXD&lt;/span&gt; if necessary, following the instructions
provided by those projects, and also install the &lt;code&gt;python-openstackclient&lt;/code&gt;
package as you&amp;#8217;ll need it later.  You&amp;#8217;ll want to &lt;a href="https://docs.jujucharms.com/2.4/en/tut-lxd"&gt;set Juju up to use
&lt;span class="caps"&gt;LXD&lt;/span&gt;&lt;/a&gt;, and you should probably
make sure that the shells you&amp;#8217;re working in don&amp;#8217;t have &lt;code&gt;http_proxy&lt;/code&gt; set as
it&amp;#8217;s quite likely to confuse things unless you&amp;#8217;ve arranged for your proxy to
be able to cope with your local &lt;span class="caps"&gt;LXD&lt;/span&gt; containers.  Then add a
&lt;a href="https://docs.jujucharms.com/2.4/en/juju-concepts#model"&gt;model&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;juju&lt;span class="w"&gt; &lt;/span&gt;add-model&lt;span class="w"&gt; &lt;/span&gt;swift
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At this point there&amp;#8217;s a bit of complexity that you normally don&amp;#8217;t have to
worry about with Juju.  The &lt;a href="https://jujucharms.com/swift-storage"&gt;swift-storage
charm&lt;/a&gt; wants to mount something to use
for storage, which with the &lt;span class="caps"&gt;LXD&lt;/span&gt; provider in practice ends up being some kind
of loopback mount.  Unfortunately, being able to perform loopback mounts
exposes too much kernel attack surface, so &lt;span class="caps"&gt;LXD&lt;/span&gt; doesn&amp;#8217;t allow unprivileged
containers to do it.
(&lt;a href="https://bugs.launchpad.net/charm-swift-storage/+bug/1250965"&gt;Ideally&lt;/a&gt; the
swift-storage charm would just let you use directory storage instead.)  To
make the containers we&amp;#8217;re about to create privileged enough for this to
work,&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lxc&lt;span class="w"&gt; &lt;/span&gt;profile&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;juju-swift&lt;span class="w"&gt; &lt;/span&gt;security.privileged&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
lxc&lt;span class="w"&gt; &lt;/span&gt;profile&lt;span class="w"&gt; &lt;/span&gt;device&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;juju-swift&lt;span class="w"&gt; &lt;/span&gt;loop-control&lt;span class="w"&gt; &lt;/span&gt;unix-char&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;major&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;minor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;237&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/loop-control
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;lxc&lt;span class="w"&gt; &lt;/span&gt;profile&lt;span class="w"&gt; &lt;/span&gt;device&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;juju-swift&lt;span class="w"&gt; &lt;/span&gt;loop&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unix-block&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;major&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;minor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/loop&lt;span class="nv"&gt;$i&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can start deploying things!  Save this to a file, e.g.
&lt;code&gt;swift.bundle&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;series&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bionic&lt;/span&gt;
&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Swift&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;box&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;applications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;charm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cs:mysql-62&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;candidate&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;num_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;dataset-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;512M&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;keystone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;charm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cs:keystone&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;num_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;swift-storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;charm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cs:swift-storage&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;num_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;keystone&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;block-device&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/etc/swift/storage.img|5G&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;swift-proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;charm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cs:swift-proxy&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;num_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;mysql&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;zone-assignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;auto&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="nt"&gt;relations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;keystone:shared-db&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mysql:shared-db&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;swift-proxy:swift-storage&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;swift-storage:swift-storage&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;swift-proxy:identity-service&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;keystone:identity-service&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;juju&lt;span class="w"&gt; &lt;/span&gt;deploy&lt;span class="w"&gt; &lt;/span&gt;./swift.bundle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will take a while.  You can run &lt;code&gt;juju status&lt;/code&gt; to see how it&amp;#8217;s going in
general terms, or &lt;code&gt;juju debug-log&lt;/code&gt; for detailed logs from the individual
containers as they&amp;#8217;re putting themselves together.  When it&amp;#8217;s all done, it
should look something like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Controller&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Cloud&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;SLA&lt;/span&gt;
&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;lxd&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;unsupported&lt;/span&gt;

&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Scale&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Charm&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;Store&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;Rev&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;OS&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Notes&lt;/span&gt;
&lt;span class="n"&gt;keystone&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;keystone&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;jujucharms&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;290&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="mf"&gt;5.7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;jujucharms&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;
&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mf"&gt;2.17&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;jujucharms&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;
&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;2.17&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;jujucharms&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;

&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="n"&gt;Workload&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Machine&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Ports&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;keystone&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;idle&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.133&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;idle&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.44&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Ready&lt;/span&gt;
&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;idle&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.44&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;
&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;idle&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.133&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;

&lt;span class="n"&gt;Machine&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;DNS&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="n"&gt;Inst&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Series&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;AZ&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.133&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;juju&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3e703&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bionic&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mf"&gt;10.36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;63.44&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;juju&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d3e703&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bionic&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At this point you have what should be a working installation, but with only
administrative privileges set up.  Normally you want to create at least one
normal user.  To do this, start by creating a configuration file granting
administrator privileges (this one comes verbatim from the &lt;a href="https://api.jujucharms.com/charmstore/v5/openstack-base/archive/openrc"&gt;openstack-base
bundle&lt;/a&gt;,
though with one
&lt;a href="https://github.com/openstack-charmers/openstack-charm-testing/commit/720a55eb629653bd78194a0cfbc21864406252d7#diff-291a64b96dd1baf50cca0b4c158a47b2"&gt;change&lt;/a&gt;
that isn&amp;#8217;t yet in the charm store version at the time of&amp;nbsp;writing):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;_OS_PARAMS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;env&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BEGIN {FS=&amp;quot;=&amp;quot;} /^OS_/ {print $1;}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;paste&lt;span class="w"&gt; &lt;/span&gt;-sd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;param&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$_OS_PARAMS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;OS_AUTH_PROTOCOL&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;OS_CACERT&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$param&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="nb"&gt;unset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;_OS_PARAMS

&lt;span class="nv"&gt;_keystone_unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;juju&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/units:$/ {getline; gsub(/:$/, &amp;quot;&amp;quot;); print $1; exit}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;_keystone_ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;juju&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--unit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_keystone_unit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;unit-get private-address&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;juju&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--unit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_keystone_unit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;leader-get admin_passwd&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_AUTH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OS_AUTH_PROTOCOL&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;http&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;://&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_keystone_ip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:5000/v3
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_USER_DOMAIN_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin_domain
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_PROJECT_DOMAIN_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin_domain
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_REGION_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;RegionOne
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_IDENTITY_API_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="c1"&gt;# Swift needs this:&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_AUTH_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="c1"&gt;# Gnocchi needs this&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OS_AUTH_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Source this into a shell: for instance, if you saved this to
&lt;code&gt;~/.swiftrc.juju-admin&lt;/code&gt;, then&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;. ~/.swiftrc.juju-admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should now be able to run &lt;code&gt;openstack endpoint list&lt;/code&gt; and see a table for
the various services exposed by your deployment.  Then you can create a
dummy project and a user with enough privileges to use&amp;nbsp;Swift:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-username
&lt;span class="nv"&gt;PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-password
openstack&lt;span class="w"&gt; &lt;/span&gt;domain&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;SwiftDomain
openstack&lt;span class="w"&gt; &lt;/span&gt;project&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--domain&lt;span class="w"&gt; &lt;/span&gt;SwiftDomain&lt;span class="w"&gt; &lt;/span&gt;--description&lt;span class="w"&gt; &lt;/span&gt;Swift&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;SwiftProject
openstack&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--domain&lt;span class="w"&gt; &lt;/span&gt;SwiftDomain&lt;span class="w"&gt; &lt;/span&gt;--project-domain&lt;span class="w"&gt; &lt;/span&gt;SwiftDomain&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--project&lt;span class="w"&gt; &lt;/span&gt;SwiftProject&lt;span class="w"&gt; &lt;/span&gt;--password&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$USERNAME&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
openstack&lt;span class="w"&gt; &lt;/span&gt;role&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;--project&lt;span class="w"&gt; &lt;/span&gt;SwiftProject&lt;span class="w"&gt; &lt;/span&gt;--user-domain&lt;span class="w"&gt; &lt;/span&gt;SwiftDomain&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$USERNAME&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Member
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(This is intended for testing rather than for doing anything particularly
sensitive.  If you cared about keeping the password secret then you&amp;#8217;d use
the &lt;code&gt;--password-prompt&lt;/code&gt; option to &lt;code&gt;openstack user create&lt;/code&gt; instead of
supplying the password on the command&amp;nbsp;line.)&lt;/p&gt;
&lt;p&gt;Now create a configuration file granting privileges for the user you just
created.  I felt like automating this to at least some&amp;nbsp;degree:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;touch ~/.swiftrc.juju
chmod 600 ~/.swiftrc.juju
sed &amp;#39;/^_password=/d;
     s/\( OS_PROJECT_DOMAIN_NAME=\).*/\1SwiftDomain/;
     s/\( OS_PROJECT_NAME=\).*/\1SwiftProject/;
     s/\( OS_USER_DOMAIN_NAME=\).*/\1SwiftDomain/;
     s/\( OS_USERNAME=\).*/\1&amp;#39;&amp;quot;$USERNAME&amp;quot;&amp;#39;/;
     s/\( OS_PASSWORD=\).*/\1&amp;#39;&amp;quot;$PASSWORD&amp;quot;&amp;#39;/&amp;#39; \
     &amp;lt;~/.swiftrc.juju-admin &amp;gt;~/.swiftrc.juju
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Source this into a shell.  For&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;. ~/.swiftrc.juju
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should now find that &lt;code&gt;swift list&lt;/code&gt; works.  Success!  Now you can &lt;code&gt;swift
upload&lt;/code&gt; files, or just start testing whatever it was that you were actually
trying to test in the first&amp;nbsp;place.&lt;/p&gt;
&lt;p&gt;This is not a setup I expect to leave running for a long time, so to tear it
down&amp;nbsp;again:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;juju destroy-model swift
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will probably get stuck trying to remove the &lt;code&gt;swift-storage&lt;/code&gt; unit,
since nothing deals with detaching the loop device.  If that happens, find
the relevant device in &lt;code&gt;losetup -a&lt;/code&gt; from another window and use &lt;code&gt;losetup -d&lt;/code&gt;
to detach it; &lt;code&gt;juju destroy-model&lt;/code&gt; should then be able to&amp;nbsp;proceed.&lt;/p&gt;
&lt;p&gt;Credit to the Juju and &lt;span class="caps"&gt;LXD&lt;/span&gt; teams and to the maintainers of the various
charms used here, as well as of course to the OpenStack folks: their work
made it very much easier to put this&amp;nbsp;together.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2019-01-18: Edited to deploy to two containers rather than four, and to
incorporate a &lt;code&gt;~/.swiftrc.juju-admin&lt;/code&gt; change to cope with&amp;nbsp;that.&lt;/em&gt;&lt;/p&gt;</content><category term="ubuntu"/><category term="juju"/><category term="openstack"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>An odd test failure</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/odd-test-failure.html" rel="alternate"/><published>2017-12-19T13:52:52+00:00</published><updated>2017-12-19T13:52:52+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2017-12-19:/~cjwatson/blog/odd-test-failure.html</id><summary type="html">&lt;p&gt;Weird test failures are great at teaching you things that you didn&amp;#8217;t realise
you might need to&amp;nbsp;know.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/mysterious-bug-with-twisted-plugins.html"&gt;As previously
mentioned&lt;/a&gt;, I&amp;#8217;ve been
working on converting Launchpad from &lt;a href="http://www.buildout.org/"&gt;Buildout&lt;/a&gt; to
&lt;a href="https://virtualenv.pypa.io/en/stable/"&gt;virtualenv&lt;/a&gt; and
&lt;a href="https://pip.pypa.io/en/stable/"&gt;pip&lt;/a&gt;, and I finally landed that change on
our development branch today.  The final landing was …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weird test failures are great at teaching you things that you didn&amp;#8217;t realise
you might need to&amp;nbsp;know.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/mysterious-bug-with-twisted-plugins.html"&gt;As previously
mentioned&lt;/a&gt;, I&amp;#8217;ve been
working on converting Launchpad from &lt;a href="http://www.buildout.org/"&gt;Buildout&lt;/a&gt; to
&lt;a href="https://virtualenv.pypa.io/en/stable/"&gt;virtualenv&lt;/a&gt; and
&lt;a href="https://pip.pypa.io/en/stable/"&gt;pip&lt;/a&gt;, and I finally landed that change on
our development branch today.  The final landing was mostly quite smooth,
except for one test failure on our buildbot that I hadn&amp;#8217;t seen&amp;nbsp;before:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;ERROR: lp.codehosting.codeimport.tests.test_worker.TestBzrSvnImport.test_stacked&lt;/span&gt;
&lt;span class="x"&gt;worker ID: unknown worker (bug in our subunit output?)&lt;/span&gt;
&lt;span class="x"&gt;----------------------------------------------------------------------&lt;/span&gt;
&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class="gr"&gt;_StringException&lt;/span&gt;: &lt;span class="n"&gt;log: {{{&lt;/span&gt;
&lt;span class="x"&gt;36.384  creating repository in file:///tmp/testbzr-6CwSLV.tmp/lp.codehosting.codeimport.tests.test_worker.TestBzrSvnImport.test_stacked/work/stacked-on/.bzr/.&lt;/span&gt;
&lt;span class="x"&gt;36.388  creating branch &amp;lt;bzrlib.branch.BzrBranchFormat7 object at 0xeb85b36c&amp;gt; in file:///tmp/testbzr-6CwSLV.tmp/lp.codehosting.codeimport.tests.test_worker.TestBzrSvnImport.test_stacked/work/stacked-on/&lt;/span&gt;
&lt;span class="x"&gt;}}}&lt;/span&gt;

&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/lib/lp/codehosting/codeimport/tests/test_worker.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;1108&lt;/span&gt;, in &lt;span class="n"&gt;test_stacked&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;stacked_on&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Branch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_details&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/branch.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;186&lt;/span&gt;, in &lt;span class="n"&gt;open&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;possible_transports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;possible_transports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_unsupported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_unsupported&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/controldir.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;689&lt;/span&gt;, in &lt;span class="n"&gt;open&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_unsupported&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_unsupported&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/controldir.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;718&lt;/span&gt;, in &lt;span class="n"&gt;open_from_transport&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;find_format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redirected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/transport/__init__.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;1719&lt;/span&gt;, in &lt;span class="n"&gt;do_catching_redirections&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/controldir.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;706&lt;/span&gt;, in &lt;span class="n"&gt;find_format&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;probers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;probers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  File &lt;span class="nb"&gt;&amp;quot;/srv/buildbot/lpbuildbot/lp-devel-xenial/build/env/local/lib/python2.7/site-packages/bzrlib/controldir.py&amp;quot;&lt;/span&gt;, line &lt;span class="m"&gt;1155&lt;/span&gt;, in &lt;span class="n"&gt;find_format&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotBranchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gr"&gt;NotBranchError&lt;/span&gt;: &lt;span class="n"&gt;Not a branch: &amp;quot;/tmp/tmpdwqrc6/trunk/&amp;quot;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When I investigated this locally, I found that I could reproduce it if I ran
just that test on its own, but not if I ran it together with the other tests
in the same class.  That&amp;#8217;s certainly my favourite way round for test
isolation failures to present themselves (it&amp;#8217;s more usual to find state from
one test leaking out and causing another one to fail, which can make for a
very time-consuming exercise of trying to find the critical combination),
but it&amp;#8217;s still pretty&amp;nbsp;odd.&lt;/p&gt;
&lt;p&gt;I stepped through the &lt;code&gt;Branch.open&lt;/code&gt; call in each case in the hope of some
enlightenment.  The interesting difference was that the custom probers
installed by the &lt;code&gt;bzr-svn&lt;/code&gt; plugin weren&amp;#8217;t installed when I ran that one test
on its own, so it was trying to open a branch as a Bazaar branch rather than
using the foreign-branch logic for Subversion, and this presumably depended
on some configuration that only some tests put in place.  I was on the verge
of just explicitly setting up that plugin in the test suite&amp;#8217;s &lt;code&gt;setUp&lt;/code&gt;
method, but I was still curious about exactly what was breaking&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;Launchpad installs several Bazaar plugins, and
&lt;code&gt;lib/lp/codehosting/__init__.py&lt;/code&gt; is responsible for putting most of these in
place: anything in Launchpad itself that uses Bazaar is generally supposed
to do something like &lt;code&gt;import lp.codehosting&lt;/code&gt; to set everything up.  I
therefore put a breakpoint at the top of &lt;code&gt;lp.codehosting&lt;/code&gt; and stepped
through it to see whether anything was going wrong in the initial setup.
Sure enough, I found that &lt;code&gt;bzrlib.plugins.svn&lt;/code&gt; was failing to import due to
an exception raised by &lt;code&gt;bzrlib.i18n.load_plugin_translations&lt;/code&gt;, which was
being swallowed silently but meant that its custom probers weren&amp;#8217;t being
installed.  Here&amp;#8217;s what that function looks&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;load_plugin_translations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Load the translations for a specific plugin.&lt;/span&gt;

&lt;span class="sd"&gt;    :param domain: Gettext domain name (usually &amp;#39;bzr-PLUGINNAME&amp;#39;)&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;locale_base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getfilesystemencoding&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="n"&gt;translation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;install_translations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;locale_base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;locale_base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;add_fallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;translation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, &lt;code&gt;sys.getfilesystemencoding&lt;/code&gt; was returning &lt;code&gt;None&lt;/code&gt;, which isn&amp;#8217;t
a valid &lt;code&gt;encoding&lt;/code&gt; argument to &lt;code&gt;unicode&lt;/code&gt;.  But why would that be?  It gave
me a sensible result when I ran it from a Python shell in this environment.
A bit of head-scratching later and it occurred to me to look at a&amp;nbsp;backtrace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(Pdb) bt
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/env/lib/python2.7/site.py(703)&amp;lt;module&amp;gt;()
-&amp;gt; main()
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/env/lib/python2.7/site.py(694)main()
-&amp;gt; execsitecustomize()
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/env/lib/python2.7/site.py(548)execsitecustomize()
-&amp;gt; import sitecustomize
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/env/lib/python2.7/sitecustomize.py(7)&amp;lt;module&amp;gt;()
-&amp;gt; lp_sitecustomize.main()
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/lib/lp_sitecustomize.py(193)main()
-&amp;gt; dont_wrap_bzr_branch_classes()
  /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/lib/lp_sitecustomize.py(139)dont_wrap_bzr_branch_classes()
-&amp;gt; import lp.codehosting
&amp;gt; /home/cjwatson/src/canonical/launchpad/lp-branches/testfix/lib/lp/codehosting/__init__.py(54)&amp;lt;module&amp;gt;()
-&amp;gt; load_plugins([_get_bzr_plugins_path()])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I wonder if there&amp;#8217;s something interesting about being imported from a
&lt;code&gt;sitecustomize&lt;/code&gt; hook?  Sure enough, when I went to look at Python for where
&lt;code&gt;sys.getfilesystemencoding&lt;/code&gt; is set up, I found this in &lt;code&gt;Py_InitializeEx&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Py_NoSiteFlag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;initsite&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cm"&gt;/* Module site */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="cp"&gt;#if defined(Py_USING_UNICODE) &amp;amp;&amp;amp; defined(HAVE_LANGINFO_H) &amp;amp;&amp;amp; defined(CODESET)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* On Unix, set the file system encoding according to the&lt;/span&gt;
&lt;span class="cm"&gt;       user&amp;#39;s preference, if the CODESET names a well-known&lt;/span&gt;
&lt;span class="cm"&gt;       Python codec, and Py_FileSystemDefaultEncoding isn&amp;#39;t&lt;/span&gt;
&lt;span class="cm"&gt;       initialized by other means. Also set the encoding of&lt;/span&gt;
&lt;span class="cm"&gt;       stdin and stdout if these are terminals, unless overridden.  */&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;overridden&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Py_FileSystemDefaultEncoding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/avoid-importing-bzr-plugins-from-site/+merge/335379"&gt;moved this out of
sitecustomize&lt;/a&gt;,
and it&amp;#8217;s working better now.  But did you know that a &lt;code&gt;sitecustomize&lt;/code&gt; hook
can&amp;#8217;t safely use anything that depends on &lt;code&gt;sys.getfilesystemencoding&lt;/code&gt;?  I
certainly didn&amp;#8217;t, until it bit&amp;nbsp;me.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Kitten Block equivalent for Firefox 57</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/kitten-block-equivalent-for-firefox-57.html" rel="alternate"/><published>2017-11-16T19:15:48+00:00</published><updated>2017-11-16T19:15:48+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2017-11-16:/~cjwatson/blog/kitten-block-equivalent-for-firefox-57.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve been using &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/kitten-block/"&gt;Kitten
Block&lt;/a&gt; for
years, since I don&amp;#8217;t really need the blood pressure spike caused by
accidentally following links to certain &lt;span class="caps"&gt;UK&lt;/span&gt; newspapers.  Unfortunately it
hasn&amp;#8217;t been ported to Firefox 57.  I tried emailing the author a couple of
months ago, but my email&amp;nbsp;bounced …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve been using &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/kitten-block/"&gt;Kitten
Block&lt;/a&gt; for
years, since I don&amp;#8217;t really need the blood pressure spike caused by
accidentally following links to certain &lt;span class="caps"&gt;UK&lt;/span&gt; newspapers.  Unfortunately it
hasn&amp;#8217;t been ported to Firefox 57.  I tried emailing the author a couple of
months ago, but my email&amp;nbsp;bounced.&lt;/p&gt;
&lt;p&gt;However, if your primary goal is just to block the websites in question
rather than seeing kitten pictures as such (let&amp;#8217;s face it, the internet is
not short of alternative sources of kitten pictures), then it&amp;#8217;s easy to do
with &lt;a href="https://addons.mozilla.org/en-GB/firefox/addon/ublock-origin/"&gt;uBlock
Origin&lt;/a&gt;.
After installing the extension if necessary, go to Tools → Add-ons →
Extensions → uBlock Origin → Preferences → My filters, and add
&lt;code&gt;www.dailymail.co.uk&lt;/code&gt; and &lt;code&gt;www.express.co.uk&lt;/code&gt;, each on its own line.  (Of
course you can easily add more if you like.)  Voilà: instant&amp;nbsp;tranquility.&lt;/p&gt;
&lt;p&gt;Incidentally, this also works fine on Android.  The fact that it was easy to
install a good ad blocker without having to mess about with a rooted device
or strange proxy settings was the main reason I switched to Firefox on my&amp;nbsp;phone.&lt;/p&gt;</content><category term="misc"/><category term="firefox"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>A mysterious bug with Twisted plugins</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/mysterious-bug-with-twisted-plugins.html" rel="alternate"/><published>2017-09-26T11:20:14-04:00</published><updated>2017-09-26T11:20:14-04:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2017-09-26:/~cjwatson/blog/mysterious-bug-with-twisted-plugins.html</id><summary type="html">&lt;p&gt;I fixed a bug in Launchpad recently that led me deeper than I&amp;nbsp;expected.&lt;/p&gt;
&lt;p&gt;Launchpad uses &lt;a href="http://www.buildout.org/"&gt;Buildout&lt;/a&gt; as its build system for
Python packages, and it&amp;#8217;s served us well for many years.  However, we&amp;#8217;re
using 1.7.1, which doesn&amp;#8217;t support ensuring that packages required using
setuptools …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I fixed a bug in Launchpad recently that led me deeper than I&amp;nbsp;expected.&lt;/p&gt;
&lt;p&gt;Launchpad uses &lt;a href="http://www.buildout.org/"&gt;Buildout&lt;/a&gt; as its build system for
Python packages, and it&amp;#8217;s served us well for many years.  However, we&amp;#8217;re
using 1.7.1, which doesn&amp;#8217;t support ensuring that packages required using
setuptools&amp;#8217; &lt;a href="https://setuptools.readthedocs.io/en/latest/setuptools.html#new-and-changed-setup-keywords"&gt;setup_requires
keyword&lt;/a&gt;
only ever come from the local index &lt;span class="caps"&gt;URL&lt;/span&gt; when one is specified; that&amp;#8217;s an
essential constraint we need to be able to impose so that our build system
isn&amp;#8217;t immediately sensitive to downtime or changes in PyPI.  There are
various issues/PRs about this in Buildout (e.g.
&lt;a href="https://github.com/buildout/buildout/pull/238"&gt;#238&lt;/a&gt;), but even if those
are fixed it&amp;#8217;ll almost certainly only be in Buildout v2, and upgrading to
that is its own kettle of fish for other reasons.  All this is a serious
problem for us because newer versions of many of our vital dependencies
(&lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt; and
&lt;a href="https://pypi.python.org/pypi/testtools"&gt;testtools&lt;/a&gt;, to name but two) use
&lt;code&gt;setup_requires&lt;/code&gt; to pull in &lt;a href="https://pypi.python.org/pypi/pbr"&gt;pbr&lt;/a&gt;, and so
we&amp;#8217;ve been stuck on old versions for some time; this is part of why
Launchpad doesn&amp;#8217;t yet support newer &lt;span class="caps"&gt;SSH&lt;/span&gt; key types, for instance.  This
situation obviously isn&amp;#8217;t&amp;nbsp;sustainable.&lt;/p&gt;
&lt;p&gt;To deal with this, I&amp;#8217;ve been working for some time on switching to
&lt;a href="https://virtualenv.pypa.io/en/stable/"&gt;virtualenv&lt;/a&gt; and
&lt;a href="https://pip.pypa.io/en/stable/"&gt;pip&lt;/a&gt;.  This is harder than you might think:
Launchpad is a long-lived and complicated project, and it had quite a number
of explicit and implicit dependencies on Buildout&amp;#8217;s configuration and
behaviour.  Upgrading our infrastructure from Ubuntu 12.04 to 16.04 has
helped a lot (12.04&amp;#8217;s baseline virtualenv and pip have some deficiencies
that would have required a more complicated bootstrapping procedure).  I&amp;#8217;ve
dealt with most of these: for example, I had to reorganise a lot of our
helper scripts
(&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/simplify-buildout-bin-python-easy/+merge/314976"&gt;1&lt;/a&gt;,
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/simplify-buildout-bin-shell/+merge/314973"&gt;2&lt;/a&gt;,
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/simplify-buildout-bin-test/+merge/323743"&gt;3&lt;/a&gt;),
but there are still a few more things to&amp;nbsp;go.&lt;/p&gt;
&lt;p&gt;One remaining problem was that our Buildout configuration relied on building
several different environments with different Python paths for various
things.  While this would technically be possible by way of building
multiple virtualenvs, this would inflate our build time even further (we&amp;#8217;re
already going to have to cope with some slowdown as a result of using
virtualenv, because the build system now has to do a lot more than
constructing a glorified link farm to a bunch of cached eggs), and it seems
like unnecessary complexity.  The obvious thing to do seemed to be to
collapse these into a single environment, since there was no obvious reason
why it should actually matter if
&lt;a href="https://pypi.python.org/pypi/txpkgupload"&gt;txpkgupload&lt;/a&gt; and
&lt;a href="https://pypi.python.org/pypi/txlongpoll"&gt;txlongpoll&lt;/a&gt; were carefully kept
off the path when running most of Launchpad: so &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/simplify-buildout-recipes/+merge/330159"&gt;I did
that&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then our build system &lt;a href="http://lpbuildbot.canonical.com/builders/lp-devel-precise/builds/1582/steps/shell_9/logs/summary"&gt;got very
sad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hmm, I thought.  To keep our test times somewhat manageable, we run them in
parallel across 20 containers, and we randomise the order in which they run
to try to shake out test isolation bugs.  It&amp;#8217;s not completely unknown for
there to be some oddities resulting from that.  So I ran it again.  &lt;a href="http://lpbuildbot.canonical.com/builders/lp-devel-precise/builds/1583/steps/shell_9/logs/summary"&gt;Nope,
but slightly differently sad this
time&lt;/a&gt;.
Furthermore, I couldn&amp;#8217;t reproduce these failures locally no matter how hard
I tried.  Oh dear.  This was obviously not going to be a good&amp;nbsp;day.&lt;/p&gt;
&lt;p&gt;In fact I spent a while on various different guesswork-based approaches.  I
found &lt;a href="https://bugs.launchpad.net/ampoule/+bug/571334"&gt;bug 571334&lt;/a&gt; in
Ampoule, an &lt;span class="caps"&gt;AMP&lt;/span&gt;-based process pool implementation that we use for some job
runners, and proposed a
&lt;a href="https://code.launchpad.net/~cjwatson/ampoule/process-error-not-ready/+merge/330848"&gt;fix&lt;/a&gt;
for that, but cherry-picking that fix into Launchpad didn&amp;#8217;t help matters.  I
tried backing out subsets of my changes and determined that if both
&lt;code&gt;txlongpoll&lt;/code&gt; and &lt;code&gt;txpkgupload&lt;/code&gt; were absent from the Python module path in
the context of the tests in question then everything was fine.  I tried
running &lt;code&gt;strace&lt;/code&gt; locally and staring at the output for some time in the hope
of enlightenment: that reminded me that the two packages in question install
modules under &lt;code&gt;twisted.plugins&lt;/code&gt;, which did at least establish a reason they
might affect the environment that was more plausible than magic, but nothing
much more specific than&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;On Friday I was fiddling about with this again and trying to insert some
more debugging when I noticed some interesting behaviour around &lt;a href="https://twistedmatrix.com/documents/current/core/howto/plugin.html#plugin-caching"&gt;plugin
caching&lt;/a&gt;.
If I caused the &lt;code&gt;txpkgupload&lt;/code&gt; plugin to raise an exception when loaded, the
Twisted plugin system would remove its &lt;code&gt;dropin.cache&lt;/code&gt; (because it was stale)
and not create a new one (because there was now no content to put in it).
After that, running the relevant tests would fail as I&amp;#8217;d seen in our
buildbot.  Aha!  This meant that I could also reproduce it by doing an even
cleaner build than I&amp;#8217;d previously tried to do, by removing the cached
&lt;code&gt;txpkgupload&lt;/code&gt; and &lt;code&gt;txlongpoll&lt;/code&gt; eggs and allowing the build system to
recreate them.  When they were recreated, they didn&amp;#8217;t contain
&lt;code&gt;dropin.cache&lt;/code&gt;, instead allowing that to be created on first&amp;nbsp;use.&lt;/p&gt;
&lt;p&gt;Based on this clue I was able to get to the answer relatively quickly.
Ampoule has a specialised bootstrapping sequence for its worker processes
that starts by doing&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;twisted.application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reactors&lt;/span&gt;
&lt;span class="n"&gt;reactors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;installReactor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reactor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, &lt;code&gt;twisted.application.reactors.installReactor&lt;/code&gt; calls
&lt;code&gt;twisted.plugin.getPlugins&lt;/code&gt;, so the very start of this bootstrapping
sequence is going to involve loading all plugins found on the module path (I
assume it&amp;#8217;s possible to write a plugin that adds an alternative reactor
implementation).  If &lt;code&gt;dropin.cache&lt;/code&gt; is up to date, then it will just get the
information it needs from that; but if it isn&amp;#8217;t, it will go ahead and import
the plugin.  If the plugin happens (as Twisted code often does) to run &lt;code&gt;from
twisted.internet import reactor&lt;/code&gt; at some point while being imported, then
that will install the platform&amp;#8217;s default reactor, and &lt;em&gt;then&lt;/em&gt;
&lt;code&gt;twisted.application.reactors.installReactor&lt;/code&gt; will raise
&lt;code&gt;ReactorAlreadyInstalledError&lt;/code&gt;.  Since Ampoule turns this into an info-level
log message for some reason, and the tests in question only passed through
error-level messages or higher, this meant that all we could see was that a
worker process had exited non-zero but not&amp;nbsp;why.&lt;/p&gt;
&lt;p&gt;The Twisted documentation
&lt;a href="https://twistedmatrix.com/documents/current/core/howto/plugin.html#plugin-caching"&gt;recommends&lt;/a&gt;
generating the plugin cache at build time for other reasons, but we weren&amp;#8217;t
doing that.  &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/build-twisted-plugin-cache/+merge/331240"&gt;Fixing
that&lt;/a&gt;
makes everything work&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;There are still a few more things needed to get us onto pip, but we&amp;#8217;re now
pretty close.  After that we can finally start bringing our dependencies up
to&amp;nbsp;date.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/><category term="twisted"/></entry><entry><title>env —chdir</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/env-chdir.html" rel="alternate"/><published>2017-08-30T00:54:42+01:00</published><updated>2017-08-30T00:54:42+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2017-08-30:/~cjwatson/blog/env-chdir.html</id><summary type="html">&lt;p&gt;I was recently asked to sort things out so that
&lt;a href="https://snapcraft.io/"&gt;snap&lt;/a&gt; builds on &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt;
could themselves install snaps as build-dependencies.  To make this work we
need to start doing builds in &lt;a href="https://linuxcontainers.org/lxd/"&gt;&lt;span class="caps"&gt;LXD&lt;/span&gt;
containers&lt;/a&gt; rather than in chroots.  As a
result I&amp;#8217;ve been doing some quite extensive refactoring of
&lt;a href="https://launchpad.net/launchpad-buildd"&gt;launchpad-buildd …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;I was recently asked to sort things out so that
&lt;a href="https://snapcraft.io/"&gt;snap&lt;/a&gt; builds on &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt;
could themselves install snaps as build-dependencies.  To make this work we
need to start doing builds in &lt;a href="https://linuxcontainers.org/lxd/"&gt;&lt;span class="caps"&gt;LXD&lt;/span&gt;
containers&lt;/a&gt; rather than in chroots.  As a
result I&amp;#8217;ve been doing some quite extensive refactoring of
&lt;a href="https://launchpad.net/launchpad-buildd"&gt;launchpad-buildd&lt;/a&gt;: it previously
had the assumption that it was going to use a chroot for everything baked
into lots of untested helper shell scripts, and I&amp;#8217;ve been rewriting those in
Python with unit tests and with a single &lt;code&gt;Backend&lt;/code&gt; abstraction that isolates
the high-level logic from the details of where each build is being&amp;nbsp;performed.&lt;/p&gt;
&lt;p&gt;This is all interesting work in its own right, but it&amp;#8217;s not what I want to
talk about here.  While I was doing all this refactoring, I ran across a
couple of methods I wrote a while back which looked something like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;chroot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Run a command in the chroot.&lt;/span&gt;

&lt;span class="sd"&gt;    :param args: the command and arguments to run.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;set_personality&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Running in chroot: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;
              &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check_call&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;/usr/bin/sudo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/usr/sbin/chroot&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chroot_path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run_build_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Run a build command in the chroot.&lt;/span&gt;

&lt;span class="sd"&gt;    This is unpleasant because we need to run it in /build under sudo&lt;/span&gt;
&lt;span class="sd"&gt;    chroot, and there&amp;#39;s no way to do this without either a helper&lt;/span&gt;
&lt;span class="sd"&gt;    program in the chroot or unpleasant quoting.  We go for the&lt;/span&gt;
&lt;span class="sd"&gt;    unpleasant quoting.&lt;/span&gt;

&lt;span class="sd"&gt;    :param args: the command and arguments to run.&lt;/span&gt;
&lt;span class="sd"&gt;    :param env: dictionary of additional environment variables to set.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;shell_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;env&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd /build &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chroot&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/bin/sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(I&amp;#8217;ve already replaced the &lt;code&gt;chroot&lt;/code&gt; method with a call to &lt;code&gt;Backend.run&lt;/code&gt;, but
it&amp;#8217;s easier to see what I&amp;#8217;m talking about in the original&amp;nbsp;form.)&lt;/p&gt;
&lt;p&gt;One thing to notice about this code is that it uses several &lt;em&gt;adverbial&lt;/em&gt;
commands: that is, commands that run another command in a different way.
For example, &lt;code&gt;sudo&lt;/code&gt; runs another command as another user, while &lt;code&gt;chroot&lt;/code&gt;
runs another command with a different root directory, and &lt;code&gt;env&lt;/code&gt; runs another
command with different environment variables set.  These commands chain
neatly, and they also have the useful property that they take the subsidiary
command and its arguments as a list of arguments.  coreutils has &lt;a href="https://www.gnu.org/software/coreutils/manual/html_node/Modified-command-invocation.html"&gt;several
other
commands&lt;/a&gt;
that behave this way, and
&lt;a href="http://www.greenend.org.uk/rjk/sw/adverbio.html"&gt;adverbio&lt;/a&gt; is another
useful&amp;nbsp;example.&lt;/p&gt;
&lt;p&gt;By contrast, &lt;code&gt;su -c&lt;/code&gt; is something you might call a &amp;#8220;quasi-adverbial&amp;#8221;
command: it does modify the behaviour of another command, but it takes it as
a single argument which it then passes to &lt;code&gt;sh -c&lt;/code&gt;.  Every time you have
something that&amp;#8217;s passed to a shell like this, you need a corresponding layer
of shell quoting to escape any shell metacharacters that should be
interpreted literally.  This is often cumbersome and is easy to get wrong.
My Python implementation is as follows, and I wouldn&amp;#8217;t be totally surprised
to discover that it contained a&amp;nbsp;bug:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;re&lt;/span&gt;

&lt;span class="n"&gt;non_meta_re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^[a-zA-Z0-9+,./:=@_-]+$&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;shell_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;non_meta_re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python &amp;gt;= 3.3 has
&lt;a href="https://docs.python.org/3/library/shlex#shlex.quote"&gt;shlex.quote&lt;/a&gt;, which is
an improvement and we should probably use that instead, but it&amp;#8217;s still
another thing to forget to call.  This is why process-spawning libraries
such as Python&amp;#8217;s &lt;a href="https://docs.python.org/3/library/subprocess"&gt;subprocess&lt;/a&gt;,
Perl&amp;#8217;s &lt;a href="http://perldoc.perl.org/functions/system.html"&gt;system&lt;/a&gt; and
&lt;a href="http://perldoc.perl.org/functions/open.html"&gt;open&lt;/a&gt;, and my own
&lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline&lt;/a&gt; for C encourage programmers to
use a list syntax and to avoid involving the shell entirely wherever&amp;nbsp;possible.&lt;/p&gt;
&lt;p&gt;One thing that the standard Unix tools don&amp;#8217;t let you do in an adverbial way
is to change your working directory, and I&amp;#8217;ve run into this annoying
limitation several times.  This means that it&amp;#8217;s difficult to chain that
operation together with other adverbs, for example to run a command in a
particular working directory inside a chroot.  The workaround I used above
was to invoke a shell that runs &lt;code&gt;cd /build &amp;amp;&amp;amp; ...&lt;/code&gt;, but that&amp;#8217;s another
command that&amp;#8217;s only quasi-adverbial, since the extra shell means an extra
layer of shell&amp;nbsp;quoting.&lt;/p&gt;
&lt;p&gt;(Ian Jackson rightly observes that you can in fact write the necessary
adverb as something like &lt;code&gt;sh -ec 'cd "$1"; shift; exec "$@"' chdir&lt;/code&gt;.  I
think that&amp;#8217;s a bit uglier than I ideally want to use in production code, but
you might reasonably think that it&amp;#8217;s worth it to avoid the extra layer of
shell&amp;nbsp;quoting.)&lt;/p&gt;
&lt;p&gt;I therefore decided that this was a feature that belonged in
&lt;a href="https://www.gnu.org/software/coreutils/"&gt;coreutils&lt;/a&gt;, and after &lt;a href="https://lists.gnu.org/archive/html/coreutils/2017-08/msg00053.html"&gt;a bit of
mailing list
discussion&lt;/a&gt;
we felt it was best implemented as a new option to
&lt;a href="https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html"&gt;env(1)&lt;/a&gt;.
I sent a patch for this which has been
&lt;a href="https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=57dea5ed07471b2192cc5edf08993e663a3f6802"&gt;accepted&lt;/a&gt;.
This means that we have a new composable adverb, &lt;code&gt;env --chdir=NEWDIR&lt;/code&gt;, which
will allow the &lt;code&gt;run_build_command&lt;/code&gt; method above to be rewritten as something
like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run_build_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Run a build command in the chroot.&lt;/span&gt;

&lt;span class="sd"&gt;    :param args: the command and arguments to run.&lt;/span&gt;
&lt;span class="sd"&gt;    :param env: dictionary of additional environment variables to set.&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;env_args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;env&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;--chdir=/build&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;env_args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chroot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env_args&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;env --chdir&lt;/code&gt; option will be in coreutils 8.28.  We won&amp;#8217;t be able to use
it in launchpad-buildd until that&amp;#8217;s available in all Ubuntu series we might
want to build for, so in this particular application that&amp;#8217;s going to take a
few years; but other applications may well be able to make use of it&amp;nbsp;sooner.&lt;/p&gt;</content><category term="misc"/><category term="coreutils"/><category term="launchpad"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>New address book</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/new-address-book.html" rel="alternate"/><published>2017-06-27T12:57:27+01:00</published><updated>2017-06-27T12:57:27+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2017-06-27:/~cjwatson/blog/new-address-book.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve had a kludgy mess of electronic address books for most of two decades,
and have got rather fed up with it.  My stack consisted&amp;nbsp;of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.mutt/aliases&lt;/code&gt;, a flat text file consisting of &lt;code&gt;mutt&lt;/code&gt; &lt;code&gt;alias&lt;/code&gt; commands&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.spinnaker.de/lbdb/"&gt;lbdb&lt;/a&gt; configuration to query
   &lt;code&gt;~/.mutt/aliases&lt;/code&gt;, Debian&amp;#8217;s &lt;span class="caps"&gt;LDAP&lt;/span&gt; database, and Canonical …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve had a kludgy mess of electronic address books for most of two decades,
and have got rather fed up with it.  My stack consisted&amp;nbsp;of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.mutt/aliases&lt;/code&gt;, a flat text file consisting of &lt;code&gt;mutt&lt;/code&gt; &lt;code&gt;alias&lt;/code&gt; commands&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.spinnaker.de/lbdb/"&gt;lbdb&lt;/a&gt; configuration to query
   &lt;code&gt;~/.mutt/aliases&lt;/code&gt;, Debian&amp;#8217;s &lt;span class="caps"&gt;LDAP&lt;/span&gt; database, and Canonical&amp;#8217;s &lt;span class="caps"&gt;LDAP&lt;/span&gt; database,
   so that I can search by name with Ctrl-t in &lt;code&gt;mutt&lt;/code&gt; when composing a new&amp;nbsp;message&lt;/li&gt;
&lt;li&gt;Google Contacts, which I used from Android and was completely separate
   from all of the&amp;nbsp;above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The biggest practical problem with this was that I had the address book that
was most convenient for me to add things to (Google Contacts) and the one I
used when sending email, and no sensible way to merge them or move things
between them.  I also wasn&amp;#8217;t especially comfortable with having all my
contact information in a proprietary web&amp;nbsp;service.&lt;/p&gt;
&lt;p&gt;My goals for a replacement address book system&amp;nbsp;were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;free software&amp;nbsp;throughout&lt;/li&gt;
&lt;li&gt;storage under my&amp;nbsp;control&lt;/li&gt;
&lt;li&gt;single common&amp;nbsp;database&lt;/li&gt;
&lt;li&gt;minimal manual transcription when consolidating existing&amp;nbsp;databases&lt;/li&gt;
&lt;li&gt;integration with Android such that I can continue using the same
   contacts, messaging, etc.&amp;nbsp;apps&lt;/li&gt;
&lt;li&gt;integration with &lt;code&gt;mutt&lt;/code&gt; such that I can continue using the same query&amp;nbsp;interface&lt;/li&gt;
&lt;li&gt;not having to write my own software, because&amp;nbsp;honestly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think I have all this&amp;nbsp;now!&lt;/p&gt;
&lt;h2&gt;New&amp;nbsp;stack&lt;/h2&gt;
&lt;p&gt;The obvious basic technology to use is
&lt;a href="https://en.wikipedia.org/wiki/CardDAV"&gt;CardDAV&lt;/a&gt;: it&amp;#8217;s fairly complex,
admittedly, but lots of software supports it and one of my goals was not
having to write my own thing.  This meant I needed a CardDAV server, some
way to sync the database to and from both Android and the system where I run
&lt;code&gt;mutt&lt;/code&gt;, and whatever query glue was necessary to get &lt;code&gt;mutt&lt;/code&gt; to understand&amp;nbsp;vCards.&lt;/p&gt;
&lt;p&gt;There are lots of different alternatives here, and if anything the problem
was an embarrassment of choice.  In the end I just decided to go for things
that looked roughly the right shape for me and tried not to spend too much
time in analysis&amp;nbsp;paralysis.&lt;/p&gt;
&lt;h3&gt;CardDAV&amp;nbsp;server&lt;/h3&gt;
&lt;p&gt;I went with &lt;a href="https://www.jelmer.uk/xandikos-intro.html"&gt;Xandikos&lt;/a&gt; for the
server, largely because I know Jelmer and have generally had pretty good
experiences with their software, but also because using Git for history of
the backend storage seems like something my future self will thank me&amp;nbsp;for.&lt;/p&gt;
&lt;p&gt;It isn&amp;#8217;t packaged in stretch, but it&amp;#8217;s in Debian unstable, so I installed it
from&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;Rather than the standalone mode suggested on the web page, I decided to set
it up in what felt like a more robust way using &lt;span class="caps"&gt;WSGI&lt;/span&gt;.  I installed
&lt;code&gt;gunicorn&lt;/code&gt; and &lt;code&gt;python3-gunicorn&lt;/code&gt;, created the following file in
&lt;code&gt;/etc/systemd/system/xandikos.socket&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Xandikos socket&lt;/span&gt;

&lt;span class="k"&gt;[Socket]&lt;/span&gt;
&lt;span class="na"&gt;ListenStream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/xandikos.socket&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;sockets.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;#8230; and the following file in &lt;code&gt;/etc/systemd/system/xandikos.service&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Xandikos CalDAV/CardDAV server&lt;/span&gt;
&lt;span class="na"&gt;Documentation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;man:xandikos(1)&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;xandikos.socket&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;xandikos&lt;/span&gt;
&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;xandikos&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/python3 /usr/bin/gunicorn --bind=unix:/run/xandikos.socket xandikos.wsgi:app&lt;/span&gt;
&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s TERM $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;XANDIKOSPATH=/srv/xandikos/collections&lt;/span&gt;
&lt;span class="na"&gt;ProtectSystem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;strict&lt;/span&gt;
&lt;span class="na"&gt;ProtectKernelTunables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;ProtectControlGroups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;PrivateDevices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;ReadWritePaths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/xandikos.socket /srv/xandikos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The path (&lt;code&gt;/srv/xandikos/collections&lt;/code&gt;) was arbitrary.  You need to create
the &lt;code&gt;xandikos&lt;/code&gt; user and group first (&lt;code&gt;adduser --system --group
--no-create-home --disabled-login xandikos&lt;/code&gt;).  I created &lt;code&gt;/srv/xandikos&lt;/code&gt;
owned by &lt;code&gt;xandikos:xandikos&lt;/code&gt; and mode 0700.  You should also run &lt;code&gt;sudo -u
xandikos xandikos -d /srv/xandikos/collections --autocreate&lt;/code&gt; and then Ctrl-c
it after a short time (I think it would be nicer if there were a way to &lt;a href="https://bugs.debian.org/866093"&gt;ask
the &lt;span class="caps"&gt;WSGI&lt;/span&gt; wrapper to do this&lt;/a&gt;).  If you
aren&amp;#8217;t using systemd then you can of course write equivalent init scripts&amp;nbsp;instead.&lt;/p&gt;
&lt;p&gt;For Apache setup, I kept it reasonably simple: I ran &lt;code&gt;a2enmod proxy_http&lt;/code&gt;,
used &lt;code&gt;htpasswd&lt;/code&gt; to create &lt;code&gt;/etc/apache2/xandikos.passwd&lt;/code&gt; with a username and
password for myself, added a virtual host in
&lt;code&gt;/etc/apache2/sites-available/xandikos.conf&lt;/code&gt;, and enabled it with &lt;code&gt;a2ensite
xandikos&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*:443&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;ServerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;xandikos.example.org
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;ServerAdmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;me@example.org

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;ErrorLog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sx"&gt;/var/log/apache2/xandikos-error.log&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;TransferLog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sx"&gt;/var/log/apache2/xandikos-access.log&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;ProxyPass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;unix:/run/xandikos.socket|http://xandikos.riva.dynamic.greenend.org.uk/&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;AuthType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Basic
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;AuthName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Xandikos&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;AuthBasicProvider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;AuthUserFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/etc/apache2/xandikos.passwd&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nb"&gt;Require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;valid-user
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should of course adjust the &lt;code&gt;ProxyPass&lt;/code&gt; line to match your own&amp;nbsp;deployment.&lt;/p&gt;
&lt;p&gt;Then &lt;code&gt;service apache2 reload&lt;/code&gt;, set the new virtual host up with &lt;a href="https://letsencrypt.org/"&gt;Let&amp;#8217;s
Encrypt&lt;/a&gt;, reloaded again, and off we&amp;nbsp;go.&lt;/p&gt;
&lt;h3&gt;Android&amp;nbsp;integration&lt;/h3&gt;
&lt;p&gt;I installed &lt;a href="https://www.davx5.com/"&gt;DAVx⁵&lt;/a&gt; from the Play Store: it cost a
few pounds, but I was &lt;span class="caps"&gt;OK&lt;/span&gt; with that since it&amp;#8217;s GPLv3 and I&amp;#8217;m happy to help
fund free software.  I created two accounts, one for my existing Google
Contacts database (and in fact calendaring as well, although I don&amp;#8217;t intend
to switch over to self-hosting that just yet), and one for the new Xandikos
instance.  The Google setup was a bit fiddly because I have two-step
verification turned on so I had to create an app-specific password.  The
Xandikos setup was straightforward: base &lt;span class="caps"&gt;URL&lt;/span&gt;, username, password, and&amp;nbsp;done.&lt;/p&gt;
&lt;p&gt;Since I didn&amp;#8217;t completely trust the new setup yet, I followed what seemed
like the most robust option from the &lt;a href="https://www.davx5.com/faq/existing-contacts-are-not-synced"&gt;DAVx⁵ contacts syncing
documentation&lt;/a&gt;,
and used the stock contacts app to export my Google Contacts account to a
&lt;code&gt;.vcf&lt;/code&gt; file and then import that into the appropriate DAVx⁵ account (which
showed up automatically).  This seemed straightforward and everything got
pushed to Xandikos.  There are some weird delays in syncing contacts that I
don&amp;#8217;t entirely understand, but it all seems to get there in the&amp;nbsp;end.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2019-06-13: Followed rename of DAVdroid to DAVx⁵.  At the moment Google
Contacts support seems to be flaky at best; see the &lt;a href="https://forums.bitfire.at/tags/google"&gt;DAVx⁵
forums&lt;/a&gt; for&amp;nbsp;tips.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;mutt&amp;nbsp;integration&lt;/h3&gt;
&lt;p&gt;First off I needed to sync the contacts.  (In fact I happen to run &lt;code&gt;mutt&lt;/code&gt; on
the same system where I run Xandikos at the moment, but I don&amp;#8217;t want to rely
on that, and going through the CardDAV server means that I don&amp;#8217;t have to
poke holes for myself using filesystem permissions.)  I used
&lt;a href="https://vdirsyncer.pimutils.org/"&gt;vdirsyncer&lt;/a&gt; for this.  In
&lt;code&gt;~/.vdirsyncer/config&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[general]&lt;/span&gt;
&lt;span class="na"&gt;status_path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/.vdirsyncer/status/&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;[pair contacts]&lt;/span&gt;
&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;contacts_local&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;contacts_remote&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;collections&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;[&amp;quot;from a&amp;quot;, &amp;quot;from b&amp;quot;]&lt;/span&gt;

&lt;span class="k"&gt;[storage contacts_local]&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;filesystem&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/.contacts/&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;fileext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.vcf&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;[storage contacts_remote]&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;carddav&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;lt;Xandikos base URL&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;lt;my username&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;lt;my password&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Running &lt;code&gt;vdirsyncer discover&lt;/code&gt; and &lt;code&gt;vdirsyncer sync&lt;/code&gt; then synced everything
into &lt;code&gt;~/.contacts/&lt;/code&gt;.  I added an hourly &lt;code&gt;crontab&lt;/code&gt; entry to run &lt;code&gt;vdirsyncer
-v WARNING sync&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, I needed a command-line address book tool based on this.
&lt;a href="https://github.com/scheibler/khard"&gt;khard&lt;/a&gt; looked about right and is in
stretch, so I installed that.  In &lt;code&gt;~/.config/khard/khard.conf&lt;/code&gt; (this is
mostly just the example configuration, but I preferred to sort by first name
since not all my contacts have neat first/last&amp;nbsp;names):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[addressbooks]&lt;/span&gt;
&lt;span class="k"&gt;[[contacts]]&lt;/span&gt;
&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;~/.contacts/&amp;lt;UUID of my contacts collection&amp;gt;/&lt;/span&gt;

&lt;span class="k"&gt;[general]&lt;/span&gt;
&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="na"&gt;default_action&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;list&lt;/span&gt;
&lt;span class="na"&gt;editor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;vim&lt;/span&gt;
&lt;span class="na"&gt;merge_editor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;vimdiff&lt;/span&gt;

&lt;span class="k"&gt;[contact table]&lt;/span&gt;
&lt;span class="c1"&gt;# display names by first or last name: first_name / last_name&lt;/span&gt;
&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;first_name&lt;/span&gt;
&lt;span class="c1"&gt;# group by address book: yes / no&lt;/span&gt;
&lt;span class="na"&gt;group_by_addressbook&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="c1"&gt;# reverse table ordering: yes / no&lt;/span&gt;
&lt;span class="na"&gt;reverse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="c1"&gt;# append nicknames to name column: yes / no&lt;/span&gt;
&lt;span class="na"&gt;show_nicknames&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="c1"&gt;# show uid table column: yes / no&lt;/span&gt;
&lt;span class="na"&gt;show_uids&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="c1"&gt;# sort by first or last name: first_name / last_name&lt;/span&gt;
&lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;first_name&lt;/span&gt;

&lt;span class="k"&gt;[vcard]&lt;/span&gt;
&lt;span class="c1"&gt;# extend contacts with your own private objects&lt;/span&gt;
&lt;span class="c1"&gt;# these objects are stored with a leading &amp;quot;X-&amp;quot; before the object name in the vcard files&lt;/span&gt;
&lt;span class="c1"&gt;# every object label may only contain letters, digits and the - character&lt;/span&gt;
&lt;span class="c1"&gt;# example:&lt;/span&gt;
&lt;span class="c1"&gt;#   private_objects = Jabber, Skype, Twitter&lt;/span&gt;
&lt;span class="na"&gt;private_objects&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Jabber, Skype, Twitter&lt;/span&gt;
&lt;span class="c1"&gt;# preferred vcard version: 3.0 / 4.0&lt;/span&gt;
&lt;span class="na"&gt;preferred_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;3.0&lt;/span&gt;
&lt;span class="c1"&gt;# Look into source vcf files to speed up search queries: yes / no&lt;/span&gt;
&lt;span class="na"&gt;search_in_source_files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;span class="c1"&gt;# skip unparsable vcard files: yes / no&lt;/span&gt;
&lt;span class="na"&gt;skip_unparsable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code&gt;khard list&lt;/code&gt; shows all my contacts.  So far so good.  Apparently there
are some &lt;a href="https://github.com/scheibler/khard#khard"&gt;awkward vCard compatibility
issues&lt;/a&gt; with creating or modifying
contacts from the &lt;code&gt;khard&lt;/code&gt; end.  I&amp;#8217;ve tried adding one address from
&lt;code&gt;~/.mutt/aliases&lt;/code&gt; using &lt;code&gt;khard&lt;/code&gt; and it seems to at least minimally work for
me, but I haven&amp;#8217;t explored this very much&amp;nbsp;yet.&lt;/p&gt;
&lt;p&gt;I had to install python3-vobject 0.9.4.1-1 from experimental to fix
&lt;a href="https://github.com/eventable/vobject/issues/39"&gt;eventable/vobject#39&lt;/a&gt;
saving certain vCard&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;mutt&lt;/code&gt; integration.  I already had &lt;code&gt;set query_command="lbdbq '%s'"&lt;/code&gt;
in &lt;code&gt;~/.muttrc&lt;/code&gt;, and I wanted to keep that in place since I still wanted to
use &lt;span class="caps"&gt;LDAP&lt;/span&gt; querying as well.  I had to write a very small amount of code for
this (perhaps I should contribute this to &lt;code&gt;lbdb&lt;/code&gt; upstream?), in
&lt;code&gt;~/.lbdb/modules/m_khard&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#! /bin/sh&lt;/span&gt;

m_khard_query&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;khard&lt;span class="w"&gt; &lt;/span&gt;email&lt;span class="w"&gt; &lt;/span&gt;--parsable&lt;span class="w"&gt; &lt;/span&gt;--remove-first-line&lt;span class="w"&gt; &lt;/span&gt;--search-in-source-files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;My full &lt;code&gt;~/.lbdb/rc&lt;/code&gt; now reads as follows (you probably won&amp;#8217;t want the &lt;span class="caps"&gt;LDAP&lt;/span&gt;
stuff, but I&amp;#8217;ve included it here for&amp;nbsp;completeness):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;MODULES_PATH=&amp;quot;$MODULES_PATH $HOME/.lbdb/modules&amp;quot;
METHODS=&amp;#39;m_muttalias m_khard m_ldap&amp;#39;
LDAP_NICKS=&amp;#39;debian canonical&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Next&amp;nbsp;steps&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve deleted one account from Google Contacts just to make sure that
everything still works (e.g. I can still search for it when composing a new
message), but I haven&amp;#8217;t yet deleted everything.  I won&amp;#8217;t be adding anything
new there&amp;nbsp;though.&lt;/p&gt;
&lt;p&gt;I need to push everything from &lt;code&gt;~/.mutt/aliases&lt;/code&gt; into the new system.  This
is only about 30 contacts so shouldn&amp;#8217;t take too&amp;nbsp;long.&lt;/p&gt;
&lt;p&gt;Overall this feels like a big improvement!  It wasn&amp;#8217;t a trivial amount of
setup for just me, but it means I have both better usability for myself and
more independence from proprietary services, and I think I can add extra
users with much less effort if I need&amp;nbsp;to.&lt;/p&gt;
&lt;h2&gt;Postscript&lt;/h2&gt;
&lt;p&gt;A day later and I&amp;#8217;ve consolidated all my accounts from Google Contacts and
&lt;code&gt;~/.mutt/aliases&lt;/code&gt; into the new system, with the exception of one group that
I had defined as a &lt;code&gt;mutt&lt;/code&gt; alias and need to work out what to do with.  This
all went&amp;nbsp;smoothly.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve filed the new &lt;code&gt;lbdb&lt;/code&gt; module as
&lt;a href="https://bugs.debian.org/866178"&gt;#866178&lt;/a&gt;, and the &lt;code&gt;python3-vobject&lt;/code&gt; bug as
&lt;a href="https://bugs.debian.org/866181"&gt;#866181&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>The sad tale of CVE-2015-1336</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/cve-2015-1336.html" rel="alternate"/><published>2016-12-11T23:42:55+00:00</published><updated>2016-12-11T23:42:55+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2016-12-11:/~cjwatson/blog/cve-2015-1336.html</id><summary type="html">&lt;p&gt;Today I released man-db 2.7.6
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2016-12/msg00000.html"&gt;announcement&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS?id=2.7.6"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/log/?h=2.7.6"&gt;git log&lt;/a&gt;), and
uploaded it to Debian unstable.  The major change in this release was a set
of fixes for two security vulnerabilities,
&lt;a href="http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/"&gt;one&lt;/a&gt;
of which affected all man-db installations since 2.3.12 (or 2.3.10-66 in
Debian), and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I released man-db 2.7.6
(&lt;a href="https://lists.nongnu.org/archive/html/man-db-announce/2016-12/msg00000.html"&gt;announcement&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS?id=2.7.6"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/log/?h=2.7.6"&gt;git log&lt;/a&gt;), and
uploaded it to Debian unstable.  The major change in this release was a set
of fixes for two security vulnerabilities,
&lt;a href="http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/"&gt;one&lt;/a&gt;
of which affected all man-db installations since 2.3.12 (or 2.3.10-66 in
Debian), and &lt;a href="http://www.halfdog.net/Security/2015/MandbSymlinkLocalRootPrivilegeEscalation/"&gt;the
other&lt;/a&gt;
of which was specific to Debian and its&amp;nbsp;derivatives.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s probably obvious from the dates here that this has not been my finest
hour in terms of responding to security issues in a timely fashion, and I
apologise for that.  Some of this is just the usual life reasons, which I
shan&amp;#8217;t bore you by reciting, but some of it has been that fixing this
properly in man-db was genuinely rather complicated and delicate.  Since
I&amp;#8217;ve previously advocated man-db over some of its competitors on the basis
of a better security posture, I think it behooves me to write up a longer&amp;nbsp;description.&lt;/p&gt;
&lt;p&gt;I took over maintaining man-db over fifteen years ago in slightly unexpected
circumstances (I got annoyed with its bug list and made a couple of
non-maintainer uploads, and then the previous maintainer
&lt;a href="https://www.debian.org/News/2001/20010402b"&gt;died&lt;/a&gt;, so I ended up taking
over both in Debian and upstream).  I was a fairly new developer at the
time, and there weren&amp;#8217;t a lot of people I could ask questions of, but I did
my best to recover as much of the history as I could and learn from it.  One
thing that became clear very quickly, both from my own inspection and from
the bug list, was that most of the code had been written in a rather more
innocent time.  It was absolutely riddled with dangerous uses of the shell,
poor temporary file handling, buffer overruns, and various common-or-garden
deficiencies of that kind.  I spent several years reworking large swathes of
the codebase to be more robust against those kinds of bugs by design, and
for example &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline&lt;/a&gt; came out of that&amp;nbsp;effort.&lt;/p&gt;
&lt;p&gt;The most subtle and risky set of problems came from the fact that the &lt;code&gt;man&lt;/code&gt;
and &lt;code&gt;mandb&lt;/code&gt; programs were installed set-user-id to the &lt;code&gt;man&lt;/code&gt; user.  Part of
this was so that &lt;code&gt;man&lt;/code&gt; could maintain preformatted &amp;#8220;cat pages&amp;#8221;, and part of
it was so that users could run &lt;code&gt;mandb&lt;/code&gt; if the system databases were out of
date (this is now much less useful since most package managers, including
&lt;code&gt;dpkg&lt;/code&gt;, support some kind of trigger mechanism that can run &lt;code&gt;mandb&lt;/code&gt; whenever
new system-level manual pages are installed).  One of the first things I did
was to make this optional, and this has been a disabled-by-default &lt;code&gt;debconf&lt;/code&gt;
option in Debian for a long time now.  But it&amp;#8217;s still a supported option and
is enabled by default upstream, and when running setuid &lt;code&gt;man&lt;/code&gt; and &lt;code&gt;mandb&lt;/code&gt;
need to take care to drop privileges when dealing with user-controlled data
and to write files with the appropriate ownership and&amp;nbsp;permissions.&lt;/p&gt;
&lt;p&gt;My predecessor had problems related to this such as
&lt;a href="https://bugs.debian.org/26002"&gt;Debian #26002&lt;/a&gt;, and one of the ways they
dealt with them was to make &lt;code&gt;/var/cache/man/&lt;/code&gt; set-group-id root, in order
that files written to that directory would have consistent group ownership.
This always struck me as rather strange and I meant to do something about it
at some point, but until the first vulnerability report above I regarded it
as mainly a curiosity, since nothing in there was group-writeable anyway.
As a result, with the more immediate aim of making the system behave
consistently and dealing with bug reports, various bits of code had accreted
that assumed that &lt;code&gt;/var/cache/man/&lt;/code&gt; would be &lt;code&gt;man:root 2755&lt;/code&gt;, and not all of
it was immediately&amp;nbsp;obvious.&lt;/p&gt;
&lt;p&gt;This interacted with the second vulnerability report in two ways.  Firstly,
at some level it caused it because I was dealing with the day-to-day
problems rather than thinking at a higher level: a
&lt;a href="https://bugs.debian.org/129340"&gt;series&lt;/a&gt;
&lt;a href="https://bugs.debian.org/619726"&gt;of&lt;/a&gt; &lt;a href="https://bugs.debian.org/734063"&gt;bugs&lt;/a&gt;
led me down the path of whacking problems over the head with a recursive
&lt;code&gt;chown&lt;/code&gt; of &lt;code&gt;/var/cache/man/&lt;/code&gt; from &lt;code&gt;cron&lt;/code&gt;, rather than working out why things
got that way in the first place.  Secondly, once I&amp;#8217;d done that, I couldn&amp;#8217;t
remove the &lt;code&gt;chown&lt;/code&gt; without a much more extensive excursion into all the code
that dealt with cache files, for fear of reintroducing those bugs.  So
although the fix for the second vulnerability is &lt;a href="https://anonscm.debian.org/cgit/pkg-man-db/man-db.git/commit/?id=2f47ed4e682183f60f9aeed7f69f61e162019b20"&gt;very simple in
itself&lt;/a&gt;,
I couldn&amp;#8217;t get there without dealing with the first&amp;nbsp;vulnerability.&lt;/p&gt;
&lt;p&gt;In some ways, of course, cat pages are a bit of an anachronism.  Most modern
systems can format pages quickly enough that it&amp;#8217;s not much of an issue.
However, I&amp;#8217;m loath to drop the feature entirely: I&amp;#8217;m generally wary of
assuming that just because I have a fast system that everyone does.  So,
instead, I
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/commit/?id=31552334cecee82809059ec598a37d9ea82683f0"&gt;did&lt;/a&gt;
what I should have done years ago: make &lt;code&gt;man&lt;/code&gt; and &lt;code&gt;mandb&lt;/code&gt; set-group-id &lt;code&gt;man&lt;/code&gt;
as well as set-user-id &lt;code&gt;man&lt;/code&gt;, at which point we can simply make all the
cache files and directories be owned by &lt;code&gt;man:man&lt;/code&gt; and drop the setgid bit on
cache directories.  This should be simpler and less prone to
difficult-to-understand&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;I expect that my next substantial upstream release will switch to
&lt;code&gt;--disable-setuid&lt;/code&gt; by default to reduce exposure, though, and distributions
can start thinking about whether they want to follow that (Fedora already
does, for example).  If this becomes widely disabled without complaints then
that would be good evidence that it&amp;#8217;s reasonable to drop the feature
entirely.  I&amp;#8217;m not in a rush, but if you do need cat pages then now is a
good time to write to me and tell me&amp;nbsp;why.&lt;/p&gt;
&lt;p&gt;This is the fiddliest set of vulnerabilities I&amp;#8217;ve dealt with in man-db for
quite some time, so I hope that if there are more then I can get back to my
previous quick response&amp;nbsp;time.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>No more “Hash Sum Mismatch” errors</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/no-more-hash-sum-mismatch-errors.html" rel="alternate"/><published>2016-04-08T15:06:03+01:00</published><updated>2016-04-08T15:06:03+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2016-04-08:/~cjwatson/blog/no-more-hash-sum-mismatch-errors.html</id><summary type="html">&lt;p&gt;The Debian repository format was designed a long time ago.  The oldest
versions of it were produced with the help of tools such as
&lt;code&gt;dpkg-scanpackages&lt;/code&gt; and consumed by &lt;code&gt;dselect&lt;/code&gt; access methods such as
&lt;code&gt;dpkg-ftp&lt;/code&gt;.  The access methods just fetched a &lt;code&gt;Packages&lt;/code&gt; file (perhaps
compressed) and used it as an index …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The Debian repository format was designed a long time ago.  The oldest
versions of it were produced with the help of tools such as
&lt;code&gt;dpkg-scanpackages&lt;/code&gt; and consumed by &lt;code&gt;dselect&lt;/code&gt; access methods such as
&lt;code&gt;dpkg-ftp&lt;/code&gt;.  The access methods just fetched a &lt;code&gt;Packages&lt;/code&gt; file (perhaps
compressed) and used it as an index of which packages were available; each
package had an &lt;span class="caps"&gt;MD5&lt;/span&gt; checksum to defend against transport errors, but being
from a more innocent age there was no repository signing or other protection
against man-in-the-middle&amp;nbsp;attacks.&lt;/p&gt;
&lt;p&gt;An important and intentional feature of the early format was that, apart
from the top-level &lt;code&gt;Packages&lt;/code&gt; file, all other files were &lt;em&gt;static&lt;/em&gt; in the
sense that, once published, their content would never change without also
changing the file name.  This means that repositories can be efficiently
copied around using &lt;code&gt;rsync&lt;/code&gt; without having to tell it to re-checksum all
files, and it avoids network races when fetching updates: the repository
you&amp;#8217;re updating from might change in the middle of your update, but as long
as the repository maintenance software keeps superseded packages around for
a suitable grace period, you&amp;#8217;ll still be able to fetch&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;The repository format evolved rather organically over time as different
needs arose, by what one might call distributed consensus among the
maintainers of the various client tools that consumed it.  Of course all
sorts of fields were added to the index files themselves, which have an
extensible format so that this kind of thing is usually easy to do.  At some
point a &lt;code&gt;Sources&lt;/code&gt; index for source packages was added, which worked pretty
much the same way as &lt;code&gt;Packages&lt;/code&gt; except for having a different set of fields.
But by far the most significant change to the repository structure was the
&amp;#8220;package pools&amp;#8221;&amp;nbsp;project.&lt;/p&gt;
&lt;p&gt;The original repository layout put the packages themselves under the
&lt;code&gt;dists/&lt;/code&gt; tree along with the index files.  The &lt;code&gt;dists/&lt;/code&gt; tree is organised by
&amp;#8220;suite&amp;#8221; (modern examples of which would be &amp;#8220;stable&amp;#8221;, &amp;#8220;stable-updates&amp;#8221;,
&amp;#8220;testing&amp;#8221;, &amp;#8220;unstable&amp;#8221;, &amp;#8220;xenial&amp;#8221;, &amp;#8220;xenial-updates&amp;#8221;, and so on).  This meant
that making a release of Debian tended to involve copying lots of data
around, and implementing the &amp;#8220;testing&amp;#8221; suite would have been very costly.
Package pools solved this problem by moving individual package files out of
&lt;code&gt;dists/&lt;/code&gt; and into a new &lt;code&gt;pool/&lt;/code&gt; tree, allowing those files to be shared
between multiple suites with only a negligible cost in disk space and mirror
bandwidth.  From a database design perspective this is obviously much more
sensible.  As part of this project, the original Debian &amp;#8220;dinstall&amp;#8221;
repository maintenance scripts were
&lt;a href="https://lists.debian.org/debian-devel-announce/2000/10/msg00007.html"&gt;replaced&lt;/a&gt;
by &amp;#8220;da-katie&amp;#8221; or &amp;#8220;dak&amp;#8221;, which among other things used a new &lt;code&gt;apt-ftparchive&lt;/code&gt;
program to build the index files; this replaced &lt;code&gt;dpkg-scanpackages&lt;/code&gt; and
&lt;code&gt;dpkg-scansources&lt;/code&gt;, and included its own database cache which made a big
difference to performance at the scale of a&amp;nbsp;distribution.&lt;/p&gt;
&lt;p&gt;A few months after the initial implementation of package pools, &lt;code&gt;Release&lt;/code&gt;
files were added.  These formed a sort of meta-index for each suite, telling
&lt;span class="caps"&gt;APT&lt;/span&gt; which index files were available (&lt;code&gt;main/binary-i386/Packages&lt;/code&gt;,
&lt;code&gt;non-free/source/Sources&lt;/code&gt;, and so on) and what their checksums were.
Detached signatures were added alongside that (&lt;code&gt;Release.gpg&lt;/code&gt;) so that it was
now possible to fetch packages securely given a public key for the
repository, and &lt;a href="https://lists.debian.org/debian-devel/2003/12/msg01986.html"&gt;client-side verification
support&lt;/a&gt; for
this eventually made its way into Debian and Ubuntu.  The repository
structure stayed more or less like this for several&amp;nbsp;years.&lt;/p&gt;
&lt;p&gt;At some point along the way, those of us by now involved in repository
maintenance realised that an important property had been lost.  I mentioned
earlier that the original format allowed race-free updates, but this was no
longer true with the introduction of the &lt;code&gt;Release&lt;/code&gt; file.  A client now had
to fetch &lt;code&gt;Release&lt;/code&gt; and then fetch whichever other index files such as
&lt;code&gt;Packages&lt;/code&gt; they wanted, typically in separate &lt;span class="caps"&gt;HTTP&lt;/span&gt; transactions.  If a
client was unlucky, these transactions would fall on either side of a mirror
update and they&amp;#8217;d get a &amp;#8220;Hash Sum Mismatch&amp;#8221; error from &lt;span class="caps"&gt;APT&lt;/span&gt;.  Worse, if a
&lt;em&gt;mirror&lt;/em&gt; was unlucky and also didn&amp;#8217;t go to special lengths to verify index
integrity (most don&amp;#8217;t), its own updates could span an update of its upstream
mirror and then all its clients would see mismatches until the next mirror
update.  This was compounded by using detached signatures, so &lt;code&gt;Release&lt;/code&gt; and
&lt;code&gt;Release.gpg&lt;/code&gt; were fetched separately and could be out of&amp;nbsp;sync.&lt;/p&gt;
&lt;p&gt;Fixing this has been a long road (the first time I remember talking about
this was in late 2007!), and we&amp;#8217;ve had to take care to maintain
client/server compatibility along the way.  The first step was to add
inline-signed versions of the &lt;code&gt;Release&lt;/code&gt; file, called &lt;code&gt;InRelease&lt;/code&gt;, so that
there would no longer be a race between fetching &lt;code&gt;Release&lt;/code&gt; and fetching its
signature.  &lt;span class="caps"&gt;APT&lt;/span&gt; has had this for a while, Debian&amp;#8217;s repository supports it as
of &lt;code&gt;stretch&lt;/code&gt;, and we finally &lt;a href="https://bugs.launchpad.net/launchpad/+bug/804252"&gt;implemented it for
Ubuntu&lt;/a&gt; six months ago.
Dealing with the other index files is more complicated, though; it isn&amp;#8217;t
sensible to inline them, as clients usually only need to fetch a small
fraction of all the indexes available for a given&amp;nbsp;suite.&lt;/p&gt;
&lt;p&gt;The solution we&amp;#8217;ve ended up with, thanks to Michael Vogt&amp;#8217;s work implementing
it in &lt;span class="caps"&gt;APT&lt;/span&gt;, is called
&lt;a href="https://wiki.debian.org/RepositoryFormat#indices_acquisition_via_hashsums_.28by-hash.29"&gt;by-hash&lt;/a&gt;
and should be familiar in concept to people who&amp;#8217;ve used &lt;code&gt;git&lt;/code&gt;: with the
exception of the top-level &lt;code&gt;InRelease&lt;/code&gt; file, index files for suites that
support the by-hash mechanism may now be fetched using a &lt;span class="caps"&gt;URL&lt;/span&gt; based on one of
their hashes listed in &lt;code&gt;InRelease&lt;/code&gt;.  This means that clients can now operate
like&amp;nbsp;this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fetch &lt;code&gt;dists/xenial/InRelease&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fetch
   &lt;code&gt;dists/xenial/main/binary-amd64/by-hash/SHA256/46316a202cdae76a73b555414741b11d08c66620b76c470a1623cedcc8a14740&lt;/code&gt;
   (and so&amp;nbsp;on)&lt;/li&gt;
&lt;li&gt;Fetch individual package&amp;nbsp;files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is now &lt;a href="https://bugs.launchpad.net/launchpad/+bug/1430011"&gt;enabled by default in
Ubuntu&lt;/a&gt;.  It&amp;#8217;s only there
as of xenial (16.04), since earlier versions of Ubuntu don&amp;#8217;t have the
necessary support in &lt;span class="caps"&gt;APT&lt;/span&gt;.  With this, hash mismatches on updates should be a
thing of the&amp;nbsp;past.&lt;/p&gt;
&lt;p&gt;There will still be some people who won&amp;#8217;t yet benefit from this.
&lt;code&gt;debmirror&lt;/code&gt; doesn&amp;#8217;t support by-hash yet; &lt;code&gt;apt-cacher-ng&lt;/code&gt; only supports it as
of xenial, although there&amp;#8217;s an &lt;a href="https://bugs.debian.org/819852"&gt;easy configuration
workaround&lt;/a&gt;.  Full archive mirrors must make
sure that they put new by-hash files in place before new &lt;code&gt;InRelease&lt;/code&gt; files
(I just fixed our &lt;a href="https://wiki.ubuntu.com/Mirrors/Scripts"&gt;recommended two-stage sync
script&lt;/a&gt; to do this;
&lt;a href="https://launchpad.net/ubumirror"&gt;ubumirror&lt;/a&gt; still needs some work; Debian&amp;#8217;s
&lt;a href="https://www.debian.org/mirror/ftpmirror#how"&gt;ftpsync&lt;/a&gt; is almost correct but
needs a tweak for its handling of translation files, which I&amp;#8217;ve sent to its
maintainers).  Other mirrors and proxies that have specific handling of the
repository format may need similar&amp;nbsp;changes.&lt;/p&gt;
&lt;p&gt;Please let me know if you see strange things happening as a result of this
change.  It&amp;#8217;s useful to check the output of &lt;code&gt;apt -o
Debug::Acquire::http=true update&lt;/code&gt; to see exactly what requests are being&amp;nbsp;issued.&lt;/p&gt;</content><category term="launchpad"/><category term="apt"/><category term="launchpad"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Re-signing PPAs</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/re-signing-ppas.html" rel="alternate"/><published>2016-03-30T10:20:32+01:00</published><updated>2016-03-30T10:20:32+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2016-03-30:/~cjwatson/blog/re-signing-ppas.html</id><summary type="html">&lt;p&gt;Julian has
&lt;a href="https://juliank.wordpress.com/2016/03/14/dropping-sha-1-support-in-apt/"&gt;written&lt;/a&gt;
about their efforts to strengthen security in &lt;span class="caps"&gt;APT&lt;/span&gt;, and shortly before that
&lt;a href="https://bugs.launchpad.net/bugs/1556666"&gt;notified&lt;/a&gt; us that Launchpad&amp;#8217;s
signatures on &lt;acronym title="Personal Package Archives"&gt;PPAs&lt;/acronym&gt; use
weak &lt;span class="caps"&gt;SHA&lt;/span&gt;-1 digests.  Unfortunately we hadn&amp;#8217;t noticed that before; GnuPG&amp;#8217;s
defaults tend to result in weak digests unless carefully tweaked, which is a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Julian has
&lt;a href="https://juliank.wordpress.com/2016/03/14/dropping-sha-1-support-in-apt/"&gt;written&lt;/a&gt;
about their efforts to strengthen security in &lt;span class="caps"&gt;APT&lt;/span&gt;, and shortly before that
&lt;a href="https://bugs.launchpad.net/bugs/1556666"&gt;notified&lt;/a&gt; us that Launchpad&amp;#8217;s
signatures on &lt;acronym title="Personal Package Archives"&gt;PPAs&lt;/acronym&gt; use
weak &lt;span class="caps"&gt;SHA&lt;/span&gt;-1 digests.  Unfortunately we hadn&amp;#8217;t noticed that before; GnuPG&amp;#8217;s
defaults tend to result in weak digests unless carefully tweaked, which is a&amp;nbsp;shame.&lt;/p&gt;
&lt;p&gt;I started on the necessary fixes for this immediately we heard of the
problem, but it&amp;#8217;s taken a little while to get everything in place, and I
thought I&amp;#8217;d explain why since some of the problems uncovered are interesting
in their own&amp;nbsp;right.&lt;/p&gt;
&lt;p&gt;Firstly, there was the relatively trivial matter of &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/digest-algo-sha512/+merge/289052"&gt;using &lt;span class="caps"&gt;SHA&lt;/span&gt;-512 digests
on new
signatures&lt;/a&gt;.
This was mostly a matter of adjusting our configuration, although writing
the test was a bit tricky since
&lt;a href="https://pypi.python.org/pypi/pygpgme"&gt;PyGPGME&lt;/a&gt; isn&amp;#8217;t as helpful as it could
be.  (Simpler repository implementations that call &lt;code&gt;gpg&lt;/code&gt; from the command
line should probably just add the &lt;code&gt;--digest-algo SHA512&lt;/code&gt; option instead of
imitating&amp;nbsp;this.)&lt;/p&gt;
&lt;p&gt;After getting that in place, any change to a suite in a &lt;span class="caps"&gt;PPA&lt;/span&gt; will result in
it being re-signed with &lt;span class="caps"&gt;SHA&lt;/span&gt;-512, which is good as far as it goes, but we
also want to re-sign PPAs that haven&amp;#8217;t been modified.  Launchpad hosts more
than 50000 active PPAs, though, a significant percentage of which include
packages for sufficiently recent Ubuntu releases that we&amp;#8217;d want to re-sign
them for this.  We can&amp;#8217;t expect everyone to push new uploads, and we need to
run this through at least some part of our usual publication machinery
rather than just writing a hacky shell script to do the job (which would
have no idea which keys to sign with, to start with); but forcing full
reprocessing of all those PPAs would take a prohibitively long time, and at
the moment we need to interrupt normal &lt;span class="caps"&gt;PPA&lt;/span&gt; publication to do this kind of
work.  I therefore had to spend some quality time working out how to make
things go fast&amp;nbsp;enough.&lt;/p&gt;
&lt;p&gt;The first couple of changes
(&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/publish-distro-careful-release/+merge/289401"&gt;1&lt;/a&gt;,
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/publish-distro-disable-steps/+merge/289658"&gt;2&lt;/a&gt;)
were to add options to our publisher script to let us run just the one step
we need in &amp;#8220;careful&amp;#8221; mode: that is, forcibly re-run the &lt;code&gt;Release&lt;/code&gt; file
processing step even if it thinks nothing has changed, and entirely disable
the other steps such as generating &lt;code&gt;Packages&lt;/code&gt; and &lt;code&gt;Sources&lt;/code&gt; files.  Then
last week I finally got around to timing things on one of our staging
systems so that we could estimate how long a full run would take.  It was
taking a little over two seconds per archive, which meant that if we were to
re-sign all published PPAs then that would take more than 33 hours!
Obviously this wasn&amp;#8217;t viable; even just re-signing xenial would be
prohibitively&amp;nbsp;slow.&lt;/p&gt;
&lt;p&gt;The next question was where all that time was going.  I thought perhaps that
the actual signing might be slow for some reason, but it was taking about
half a second per archive: not great, but not enough to account for most of
the slowness.  The main part of the delay was in fact when we committed the
database transaction after processing each archive, but not in the actual
PostgreSQL commit, rather in the &lt;acronym title="object-relational
mapper"&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/acronym&gt; &lt;code&gt;invalidate&lt;/code&gt; method called to prepare for a&amp;nbsp;commit.&lt;/p&gt;
&lt;p&gt;Launchpad uses the excellent &lt;a href="https://storm.canonical.com/"&gt;Storm&lt;/a&gt; for all
of its database interactions.  One property of this &lt;span class="caps"&gt;ORM&lt;/span&gt; (and possibly of
others; I&amp;#8217;ll cheerfully admit to not having spent much time with other ORMs)
is that it uses a
&lt;a href="https://docs.python.org/2/library/weakref.html#weakref.WeakValueDictionary"&gt;WeakValueDictionary&lt;/a&gt;
to keep track of the objects it&amp;#8217;s populated with database results.  Before
it commits a transaction, it iterates over all those &amp;#8220;alive&amp;#8221; objects to note
that if they&amp;#8217;re used in future then information needs to be reloaded from
the database first.  Usually this is a very good thing: it saves us from
having to think too hard about data consistency at the application layer.
But in this case, one of the things we did at the start of the publisher
script&amp;nbsp;was:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getPPAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Find private package archives for the selected distribution.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isCareful&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;careful_publishing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_non_pending&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getAllPPAs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPendingPublicationPPAs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getTargetArchives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Find the archive(s) selected by the script&amp;#39;s options.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getArchiveByComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;partner&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ppa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_ppa_public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPPAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;private_ppa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_ppa_private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPPAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy_archive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getCopyArchives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_archive&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That innocuous-looking &lt;code&gt;filter&lt;/code&gt; means that we do all the public/private
filtering of PPAs up-front and return a list of all the PPAs we intend to
operate on.  This means that all those objects are alive as far as Storm is
concerned and need to be considered for invalidation on every commit, and
the time required for that stacks up when many thousands of objects are
involved: this is essentially &lt;a href="http://accidentallyquadratic.tumblr.com/"&gt;accidentally
quadratic&lt;/a&gt; behaviour, because all
archives are considered when committing changes to each archive in turn.
Normally this isn&amp;#8217;t too bad because only a few hundred PPAs need to be
processed in any given run; but if we&amp;#8217;re running in a mode where we&amp;#8217;re
processing all PPAs rather than just ones that are pending publication, then
suddenly this balloons to the point where it takes a couple of seconds.  The
&lt;a href="https://code.launchpad.net/~cjwatson/launchpad/publish-distro-many-ppas/+merge/289925"&gt;fix&lt;/a&gt;
is very simple, using an
&lt;a href="https://docs.python.org/2/library/stdtypes.html#typeiter"&gt;iterator&lt;/a&gt; instead
so that we don&amp;#8217;t need to keep all the objects&amp;nbsp;alive:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;itertools&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ifilter&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getTargetArchives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Find the archive(s) selected by the script&amp;#39;s options.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getArchiveByComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;partner&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ppa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ifilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_ppa_public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPPAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;private_ppa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ifilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_ppa_private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getPPAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy_archive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getCopyArchives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_archive&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that, I turned to that half a second for signing.  A good chunk of
that was accounted for by the &lt;code&gt;signContent&lt;/code&gt; method taking a fingerprint
rather than a key, despite the fact that we normally already had the key in
hand; this caused us to have to ask &lt;span class="caps"&gt;GPGME&lt;/span&gt; to reload the key, which requires
two subprocess calls.  Converting this to &lt;a href="https://code.launchpad.net/~cjwatson/launchpad/faster-gpg-operations/+merge/289950"&gt;take a key rather than a
fingerprint&lt;/a&gt;
gets the per-archive time down to about a quarter of a second on our staging
system, about eight times faster than where we&amp;nbsp;started.&lt;/p&gt;
&lt;p&gt;Using this, we&amp;#8217;ve now re-signed all xenial &lt;code&gt;Release&lt;/code&gt; files in PPAs using
&lt;span class="caps"&gt;SHA&lt;/span&gt;-512 digests.  On production, this took about 80 minutes to iterate over
around 70000 archives, of which 1761 were modified.  Most of the time
appears to have been spent skipping over unmodified archives; even a few
hundredths of a second per archive adds up quickly there.  The remaining
time comes out to around 0.4 seconds per modified archive.  There&amp;#8217;s
certainly still room for speeding this up a&amp;nbsp;bit.&lt;/p&gt;
&lt;p&gt;We wouldn&amp;#8217;t want to do this procedure every day, but it&amp;#8217;s acceptable for
occasional tasks like this.  I expect that we&amp;#8217;ll similarly re-sign wily,
vivid, and trusty &lt;code&gt;Release&lt;/code&gt; files soon in the same&amp;nbsp;way.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>SSH SHA-2 support in Twisted</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ssh-sha-2-support-in-twisted.html" rel="alternate"/><published>2015-12-02T20:42:25+00:00</published><updated>2015-12-02T20:42:25+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2015-12-02:/~cjwatson/blog/ssh-sha-2-support-in-twisted.html</id><summary type="html">&lt;p&gt;Launchpad operates a few &lt;span class="caps"&gt;SSH&lt;/span&gt; endpoints: &lt;code&gt;bazaar.launchpad.net&lt;/code&gt; and
&lt;code&gt;git.launchpad.net&lt;/code&gt; for code hosting, and &lt;code&gt;upload.ubuntu.com&lt;/code&gt; and
&lt;code&gt;ppa.launchpad.net&lt;/code&gt; for uploading packages.  None of these are
straightforward OpenSSH servers, because they don&amp;#8217;t give ordinary shell
access and they authenticate against users&amp;#8217; &lt;span class="caps"&gt;SSH&lt;/span&gt; keys recorded …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Launchpad operates a few &lt;span class="caps"&gt;SSH&lt;/span&gt; endpoints: &lt;code&gt;bazaar.launchpad.net&lt;/code&gt; and
&lt;code&gt;git.launchpad.net&lt;/code&gt; for code hosting, and &lt;code&gt;upload.ubuntu.com&lt;/code&gt; and
&lt;code&gt;ppa.launchpad.net&lt;/code&gt; for uploading packages.  None of these are
straightforward OpenSSH servers, because they don&amp;#8217;t give ordinary shell
access and they authenticate against users&amp;#8217; &lt;span class="caps"&gt;SSH&lt;/span&gt; keys recorded in Launchpad;
both of these are much easier to do with &lt;span class="caps"&gt;SSH&lt;/span&gt; server code that we can use in
library form as part of another service.  We use
&lt;a href="https://pypi.python.org/pypi/Twisted"&gt;Twisted&lt;/a&gt; for several other tasks
where we need event-based networking code, and its
&lt;a href="https://twistedmatrix.com/trac/wiki/TwistedConch"&gt;conch&lt;/a&gt; package is a good
fit for&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;Of course, this means that it&amp;#8217;s important that conch keeps up to date with
the cryptographic state of the art in other &lt;span class="caps"&gt;SSH&lt;/span&gt; implementations, and this
hasn&amp;#8217;t always been the case.  OpenSSH 7.0 &lt;a href="http://www.openssh.com/txt/release-7.0"&gt;dropped support for some old
algorithms&lt;/a&gt;, including disabling the
1024-bit &lt;code&gt;diffie-hellman-group1-sha1&lt;/code&gt; key exchange method at run-time.
Unfortunately, this also happened to be the only key exchange method that
Launchpad&amp;#8217;s &lt;span class="caps"&gt;SSH&lt;/span&gt; endpoints supported (conch supported the slightly better
&lt;code&gt;diffie-hellman-group-exchange-sha1&lt;/code&gt; method as well, but that was disabled
in Launchpad due to a missing piece of configuration).  &lt;a href="https://bugs.launchpad.net/bugs/1445619"&gt;&lt;span class="caps"&gt;SHA&lt;/span&gt;-2
support&lt;/a&gt; was clearly called for,
and the fact that we had to get this sorted out in conch first meant that
everything took a bit longer than we&amp;#8217;d&amp;nbsp;hoped.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://twistedmatrix.com/pipermail/twisted-python/2015-November/029993.html"&gt;Twisted
15.5&lt;/a&gt;,
we contributed support for several conch&amp;nbsp;improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twistedmatrix.com/trac/ticket/7717"&gt;diffie-hellman-group14-sha1 key
   exchange&lt;/a&gt; (mostly by Ian
   Moore, finished off by&amp;nbsp;me)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twistedmatrix.com/trac/ticket/7672"&gt;diffie-hellman-group-exchange-sha256 key&amp;nbsp;exchange&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twistedmatrix.com/trac/ticket/8108"&gt;hmac-sha2-256 and hmac-sha2-512&amp;nbsp;MACs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Between them and with some adjustments to the
&lt;a href="https://pypi.python.org/pypi/lazr.sshserver"&gt;lazr.sshserver&lt;/a&gt; package we use
to glue all this together to add support for &lt;span class="caps"&gt;DH&lt;/span&gt; group exchange, these are
enough to allow us not to rely on &lt;span class="caps"&gt;SHA&lt;/span&gt;-1 at all, and these improvements have
now been rolled out to all four endpoints listed above.  I&amp;#8217;ve thus also
uploaded OpenSSH 7.1 packages to Debian&amp;nbsp;unstable.&lt;/p&gt;
&lt;p&gt;If you also run a Twisted-based &lt;span class="caps"&gt;SSH&lt;/span&gt; server, upgrade it now!  Otherwise it
will be &lt;a href="http://www.openssh.com/legacy.html"&gt;harder&lt;/a&gt; for users of recent
OpenSSH client versions to use your server, and for good&amp;nbsp;reason.&lt;/p&gt;</content><category term="launchpad"/><category term="launchpad"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/><category term="twisted"/></entry><entry><title>Moving on, but not too far</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/moving-on-but-not-too-far.html" rel="alternate"/><published>2014-10-26T18:54:34-04:00</published><updated>2014-10-26T18:54:34-04:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2014-10-26:/~cjwatson/blog/moving-on-but-not-too-far.html</id><summary type="html">&lt;p&gt;The &lt;a href="http://www.ubuntu.com/about/about-ubuntu/conduct"&gt;Ubuntu Code of
Conduct&lt;/a&gt;&amp;nbsp;says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step down considerately&lt;/strong&gt;: When somebody leaves or disengages from the
project, we ask that they do so in a way that minimises disruption to the
project.  They should tell people they are leaving and take the proper
steps to ensure that others can pick …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;The &lt;a href="http://www.ubuntu.com/about/about-ubuntu/conduct"&gt;Ubuntu Code of
Conduct&lt;/a&gt;&amp;nbsp;says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step down considerately&lt;/strong&gt;: When somebody leaves or disengages from the
project, we ask that they do so in a way that minimises disruption to the
project.  They should tell people they are leaving and take the proper
steps to ensure that others can pick up where they left&amp;nbsp;off.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#8217;ve been working on Ubuntu for over ten years now, almost right from the
very start; I&amp;#8217;m Canonical&amp;#8217;s employee #17 due to working out a notice period
in my previous job, but I was one of the founding group of developers.  I
occasionally tell the story that Mark originally hired me mainly to work on
what later became Launchpad Bugs due to my experience maintaining the Debian
bug tracking system, but then not long afterwards Jeff Waugh got in touch
and said &amp;#8220;hey Colin, would you mind just sorting out some installable &lt;span class="caps"&gt;CD&lt;/span&gt;
images for us?&amp;#8221;.  This is where you imagine one of those movie time-lapse
clocks &amp;#8230;  At some point it became fairly clear that I was working on
Ubuntu, and the bug system work fell to other people.  Then, when Matt
Zimmerman could no longer manage the entire Ubuntu team in Canonical by
himself, Scott James Remnant and I stepped up to help him out.  I did that
for a couple of years, starting the Foundations team in the process.  As the
team grew I found that my interests really lay in hands-on development
rather than in management, so I switched over to being the technical lead
for Foundations, and have made my home there ever since.  Over the years
this has given me the opportunity to do all sorts of things, particularly
working on our installers and on the &lt;span class="caps"&gt;GRUB&lt;/span&gt; boot loader, leading the
development work on many of our archive maintenance tools, instituting the
+1 maintenance effort and proposed-migration, and developing the Click
package manager, and I&amp;#8217;ve had the great pleasure of working with many
exceptionally talented&amp;nbsp;people.&lt;/p&gt;
&lt;p&gt;However.  In recent months I&amp;#8217;ve been feeling a general sense of malaise and
what I&amp;#8217;ve come to recognise with hindsight as the symptoms of approaching
burnout.  I&amp;#8217;ve been working long hours for a long time, and while I can draw
on a lot of experience by now, it&amp;#8217;s been getting harder to summon the
enthusiasm and creativity to go with that.  I have a wonderful wife, amazing
children, and lovely friends, and I want to be able to spend a bit more time
with them.  After ten years doing the same kinds of things, I&amp;#8217;ve accreted
history with and responsibility for a lot of projects.  One of the things I
always loved about Foundations was that it&amp;#8217;s a broad church, covering a wide
range of software and with a correspondingly wide range of opportunities;
but, over time, this has made it difficult for me to focus on things that
are important because there are so many areas where I might be called upon
to help.  I thought about simply stepping down from the technical lead
position and remaining in the same team, but I decided that that wouldn&amp;#8217;t
make enough of a difference to what matters to me.  I need a clean break and
an opportunity to reset my habits before I burn out for&amp;nbsp;real.&lt;/p&gt;
&lt;p&gt;One of the things that has consistently held my interest through all of this
has been making sure that the infrastructure for Ubuntu keeps running
reliably and that other developers can work efficiently.  As part of this,
I&amp;#8217;ve been able to do &lt;a href="https://dev.launchpad.net/Contributions#colin_watson"&gt;a lot of
work&lt;/a&gt; over the years
on &lt;a href="https://launchpad.net/"&gt;Launchpad&lt;/a&gt; where it was a good fit with my
remit: this has included significant performance improvements to archive
publishing, moving most archive administration operations from
excessively-privileged command-line operations to the webservice, making
build cancellation reliable across the board, and moving live filesystem
building from an unscalable ad-hoc collection of machines into the Launchpad
build farm.  The Launchpad development team has generally welcomed help with
open arms, and in fact I joined the &lt;a href="https://launchpad.net/~launchpad"&gt;~launchpad
team&lt;/a&gt; last&amp;nbsp;year.&lt;/p&gt;
&lt;p&gt;So, the logical next step for me is to make this informal involvement
permanent.  As such, at the end of this year I will be moving from Ubuntu
Foundations to the Launchpad engineering&amp;nbsp;team.&lt;/p&gt;
&lt;p&gt;This doesn&amp;#8217;t mean me leaving Ubuntu.  Within Canonical, Launchpad
development is currently organised under the Continuous Integration team,
which is part of Ubuntu Engineering.  I&amp;#8217;ll still be around in more or less
the usual places and available for people to ask me questions.  But I will
in general be trying to reduce my involvement in Ubuntu proper to things
that are closely related to the operation of Launchpad, and a small number
of low-effort things that I&amp;#8217;m interested enough in to find free time for
them.  I still need to sort out a lot of details, but it&amp;#8217;ll very likely
involve me handing over project leadership of Click, drastically reducing my
involvement in the installer, and looking for at least some help with boot
loader work, among others.  I don&amp;#8217;t expect my Debian involvement to change,
and I may well find myself more motivated there now that it won&amp;#8217;t be so
closely linked with my day job, although it&amp;#8217;s possible that I will pare some
things back that I was mostly doing on Ubuntu&amp;#8217;s behalf.  If you ask me for
help with something over the next few months, expect me to be more likely to
direct you to other people or suggest ways you can help yourself out, so
that I can start disentangling myself from my current web of&amp;nbsp;projects.&lt;/p&gt;
&lt;p&gt;Please contact me sooner or later if you&amp;#8217;re interested in helping out with
any of the things I&amp;#8217;m visible in right now, and we can see what makes sense.
I&amp;#8217;m looking forward to&amp;nbsp;this!&lt;/p&gt;</content><category term="ubuntu"/><category term="launchpad"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Porting GHC: A Tale of Two Architectures</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/porting-ghc-a-tale-of-two-architectures.html" rel="alternate"/><published>2014-04-15T02:36:01+01:00</published><updated>2014-04-15T02:36:01+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2014-04-15:/~cjwatson/blog/porting-ghc-a-tale-of-two-architectures.html</id><summary type="html">&lt;p&gt;We had
&lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-discuss/2013-December/014795.html"&gt;some&lt;/a&gt;
&lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-discuss/2014-March/014907.html"&gt;requests&lt;/a&gt;
to get &lt;a href="http://www.haskell.org/ghc/"&gt;&lt;span class="caps"&gt;GHC&lt;/span&gt;&lt;/a&gt; (the Glasgow Haskell Compiler) up
and running on two new Ubuntu architectures:
&lt;acronym title="64-bit ARM, a.k.a. aarch64"&gt;arm64&lt;/acronym&gt;, added in 13.10,
and &lt;acronym title="little-endian 64-bit PowerPC"&gt;ppc64el&lt;/acronym&gt;, added
in 14.04.  This has been something of a saga, and has involved rather more
late-night hacking than is probably good for&amp;nbsp;me …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We had
&lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-discuss/2013-December/014795.html"&gt;some&lt;/a&gt;
&lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-discuss/2014-March/014907.html"&gt;requests&lt;/a&gt;
to get &lt;a href="http://www.haskell.org/ghc/"&gt;&lt;span class="caps"&gt;GHC&lt;/span&gt;&lt;/a&gt; (the Glasgow Haskell Compiler) up
and running on two new Ubuntu architectures:
&lt;acronym title="64-bit ARM, a.k.a. aarch64"&gt;arm64&lt;/acronym&gt;, added in 13.10,
and &lt;acronym title="little-endian 64-bit PowerPC"&gt;ppc64el&lt;/acronym&gt;, added
in 14.04.  This has been something of a saga, and has involved rather more
late-night hacking than is probably good for&amp;nbsp;me.&lt;/p&gt;
&lt;h2&gt;Book the First: Recalled to a life of strange build&amp;nbsp;systems&lt;/h2&gt;
&lt;p&gt;You might not know it from the sheer bulk of uploads I do sometimes, but I
actually don&amp;#8217;t speak a word of Haskell and it&amp;#8217;s not very high up my list of
things to learn.  But I am a pretty experienced build engineer, and I enjoy
porting things to new architectures: I&amp;#8217;m firmly of the belief that breadth
of architecture support is a good way to shake out certain categories of
issues in code, that it&amp;#8217;s worth doing aggressively across an entire
distribution, and that, even if you don&amp;#8217;t think you need something now, new
requirements have a habit of coming along when you least expect them and you
might as well be prepared in advance.  Furthermore, it annoys me when we
have excessive noise in our &lt;a href="http://qa.ubuntuwire.com/ftbfs/"&gt;build failure&lt;/a&gt;
and &lt;a href="https://wiki.ubuntu.com/ProposedMigration"&gt;proposed-migration&lt;/a&gt; output
and I often put bits and pieces of spare time into gardening miscellaneous
problems there, and at one point there was a lot of Haskell stuff on the
list and it got a bit annoying to have to keep sending patches rather than
just fixing things myself, and &amp;#8230; well, I ended up as probably the only
non-Haskell-programmer on the Debian Haskell team and found myself fixing
problems there in my free time.  Life is a bit weird&amp;nbsp;sometimes.&lt;/p&gt;
&lt;p&gt;Bootstrapping packages on a new architecture is a bit of a black art that
only a fairly small number of relatively bitter and twisted people know very
much about.  Doing it in Ubuntu is specifically painful because we&amp;#8217;ve always
forbidden direct binary uploads: all binaries have to come from a build
daemon.  Compilers in particular often tend to be written in the language
they compile, and it&amp;#8217;s not uncommon for them to build-depend on themselves:
that is, you need a previous version of the compiler to build the compiler,
stretching back to the dawn of time where somebody put things together with
a big magnet or something.  So how do you get started on a new architecture?
Well, what we do in this case is we construct a binary somehow (usually
involving cross-compilation) and insert it as a build-dependency for a
proper build in Launchpad.  The ability to do this is restricted to a small
group of Canonical employees, partly because it&amp;#8217;s very easy to make mistakes
and partly because things like the classic &amp;#8220;&lt;a href="http://cm.bell-labs.com/who/ken/trust.html"&gt;Reflections on Trusting
Trust&lt;/a&gt;&amp;#8221; are in the backs of our
minds somewhere.  We have an iron rule for our own sanity that the injected
build-dependencies must themselves have been built from the unmodified
source package in Ubuntu, although there can be source modifications further
back in the chain.  Fortunately, we don&amp;#8217;t need to do this very often, but it
does mean that as somebody who can do it I feel an obligation to try and
unblock other people where I&amp;nbsp;can.&lt;/p&gt;
&lt;p&gt;As far as constructing those build-dependencies goes, sometimes we look for
binaries built by other distributions (particularly Debian), and that&amp;#8217;s
pretty straightforward.  In this case, though, these two architectures are
pretty new and the Debian ports are only just getting going, and as far as I
can tell none of the other distributions with active arm64 or ppc64el ports
(or trivial name variants) has got as far as porting &lt;span class="caps"&gt;GHC&lt;/span&gt; yet.  Well, &lt;span class="caps"&gt;OK&lt;/span&gt;.
This was somewhere around the Christmas holidays and I had some time.
Muggins here cracks his knuckles and decides to have a go at bootstrapping
it from scratch.  It can&amp;#8217;t be that hard, right?  Not to mention that it was
a blocker for over 600 entries on that build failure list I mentioned, which
is definitely enough to make me sit up and take notice; we&amp;#8217;d even had the
odd customer request for&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Several attempts later and I was starting to doubt my sanity, not least for
trying in the first place.  We ship &lt;span class="caps"&gt;GHC&lt;/span&gt; 7.6, and upgrading to 7.8 is not a
project I&amp;#8217;d like to tackle until the much more experienced Haskell folks in
Debian have switched to it in unstable.  The &lt;a href="https://ghc.haskell.org/trac/ghc/wiki/Building/Porting"&gt;porting documentation for
7.6&lt;/a&gt; has bitrotted
more or less beyond usability, and the &lt;a href="https://ghc.haskell.org/trac/ghc/wiki/CrossCompilation"&gt;corresponding documentation for
7.8&lt;/a&gt; really isn&amp;#8217;t
backportable to 7.6.  I tried building 7.8 for ppc64el anyway, picking that
on the basis that we had quicker hardware for it and didn&amp;#8217;t seem likely to
be particularly more arduous than arm64 (ho ho), and I even got to the point
of having a cross-built stage2 compiler (stage1, in the cross-building case,
is a &lt;span class="caps"&gt;GHC&lt;/span&gt; binary that runs on your starting architecture and generates code
for your target architecture) that I could copy over to a ppc64el box and
try to use as the base for a fully-native build, but it segfaulted
incomprehensibly just after spawning any child process.  Compilers tend to
do rather a lot, especially when they&amp;#8217;re built to use &lt;span class="caps"&gt;GCC&lt;/span&gt; to generate object
code, so this was a pretty serious problem, and it resisted analysis.  I
poked at it for a while but didn&amp;#8217;t get anywhere, and I had other things to
do so declared it a write-off and gave&amp;nbsp;up.&lt;/p&gt;
&lt;h2&gt;Book the Second: The golden thread of&amp;nbsp;progress&lt;/h2&gt;
&lt;p&gt;In March, another mailing list conversation prodded me into finding a &lt;a href="https://ghcarm.wordpress.com/2014/01/18/unregisterised-ghc-head-build-for-arm64-platform/"&gt;blog
entry by Karel
Gardas&lt;/a&gt;
on building &lt;span class="caps"&gt;GHC&lt;/span&gt; for arm64.  This was enough to be worth another look, and
indeed it turned out that (with some help from Karel in private mail) I was
able to cross-build a compiler that actually worked and could be used to run
a fully-native build that also worked.  Of course this was 7.8, since as I
mentioned cross-building 7.6 is unrealistically difficult unless you&amp;#8217;re
considerably more of an expert on &lt;span class="caps"&gt;GHC&lt;/span&gt;&amp;#8217;s labyrinthine build system than I am.
&lt;span class="caps"&gt;OK&lt;/span&gt;, no problem, right?  Getting a &lt;span class="caps"&gt;GHC&lt;/span&gt; at all is the hard bit, and 7.8 must
be at least as capable as 7.6, so it should be able to build 7.6 easily
enough&amp;nbsp;&amp;#8230;&lt;/p&gt;
&lt;p&gt;Not so much.  What I&amp;#8217;d missed here was that compiler engineers generally
only care very much about building the compiler with &lt;em&gt;older&lt;/em&gt; versions of
itself, and if the language in question has any kind of deprecation cycle
then the compiler itself is likely to be behind on various things compared
to more typical code since it has to be buildable with older versions.  This
means that the removal of some deprecated interfaces from 7.8 posed a
problem, as did some changes in certain &lt;acronym title="primitive
operations"&gt;primops&lt;/acronym&gt; that had gained an associated compatibility
layer in 7.8 but nobody had gone back to put the corresponding compatibility
layer into 7.6.  &lt;span class="caps"&gt;GHC&lt;/span&gt; supports running Haskell code through the C
preprocessor, and there&amp;#8217;s a &lt;code&gt;__GLASGOW_HASKELL__&lt;/code&gt; definition with the
compiler&amp;#8217;s version number, so this was just a slog tracking down changes in
git and adding &lt;code&gt;#ifdef&lt;/code&gt;-guarded code that coped with the newer compiler
(remembering that stage1 will be built with 7.8 and stage2 with stage1, i.e.
7.6, from the same source tree).  More inscrutably, &lt;span class="caps"&gt;GHC&lt;/span&gt; has its own
packaging system called Cabal which is also used by the compiler build
process to determine which subpackages to build and how to link them against
each other, and some crucial subpackages weren&amp;#8217;t being built: it looked like
it was stuck on picking versions from &amp;#8220;stage0&amp;#8221; (i.e. the initial compiler
used as an input to the whole process) when it should have been building its
own.  Eventually I figured out that this was because &lt;span class="caps"&gt;GHC&lt;/span&gt;&amp;#8217;s use of its
packaging system hadn&amp;#8217;t anticipated this case, and was selecting the higher
version of the &lt;code&gt;ghc&lt;/code&gt; package itself from stage0 rather than the version it
was about to build for itself, and thus never actually tried to build most
of the compiler.  Editing &lt;code&gt;ghc_stage1_DEPS&lt;/code&gt; in &lt;code&gt;ghc/stage1/package-data.mk&lt;/code&gt;
after its initial generation sorted this out.  One late night building round
and round in circles for a while until I had something stable, and a Debian
source upload to add basic support for the architecture name (and other
changes which were a bit over the top in retrospect: I didn&amp;#8217;t need to touch
the embedded copy of libffi, as we build with the system one), and I was
able to feed this all into Launchpad and watch the builders munch away very
satisfyingly at the Haskell library stack for a&amp;nbsp;while.&lt;/p&gt;
&lt;p&gt;This was all interesting, and finally all that work was actually paying off
in terms of getting to watch a slew of several hundred build failures vanish
from arm64 (the final count was something like 640, I think).  The fly in
the ointment was that ppc64el was still blocked, as the problem there wasn&amp;#8217;t
building 7.6, it was getting a working 7.8.  But now I really did have other
much more urgent things to do, so I figured I just wouldn&amp;#8217;t get to this by
release time and stuck it on the figurative&amp;nbsp;shelf.&lt;/p&gt;
&lt;h2&gt;Book the Third: The track of a&amp;nbsp;bug&lt;/h2&gt;
&lt;p&gt;Then, last Friday, I cleared out my urgent pile and thought I&amp;#8217;d have another
quick look.  (I get a bit obsessive about things like this that smell of
&amp;#8220;interesting intellectual puzzle&amp;#8221;.)  slyfox on the #ghc &lt;span class="caps"&gt;IRC&lt;/span&gt; channel gave me
some general debugging advice and, particularly usefully, a reduced example
program that I could use to debug just the process-spawning problem without
having to wade through noise from running the rest of the compiler.  I
reproduced the same problem there, and then found that the program crashed
earlier (in &lt;code&gt;stg_ap_0_fast&lt;/code&gt;, part of the run-time system) if I compiled it
with &lt;code&gt;+RTS -Da -RTS&lt;/code&gt;.  I nailed it down to a small enough region of assembly
that I could see all of the assembly, the source code, and an intermediate
representation or two from the compiler, and then started meditating on what
makes ppc64el&amp;nbsp;special.&lt;/p&gt;
&lt;p&gt;You see, the vast majority of porting bugs come down to what I might call
gross properties of the architecture.  You have things like whether it&amp;#8217;s
32-bit or 64-bit, big-endian or little-endian, whether &lt;code&gt;char&lt;/code&gt; is signed or
unsigned, that sort of thing.  There&amp;#8217;s a &lt;a href="https://wiki.debian.org/ArchitectureSpecificsMemo"&gt;big
table&lt;/a&gt; on the Debian wiki
that handily summarises most of the important ones.  Sometimes you have to
deal with distribution-specific things like whether &lt;span class="caps"&gt;GL&lt;/span&gt; or &lt;span class="caps"&gt;GLES&lt;/span&gt; is used;
often, especially for new variants of existing architectures, you have to
cope with foolish configure scripts that think they can guess certain things
from the architecture name and get it wrong (assuming that &lt;code&gt;powerpc*&lt;/code&gt; means
big-endian, for instance).  We often have to update &lt;code&gt;config.guess&lt;/code&gt; and
&lt;code&gt;config.sub&lt;/code&gt;, and on ppc64el we have the additional hassle of updating
libtool macros too.  But I&amp;#8217;ve done a lot of this stuff and I&amp;#8217;d accounted for
everything I could think of.  ppc64el is actually a lot like amd64 in terms
of many of these porting-relevant properties, and not even that far off
arm64 which I&amp;#8217;d just successfully ported &lt;span class="caps"&gt;GHC&lt;/span&gt; to, so I couldn&amp;#8217;t be dealing
with anything particularly obvious.  There was some hand-written assembly
which certainly could have been problematic, but I&amp;#8217;d carefully checked that
this wasn&amp;#8217;t being used by the &amp;#8220;unregisterised&amp;#8221; (no specialised machine
dependencies, so relatively easy to port but not well-optimised) build I was
using.  A problem around spawning processes suggested a problem with
&lt;code&gt;SIGCHLD&lt;/code&gt; handling, but I ruled that out by slowing down the first child
process that it spawned and using &lt;code&gt;strace&lt;/code&gt; to confirm that &lt;code&gt;SIGSEGV&lt;/code&gt; was the
first signal received.  What on earth was the&amp;nbsp;problem?&lt;/p&gt;
&lt;p&gt;From some painstaking gdb work, one thing I eventually noticed was that
&lt;code&gt;stg_ap_0_fast&lt;/code&gt;&lt;span class="quo"&gt;&amp;#8216;&lt;/span&gt;s local stack appeared to be being corrupted by a function
call, specifically a call to the colourfully-named &lt;code&gt;debugBelch&lt;/code&gt;.  Now, when
&lt;span class="caps"&gt;IBM&lt;/span&gt;&amp;#8217;s toolchain engineers were putting together ppc64el based on ppc64, they
took the opportunity to fix a number of problems with their &lt;span class="caps"&gt;ABI&lt;/span&gt;: there&amp;#8217;s an
&lt;a href="https://bugs.openjdk.java.net/browse/JDK-8035647"&gt;OpenJDK bug&lt;/a&gt; with a handy
list of references.  One of the things I noticed there was that there were
some &lt;a href="http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01149.html"&gt;stack allocation
optimisations&lt;/a&gt; in
the new &lt;span class="caps"&gt;ABI&lt;/span&gt;, which affected functions that don&amp;#8217;t call any vararg functions
and don&amp;#8217;t call any functions that take enough parameters that some of them
have to be passed on the stack rather than in registers.  &lt;code&gt;debugBelch&lt;/code&gt; takes
varargs: hmm.  Now, the calling code isn&amp;#8217;t quite in C as such, but in a
related dialect called &amp;#8220;Cmm&amp;#8221;, a variant of C&amp;#8212; (yes, minus), that &lt;span class="caps"&gt;GHC&lt;/span&gt; uses
to help bridge the gap between the functional world and its code generation,
and which is compiled down to C by &lt;span class="caps"&gt;GHC&lt;/span&gt;.  When importing C functions into
Cmm, &lt;span class="caps"&gt;GHC&lt;/span&gt; generates prototypes for them, but it doesn&amp;#8217;t do enough parsing to
work out the true prototype; instead, they all just get something like
&lt;code&gt;extern StgFunPtr f(void);&lt;/code&gt;.  In most architectures you can get away with
this, because the arguments get passed in the usual calling convention
anyway and it all works out, but on ppc64el this means that the caller
doesn&amp;#8217;t generate enough stack space and then the callee tries to save its
varargs onto the stack in an area that in fact belongs to the caller, and
suddenly everything goes south.  Things were starting to make&amp;nbsp;sense.&lt;/p&gt;
&lt;p&gt;Now, &lt;code&gt;debugBelch&lt;/code&gt; is only used in optional debugging code; but
&lt;code&gt;runInteractiveProcess&lt;/code&gt; (the function associated with the initial round of
failures) takes no fewer than twelve arguments, plenty to force some of them
onto the stack.  I poked around the &lt;span class="caps"&gt;GCC&lt;/span&gt; patch for this &lt;span class="caps"&gt;ABI&lt;/span&gt; change a bit and
determined that it only optimised away the stack allocation if it had a full
prototype for all the callees, so I guessed that changing those prototypes
to &lt;code&gt;extern StgFunPtr f();&lt;/code&gt; might work: it&amp;#8217;s still technically wrong, not
least because omitting the parameter list is an obsolescent feature in C11,
but it&amp;#8217;s at least just omitting information about the parameter list rather
than actively lying about it.  I tweaked that and ran the cross-build from
scratch again.  Lo and behold, suddenly I had a working compiler, and I
could go through the same build-7.6-using-7.8 procedure as with arm64, much
more quickly this time now that I knew what I was doing.  One &lt;a href="https://ghc.haskell.org/trac/ghc/ticket/8965"&gt;upstream
bug&lt;/a&gt;, one Debian upload, and
several bootstrapping builds later, and &lt;span class="caps"&gt;GHC&lt;/span&gt; was up and running on another
architecture in Launchpad.&amp;nbsp;Success!&lt;/p&gt;
&lt;h2&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;There&amp;#8217;s still more to do.  I gather there may be a Google Summer of Code
project in Linaro to write proper native code generation for &lt;span class="caps"&gt;GHC&lt;/span&gt; on arm64:
this would make things a good deal faster, but also enable GHCi (the
interpreter) and Template Haskell, and thus clear quite a few more build
failures.  Since there&amp;#8217;s already native code generation for ppc64 in &lt;span class="caps"&gt;GHC&lt;/span&gt;,
getting it going for ppc64el would probably only be a couple of days&amp;#8217; work
at this point.  But these are niceties by comparison, and I&amp;#8217;m more than
happy with what I got working for&amp;nbsp;14.04.&lt;/p&gt;
&lt;p&gt;The upshot of all of this is that I may be the first non-Haskell-programmer
to ever port &lt;span class="caps"&gt;GHC&lt;/span&gt; to two entirely new architectures.  I&amp;#8217;m not sure if I gain
much from that personally aside from a lot of lost sleep and being
considered extremely strange.  It has, however, been by far the most
challenging set of packages I&amp;#8217;ve ported, and a fascinating trip through some
odd corners of build systems and undefined behaviour that I don&amp;#8217;t normally
need to&amp;nbsp;touch.&lt;/p&gt;</content><category term="misc"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Testing wanted: GRUB 2.02~beta2 Debian/Ubuntu packages</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/testing-wanted-grub-2.02-beta2.html" rel="alternate"/><published>2014-01-18T01:46:55+00:00</published><updated>2014-01-18T01:46:55+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2014-01-18:/~cjwatson/blog/testing-wanted-grub-2.02-beta2.html</id><summary type="html">&lt;p&gt;This is mostly a repost of my &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel/2014-January/037978.html"&gt;ubuntu-devel
mail&lt;/a&gt;
for a wider audience, but see below for some&amp;nbsp;additions.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d like to upgrade to &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2.02 for Ubuntu 14.04; it&amp;#8217;s currently in beta.
This represents a year and a half of upstream development, and contains many …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is mostly a repost of my &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel/2014-January/037978.html"&gt;ubuntu-devel
mail&lt;/a&gt;
for a wider audience, but see below for some&amp;nbsp;additions.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d like to upgrade to &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2.02 for Ubuntu 14.04; it&amp;#8217;s currently in beta.
This represents a year and a half of upstream development, and contains many
new features, which you can see in the
&lt;a href="http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=NEWS"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;&amp;nbsp;file.&lt;/p&gt;
&lt;p&gt;Obviously I want to be very careful with substantial upgrades to the default
boot loader.  So, I&amp;#8217;ve put this in trusty-proposed, and filed a &lt;a href="https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1269992"&gt;blocking
bug&lt;/a&gt; to ensure
that it doesn&amp;#8217;t reach trusty proper until it&amp;#8217;s had a reasonable amount of
manual testing.  If you are already using trusty and have some time to try
this out, it would be very helpful to me.  I suggest that you only attempt
this if you&amp;#8217;re comfortable driving &lt;code&gt;apt-get&lt;/code&gt; directly and recovering from
errors at that level, and if you&amp;#8217;re willing to spend time working with me on
narrowing down any problems that&amp;nbsp;arise.&lt;/p&gt;
&lt;p&gt;Please ensure that you have rescue media to hand before starting testing.
The simplest way to upgrade is to enable trusty-proposed, upgrade &lt;span class="caps"&gt;ONLY&lt;/span&gt;
packages whose names start with &amp;#8220;grub&amp;#8221; (e.g. use &lt;code&gt;apt-get dist-upgrade&lt;/code&gt; to
show the full list, say no to the upgrade, and then pass all the relevant
package names to &lt;code&gt;apt-get install&lt;/code&gt;), and then (very important!) disable
trusty-proposed again.  Provided that there were no errors in this process,
you should be safe to reboot.  If there were errors, you should be able to
downgrade back to 2.00-22 (or 1.27+2.00-22 in the case of&amp;nbsp;grub-efi-amd64-signed).&lt;/p&gt;
&lt;p&gt;Please report your experiences (positive and negative) with this upgrade in
the &lt;a href="https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1269992"&gt;tracking
bug&lt;/a&gt;.  I&amp;#8217;m
particularly interested in systems that are complex in any way: &lt;span class="caps"&gt;UEFI&lt;/span&gt; Secure
Boot, non-trivial disk setups, manual configuration, that kind of thing.  If
any of the problems you see are also ones you saw with earlier versions of
&lt;span class="caps"&gt;GRUB&lt;/span&gt;, please identify those clearly, as I want to prioritise handling
regressions over anything else.  I&amp;#8217;ve assigned myself to that bug to ensure
that messages to it are filtered directly into my&amp;nbsp;inbox.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll add a couple of things that weren&amp;#8217;t in my ubuntu-devel mail.  Firstly,
this is all in Debian experimental as well (I do all the work in Debian and
sync it across, so the grub2 source package in Ubuntu is a verbatim copy of
the one in Debian these days).  There are some configuration differences
applied at build time, but a large fraction of test cases will apply equally
well to both.  I don&amp;#8217;t have a definite schedule for pushing this into jessie
yet - I only just finished getting 2.00 in place there, and the release
schedule gives me a bit more time - but I certainly want to ship jessie with
2.02 or newer, and any test feedback would be welcome.  It&amp;#8217;s probably best
to just e-mail feedback to me directly for now, or to the pkg-grub-devel&amp;nbsp;list.&lt;/p&gt;
&lt;p&gt;Secondly, a couple of news sites have picked this up and run it as
&amp;#8220;Canonical intends to ship Ubuntu 14.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; with a beta version of &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;#8221;.
This isn&amp;#8217;t in fact my intent at all.  I&amp;#8217;m doing this now because I think
&lt;span class="caps"&gt;GRUB&lt;/span&gt; 2.02 will be ready in non-beta form in time for Ubuntu 14.04, and
indeed that putting it in our development release will help to stabilise it;
I&amp;#8217;m an upstream &lt;span class="caps"&gt;GRUB&lt;/span&gt; developer too and I find the exposure of widely-used
packages very helpful in that context.  It will certainly be much easier to
upgrade to a beta now and a final release later than it would be to try to
jump from 2.00 to 2.02 in a month or two&amp;#8217;s&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;Even if there&amp;#8217;s some unforeseen delay and 2.02 isn&amp;#8217;t released in time,
though, I think nearly three months of stabilisation is still plenty to
yield a boot loader that I&amp;#8217;m comfortable with shipping in an &lt;span class="caps"&gt;LTS&lt;/span&gt;.  I&amp;#8217;ve been
backporting a lot of changes to 2.00 and even 1.99, and, as ever for an
actively-developed codebase, it gets harder and harder over time (in
particular, I&amp;#8217;ve spent longer than I&amp;#8217;d like hunting down and backporting
fixes for non-512-byte sector disks).  While I can still manage it, I don&amp;#8217;t
want to be supporting 2.00 for five more years after upstream has moved on;
I don&amp;#8217;t think that would be in anyone&amp;#8217;s best interests.  And I definitely
want some of the new features which aren&amp;#8217;t sensibly backportable, such as
several of the new platforms (&lt;span class="caps"&gt;ARM&lt;/span&gt;, &lt;span class="caps"&gt;ARM64&lt;/span&gt;, Xen) and various networking
improvements; I can imagine a number of our users being interested in things
like optional signature verification of files &lt;span class="caps"&gt;GRUB&lt;/span&gt; reads from disk, improved
Mac support, and the TrueCrypt &lt;span class="caps"&gt;ISO&lt;/span&gt; loader, just to name a few.  This should
be a much stronger base for five-year&amp;nbsp;support.&lt;/p&gt;</content><category term="grub"/><category term="grub"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Automatic installability checking</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/automatic-installability-checking.html" rel="alternate"/><published>2012-10-26T10:18:26+01:00</published><updated>2012-10-26T10:20:07+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2012-10-26:/~cjwatson/blog/automatic-installability-checking.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve just finished deploying automatic installability checking for Ubuntu&amp;#8217;s
development release, which is more or less equivalent to the way that
uploads are promoted from Debian unstable to testing.  See &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel/2012-October/036043.html"&gt;my ubuntu-devel
post&lt;/a&gt;
and &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-announce/2012-October/000989.html"&gt;my ubuntu-devel-announce
post&lt;/a&gt;
for details.  This now means that we&amp;#8217;ll be opening the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve just finished deploying automatic installability checking for Ubuntu&amp;#8217;s
development release, which is more or less equivalent to the way that
uploads are promoted from Debian unstable to testing.  See &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel/2012-October/036043.html"&gt;my ubuntu-devel
post&lt;/a&gt;
and &lt;a href="https://lists.ubuntu.com/archives/ubuntu-devel-announce/2012-October/000989.html"&gt;my ubuntu-devel-announce
post&lt;/a&gt;
for details.  This now means that we&amp;#8217;ll be opening the archive for general
development once glibc 2.16 packages are&amp;nbsp;ready.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m very excited about this because it&amp;#8217;s something I&amp;#8217;ve wanted to do for a
long, long time.  In fact, back in 2004 when I had my very first telephone
conversation with a certain spaceman about this crazy Debian-based project
he wanted me to work on, I remember talking about Debian&amp;#8217;s testing migration
system and some ways I thought it could be improved.  I don&amp;#8217;t remember the
details of that conversation any more and what I just deployed may well bear
very little resemblance to it, but it should transform the extent to which
our development release is continuously&amp;nbsp;usable.&lt;/p&gt;
&lt;p&gt;The next step is to hook in &lt;a href="http://dep.debian.net/deps/dep8/"&gt;autopkgtest&lt;/a&gt;
results.  This will allow us to do a degree of automatic testing of
reverse-dependencies when we upgrade low-level&amp;nbsp;libraries.&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>OpenSSH 6.0p1</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/openssh-6.0p1.html" rel="alternate"/><published>2012-05-27T20:12:12+01:00</published><updated>2012-05-27T20:12:12+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2012-05-27:/~cjwatson/blog/openssh-6.0p1.html</id><summary type="html">&lt;p&gt;OpenSSH 6.0p1 was &lt;a href="http://www.openssh.com/txt/release-6.0"&gt;released&lt;/a&gt; a
little while back; this weekend I belatedly got round to uploading packages
of it to Debian unstable and Ubuntu&amp;nbsp;quantal.&lt;/p&gt;
&lt;p&gt;I was a bit delayed by needing to put together an &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=2011"&gt;improvement to privsep
sandbox selection&lt;/a&gt; that
particularly matters in the context of distributions …&lt;/p&gt;</summary><content type="html">&lt;p&gt;OpenSSH 6.0p1 was &lt;a href="http://www.openssh.com/txt/release-6.0"&gt;released&lt;/a&gt; a
little while back; this weekend I belatedly got round to uploading packages
of it to Debian unstable and Ubuntu&amp;nbsp;quantal.&lt;/p&gt;
&lt;p&gt;I was a bit delayed by needing to put together an &lt;a href="https://bugzilla.mindrot.org/show_bug.cgi?id=2011"&gt;improvement to privsep
sandbox selection&lt;/a&gt; that
particularly matters in the context of distributions.  One of the experts on
&lt;code&gt;seccomp_filter&lt;/code&gt; has commented favourably on it, but I haven&amp;#8217;t yet had a
comment from upstream themselves, so I may need to refine this depending on
what they&amp;nbsp;say.&lt;/p&gt;
&lt;p&gt;(This is a good example of how it matters that software is often not built
on the system that it&amp;#8217;s going to run on, and in particular that the kernel
version is rather likely to be different.  Where possible it&amp;#8217;s always best
to detect kernel capabilities at run-time rather than at&amp;nbsp;build-time.)&lt;/p&gt;
&lt;p&gt;I didn&amp;#8217;t make it very clear in the changelog, but using the new
&lt;code&gt;seccomp_filter&lt;/code&gt; sandbox currently requires &lt;code&gt;UsePrivilegeSeparation sandbox&lt;/code&gt;
in &lt;code&gt;sshd_config&lt;/code&gt; as well as a capable kernel.  I won&amp;#8217;t change the default
here in advance of upstream, who still consider privsep sandboxing&amp;nbsp;experimental.&lt;/p&gt;</content><category term="misc"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>libpipeline 1.2.1 released</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/libpipeline-1.2.1-released.html" rel="alternate"/><published>2012-03-02T21:49:10+00:00</published><updated>2012-03-02T21:49:10+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2012-03-02:/~cjwatson/blog/libpipeline-1.2.1-released.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline 1.2.1&lt;/a&gt;, and
uploaded it to Debian unstable.  This is a bug-fix&amp;nbsp;release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retry reads and writes on &lt;code&gt;EINTR&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fix opening of output files requested by &lt;code&gt;pipeline_want_outfile&lt;/code&gt;; these
   are now created if they do not already exist, and truncated if they&amp;nbsp;do.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;pipeline.h&amp;gt;&lt;/code&gt; is …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline 1.2.1&lt;/a&gt;, and
uploaded it to Debian unstable.  This is a bug-fix&amp;nbsp;release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retry reads and writes on &lt;code&gt;EINTR&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fix opening of output files requested by &lt;code&gt;pipeline_want_outfile&lt;/code&gt;; these
   are now created if they do not already exist, and truncated if they&amp;nbsp;do.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;pipeline.h&amp;gt;&lt;/code&gt; is now wrapped in &lt;code&gt;extern "C"&lt;/code&gt; when used in a C++
   compilation&amp;nbsp;unit.&lt;/li&gt;
&lt;/ul&gt;</content><category term="libpipeline"/><category term="libpipeline"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>APT resolver bugs</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/apt-resolver-bugs.html" rel="alternate"/><published>2012-01-30T10:54:25+00:00</published><updated>2012-01-30T10:54:25+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2012-01-30:/~cjwatson/blog/apt-resolver-bugs.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve managed to go for eleven years working on Debian and nearly eight on
Ubuntu without ever needing to teach myself how &lt;span class="caps"&gt;APT&lt;/span&gt;&amp;#8217;s resolver works.  I get
the impression that there&amp;#8217;s a certain mystique about it in general
(alternatively, I&amp;#8217;m just the last person to figure …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve managed to go for eleven years working on Debian and nearly eight on
Ubuntu without ever needing to teach myself how &lt;span class="caps"&gt;APT&lt;/span&gt;&amp;#8217;s resolver works.  I get
the impression that there&amp;#8217;s a certain mystique about it in general
(alternatively, I&amp;#8217;m just the last person to figure this out).  Recently,
though, I had a couple of Ubuntu upgrade bugs to fix that turned out to be
bugs in the resolver, and I thought it might be interesting to walk through
the process of fixing them based on the &lt;code&gt;Debug::pkgProblemResolver=true&lt;/code&gt; log&amp;nbsp;files.&lt;/p&gt;
&lt;h2&gt;Breakage with&amp;nbsp;Breaks&lt;/h2&gt;
&lt;p&gt;The first was &lt;a href="https://bugs.launchpad.net/bugs/922485"&gt;Ubuntu bug #922485&lt;/a&gt;
(&lt;a href="https://launchpadlibrarian.net/91187038/apt.log"&gt;apt.log&lt;/a&gt;).  To understand
the log, you first need to know that &lt;span class="caps"&gt;APT&lt;/span&gt; makes up to ten passes of the
resolver to attempt to fix broken dependencies by upgrading, removing, or
holding back packages; if there are still broken packages after this point,
it&amp;#8217;s generally because it&amp;#8217;s got itself stuck in some kind of loop, and it
bails out rather than carrying on forever.  The current pass number is shown
in each &amp;#8220;Investigating&amp;#8221; log entry, so they start with &amp;#8220;Investigating (0)&amp;#8221;
and carry on up to at most &amp;#8220;Investigating (9)&amp;#8221;.  Any packages that you see
still being investigated on the tenth pass are probably something to do with
whatever&amp;#8217;s going&amp;nbsp;wrong.&lt;/p&gt;
&lt;p&gt;In this case, most packages have been resolved by the end of the fourth
pass, but &lt;code&gt;xserver-xorg-core&lt;/code&gt; is causing some trouble.  (Not a particular
surprise, as it&amp;#8217;s an important package with lots of relationships.)  We can
see that each breakage&amp;nbsp;is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Broken xserver-xorg-core:i386 Breaks on xserver-xorg-video-6 [ i386 ] &amp;lt; none &amp;gt; ( none )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a
&lt;a href="http://www.debian.org/doc/debian-policy/ch-relationships.html#s-breaks"&gt;&lt;code&gt;Breaks&lt;/code&gt;&lt;/a&gt;
(a relatively new package relationship type introduced a few years ago as a
sort of weaker form of &lt;code&gt;Conflicts&lt;/code&gt;) on a virtual package, which means that
in order to unpack &lt;code&gt;xserver-xorg-core&lt;/code&gt; each package that provides
&lt;code&gt;xserver-xorg-video-6&lt;/code&gt; must be deconfigured.  Much like &lt;code&gt;Conflicts&lt;/code&gt;, &lt;span class="caps"&gt;APT&lt;/span&gt;
responds to this by upgrading providing packages to versions that don&amp;#8217;t
provide the offending virtual package if it can, and otherwise removing
them.  We can see it doing just that in the log (some lines&amp;nbsp;omitted):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.7.6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.11.3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Fixing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tseng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.7.6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.11.3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Fixing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i740&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.7.6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1.11.3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Fixing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xorg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nv&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;span class="caps"&gt;OK&lt;/span&gt;, so that makes sense - presumably upgrading those packages didn&amp;#8217;t help at
the time.  But look at the pass numbers.  Rather than just fixing all the
packages that provide &lt;code&gt;xserver-xorg-video-6&lt;/code&gt; in a single pass, which it
would be perfectly able to do, it only fixes one per pass.  This means that
if a package &lt;code&gt;Breaks&lt;/code&gt; a virtual package which is provided by more than ten
installed packages, the resolver will fail to handle that situation.  On
inspection of the code, this was being handled correctly for &lt;code&gt;Conflicts&lt;/code&gt; by
carrying on through the list of possible targets for the dependency relation
in that case, but apparently when &lt;code&gt;Breaks&lt;/code&gt; support was implemented in &lt;span class="caps"&gt;APT&lt;/span&gt;
this case was overlooked.  The fix is to carry on through the list of
possible targets for any &amp;#8220;negative&amp;#8221; dependency relation, not just
&lt;code&gt;Conflicts&lt;/code&gt;, and I&amp;#8217;ve filed a patch as &lt;a href="http://bugs.debian.org/657695"&gt;Debian
bug #657695&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;My cup&amp;nbsp;overfloweth&lt;/h2&gt;
&lt;p&gt;The second bug I looked at was &lt;a href="https://bugs.launchpad.net/bugs/917173"&gt;Ubuntu
bug #917173&lt;/a&gt;
(&lt;a href="https://launchpadlibrarian.net/90202820/apt.log"&gt;apt.log&lt;/a&gt;).  Just as in
the previous case, we can see the resolver &amp;#8220;running out of time&amp;#8221; by reaching
the end of the tenth pass with some dependencies still broken.  This one is
a lot less obvious, though.  The last few entries clearly indicate that the
resolver is stuck in a&amp;nbsp;loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Breaks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7205&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Upgrading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Breaks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Holding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Back&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Breaks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7205&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Upgrading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Breaks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.15.5.6&lt;/span&gt;&lt;span class="n"&gt;ubuntu4&lt;/span&gt;&lt;span class="mf"&gt;.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Holding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Back&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The new version of &lt;code&gt;dpkg&lt;/code&gt; requires upgrading &lt;code&gt;dpkg-dev&lt;/code&gt;, but it can&amp;#8217;t
because of something wrong with &lt;code&gt;libdpkg-perl&lt;/code&gt;.  Following the breadcrumb
trail back through the log, we&amp;nbsp;find:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.16.1.2&lt;/span&gt;&lt;span class="n"&gt;ubuntu5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.10.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="mf"&gt;.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.14.2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6u&lt;/span&gt;&lt;span class="n"&gt;buntu1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1472&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Holding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Back&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libdpkg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;

&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.10.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="mf"&gt;.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.14.2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6u&lt;/span&gt;&lt;span class="n"&gt;buntu1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.10.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="mf"&gt;.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.14.2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6u&lt;/span&gt;&lt;span class="n"&gt;buntu1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.14.2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6u&lt;/span&gt;&lt;span class="n"&gt;buntu1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5806&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1472&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;

&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.10.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="mf"&gt;.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.14.2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6u&lt;/span&gt;&lt;span class="n"&gt;buntu1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PreDepends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.11.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.13&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;24u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;17473&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;perl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5806&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;

&lt;span class="n"&gt;Investigating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.11.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.13&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;24u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Broken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.11.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.13&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;24u&lt;/span&gt;&lt;span class="n"&gt;buntu2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.11.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0u&lt;/span&gt;&lt;span class="n"&gt;buntu7&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Considering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10358&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;17473&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rather&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i386&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So ultimately the problem is something to do with libc6; but what?  &lt;a href="https://bugs.launchpad.net/ubuntu/+source/apt/+bug/917173/comments/10"&gt;As
Steve Langasek said in the
bug&lt;/a&gt;,
libc6&amp;#8217;s dependencies have been very carefully structured, and surely we
would have seen some hint of it elsewhere if they were wrong.  At this point
ideally I wanted to break out &lt;span class="caps"&gt;GDB&lt;/span&gt; or at the very least experiment a bit with
&lt;code&gt;apt-get&lt;/code&gt;, but due to some tedious local problems I hadn&amp;#8217;t been able to
restore the &lt;code&gt;apt-clone&lt;/code&gt; state file for this bug onto my system so that I
could attack it directly.  So I fell back on the last refuge of the
frustrated debugger and sat and thought about it for a&amp;nbsp;bit.&lt;/p&gt;
&lt;p&gt;Eventually I noticed something.  The numbers after the package names in the
third line of each of these log entries are &amp;#8220;scores&amp;#8221;: roughly, the more
important a package is, the higher its score should be.  The function that
calculates these is &lt;code&gt;pkgProblemResolver::MakeScores()&lt;/code&gt; in
&lt;a href="http://anonscm.debian.org/cgit/apt/apt.git/tree/apt-pkg/algorithms.cc?id=f23e1e940214c7abbf87c28bc71a5d37d117aa57"&gt;apt-pkg/algorithms.cc&lt;/a&gt;.
Reading this, I noticed that the various values added up to make each score
are almost all provably positive, for&amp;nbsp;example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OldScores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParentPkg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only exceptions are an initial -1 or -2 points for &lt;code&gt;Priority: optional&lt;/code&gt;
or &lt;code&gt;Priority: extra&lt;/code&gt; packages respectively, or some values that could
theoretically be configured to be negative but weren&amp;#8217;t in this case.  &lt;span class="caps"&gt;OK&lt;/span&gt;.
So how come &lt;code&gt;libc6&lt;/code&gt; has such a huge negative score of -17473, when one would
normally expect it to be an extremely powerful package with a large positive&amp;nbsp;score?&lt;/p&gt;
&lt;p&gt;Oh.  This is computer programming, not mathematics &amp;#8230; and each score is
stored in a &lt;code&gt;signed short&lt;/code&gt;, so in a sufficiently large upgrade all those
bonus points add up to something larger than 32767 and everything goes
haywire.  Bingo.  Make it an &lt;code&gt;int&lt;/code&gt; instead - the number of installed
packages is going to be on the order of tens of thousands at most, so it&amp;#8217;s
not as though it&amp;#8217;ll make a substantial difference to the amount of memory
used - and chances are everything will be fine.  I&amp;#8217;ve filed a patch as
&lt;a href="http://bugs.debian.org/657732"&gt;Debian bug #657732&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d expected this to be a pretty challenging pair of bugs.  While I
certainly haven&amp;#8217;t lost any respect for the &lt;span class="caps"&gt;APT&lt;/span&gt; maintainers for dealing with
this stuff regularly, it wasn&amp;#8217;t as bad as I thought.  I&amp;#8217;d expected to have
to figure out how to retune some slightly out-of-balance heuristics and not
really know whether I&amp;#8217;d broken anything else in the process; but in the end
both patches were very&amp;nbsp;straightforward.&lt;/p&gt;</content><category term="ubuntu"/><category term="apt"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Quality in Ubuntu 12.04 LTS</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/quality-in-12-04.html" rel="alternate"/><published>2011-10-24T14:57:41+01:00</published><updated>2011-10-24T14:57:41+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2011-10-24:/~cjwatson/blog/quality-in-12-04.html</id><summary type="html">&lt;p&gt;As is natural for an &lt;span class="caps"&gt;LTS&lt;/span&gt; cycle, lots of people are thinking and talking
about work focused on quality rather than features.  With Canonical
&lt;a href="http://www.canonical.com/content/ubuntu-1204-feature-extended-support-period-desktop-users"&gt;extending &lt;span class="caps"&gt;LTS&lt;/span&gt;
support&lt;/a&gt;
to five years on the desktop for 12.04, much of this is quite rightly
focused on the desktop.  I&amp;#8217;m really not …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As is natural for an &lt;span class="caps"&gt;LTS&lt;/span&gt; cycle, lots of people are thinking and talking
about work focused on quality rather than features.  With Canonical
&lt;a href="http://www.canonical.com/content/ubuntu-1204-feature-extended-support-period-desktop-users"&gt;extending &lt;span class="caps"&gt;LTS&lt;/span&gt;
support&lt;/a&gt;
to five years on the desktop for 12.04, much of this is quite rightly
focused on the desktop.  I&amp;#8217;m really not a desktop hacker in any way, shape,
or form, though.  I spent my first few years in Ubuntu working mainly on the
installer - I still do, although I do some other things now too - and I used
to say only half-jokingly that my job was done once X started.  Of course
there are plenty of bugs I can fix, but I wanted to see if I could do
something with a bit more structure, so I got to thinking about projects we
could work on at the foundations level that would make a big&amp;nbsp;difference.&lt;/p&gt;
&lt;h2&gt;Image build&amp;nbsp;pipeline&lt;/h2&gt;
&lt;p&gt;One difficulty we have is that quite a few of our bugs - especially
installer bugs, although this goes for some other things too - are only
really caught when people are doing coordinated image testing just before a
milestone release.  Now, it takes a while to do all the builds and then it
takes a while to test them.  The excellent work of the &lt;span class="caps"&gt;QA&lt;/span&gt; team has meant
that testing is much quicker now than it used to be, and a certain amount of
smoke-testing is automated (particularly for server images).  On the other
hand, the build phase has only got longer as we&amp;#8217;ve added more flavours and
architectures, particularly as some parts of the process are still
serialised per architecture or subarchitecture so &lt;span class="caps"&gt;ARM&lt;/span&gt; builds in particular
take a very long time indeed.  Exact timings are a bit difficult to get for
various reasons, but I think the minimum time between a developer uploading
a fix and us having a full set of candidate images on all architectures
including that fix is currently somewhere north of eight hours, and that&amp;#8217;s
with people cutting corners and pulling strings which is a suboptimal thing
to have to do around release time.  This obviously makes us reluctant to
respin for anything short of showstopper bugs.  If we could get things down
to something closer to two hours, respins would be a much less horrible
proposition and so we might be able to fix a few bugs that are serious but
not showstoppers, not to mention that the release team would feel less
burned&amp;nbsp;out.&lt;/p&gt;
&lt;p&gt;We discussed this problem at the release sprint, and came up with a &lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/foundations-p-image-build-pipeline"&gt;laundry
list of
improvements&lt;/a&gt;;
I&amp;#8217;ve scheduled this for discussion at &lt;span class="caps"&gt;UDS&lt;/span&gt; in case we can think of any more.
Please come along if you&amp;#8217;re&amp;nbsp;interested!&lt;/p&gt;
&lt;p&gt;One thing in particular that I&amp;#8217;m working on is refactoring
&lt;a href="https://launchpad.net/germinate"&gt;Germinate&lt;/a&gt;, a tool which dates right back
to our first meeting before Ubuntu was even called Ubuntu and whose job is
to expand dependencies starting from our lists of &amp;#8220;seed&amp;#8221; packages; we use
this, among other things, to generate &lt;code&gt;Task&lt;/code&gt; fields in the archive and to
decide which packages to copy into our images.  This was acceptably quick in
2004, but now that we run it forty times (eight flavours multiplied by five
architectures) at the end of every publisher run it&amp;#8217;s actually become rather
a serious performance problem: &lt;code&gt;cron.germinate&lt;/code&gt; takes about ten minutes,
which is over a third of the typical publisher runtime.  It parses Packages
files eight times as often as it needs to, Sources files forty times as
often as it needs to, and recalculates the dependency tree of the base
system five times as often as it needs to.  I am confident that we can
significantly reduce the runtime here, and I think there&amp;#8217;s some hope that we
might be able to move the publisher back to a 30-minute cycle, which would
increase the velocity of Ubuntu development in&amp;nbsp;general.&lt;/p&gt;
&lt;h2&gt;Maintaining the development&amp;nbsp;release&lt;/h2&gt;
&lt;p&gt;Our release cycle always starts with syncing and merging packages from
Debian unstable (or testing in the case of &lt;span class="caps"&gt;LTS&lt;/span&gt; cycles).  The vast majority
of packages in Ubuntu arrive this way, and generally speaking if we didn&amp;#8217;t
do this we would fall behind in ways that would be difficult to recover from
later.  However, this does mean that we get a &amp;#8220;big bang&amp;#8221; of changes at the
start of the cycle, and it takes a while for the archive to be usable again.
Furthermore, even once we&amp;#8217;ve taken care of this, we have a long-established
rhythm where the first part of the cycle is mainly about feature development
and the second part of the cycle is mainly about stabilisation.  As a
result, we&amp;#8217;ve got used to the archive being fairly broken for the first few
months, and we even tell people that they shouldn&amp;#8217;t expect things to work
reliably until somewhere approaching&amp;nbsp;beta.&lt;/p&gt;
&lt;p&gt;This makes some kind of sense from the inside.  But how are you supposed to
do feature development that relies on other things in the development&amp;nbsp;release?&lt;/p&gt;
&lt;p&gt;In the first few years of Ubuntu, this question didn&amp;#8217;t matter very much.
Nearly all the people doing serious feature development were themselves
serious Ubuntu developers; they were capable of fixing problems in the
development release as they went along, and while it got in their way a
little bit it wasn&amp;#8217;t all that big a deal.  Now, though, we have people
focusing on things like Unity development, and we shouldn&amp;#8217;t assume that just
because somebody is (say) an OpenGL expert or a window management expert
that they should be able to recover from arbitrary failures in development
release upgrades.  One of the best things we could do to help the 12.04
desktop be more stable is to have the entire system be less unstable as we
go along, so that developers further up the stack don&amp;#8217;t have to be
distracted by things wobbling underneath them.  Plus, it&amp;#8217;s just good
software engineering to keep the basics working as you go along: it should
always build, it should always install, it should always upgrade.  Ubuntu is
too big to do something like having everyone stop any time the build breaks,
the way you might do in a smaller project, but we shouldn&amp;#8217;t let things slide
for months&amp;nbsp;either.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been talking to &lt;a href="http://theravingrick.blogspot.com/"&gt;Rick Spencer&lt;/a&gt; and
the other Ubuntu engineering leads at Canonical about this.  Canonical has a
system of &amp;#8220;rotations&amp;#8221;, where you can go off to another team for a while if
you&amp;#8217;re in need of a change or want to branch out a bit; so I proposed that
we allow our engineers to spend a month or two at a time on what I&amp;#8217;m calling
the &lt;strong&gt;+1 Maintenance Team&lt;/strong&gt;, whose job is simply to keep the development
release buildable, installable, and upgradeable at all times.  Rick has been
very receptive to this, and we&amp;#8217;re going to be running this as a trial
throughout the 12.04 cycle, with probably about three people at a time.  As
well as being professional archive gardeners, these people will also work on
developing infrastructure to help us keep better track of what we need to
do.  For instance, we could deploy better tools from Debian &lt;span class="caps"&gt;QA&lt;/span&gt; to help us
track uninstallable packages, or we could enhance
&lt;a href="http://people.canonical.com/~ubuntu-archive/nbs.html"&gt;some&lt;/a&gt; of our
&lt;a href="http://conflictchecker.ubuntu.com/possible-conflicts/oneiric/main.txt"&gt;many&lt;/a&gt;
&lt;a href="http://people.canonical.com/~ubuntu-archive/component-mismatches.txt"&gt;existing&lt;/a&gt;
&lt;a href="http://people.canonical.com/~ubuntu-archive/testing/precise_probs.html"&gt;reports&lt;/a&gt;
to have bug links and/or comment facilities, or we could spruce up the
&lt;a href="http://reports.qa.ubuntu.com/reports/ogasawara/weatherreport.html"&gt;weather
report&lt;/a&gt;;
there are lots of things we could do to make our own lives&amp;nbsp;easier.&lt;/p&gt;
&lt;p&gt;By 12.04, I would like, in no particular&amp;nbsp;order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Precise to have been more or less continuously usable from Alpha 1 onward
   for people with reasonable general technical&amp;nbsp;ability&lt;/li&gt;
&lt;li&gt;Canonical engineering teams outside Ubuntu (&lt;span class="caps"&gt;DX&lt;/span&gt;, Ubuntu One, Launchpad,
   etc.) to be comfortable with running the development release on at least
   one system from Alpha 2&amp;nbsp;onward&lt;/li&gt;
&lt;li&gt;Installability problems in daily image builds to be dealt with within one
   working day, or preferably before they even make it to daily&amp;nbsp;builds&lt;/li&gt;
&lt;li&gt;The archive to be close to consistent as we start milestone preparation,
   rather than the release team having to scramble to make it&amp;nbsp;so&lt;/li&gt;
&lt;li&gt;A very significant reduction in our long-term backlog of
   automatically-detected&amp;nbsp;problems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, this overlaps to a certain extent with the kinds of things that
the &lt;span class="caps"&gt;MOTU&lt;/span&gt; team have been doing for years, not to mention with what all
developers should be doing to keep their own houses in reasonable order, and
I&amp;#8217;d like us to work together on this; we&amp;#8217;re trying to provide some extra
hands here to make Ubuntu better for everyone, not take over!  I would love
this to be an opportunity to re-energise &lt;span class="caps"&gt;MOTU&lt;/span&gt; and bring some new people on&amp;nbsp;board.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve registered a couple of blueprints
(&lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/other-p-plusonemaint-priorities"&gt;priorities&lt;/a&gt;,
&lt;a href="https://blueprints.launchpad.net/ubuntu/+spec/other-p-plusonemaint-infrastructure"&gt;infrastructure&lt;/a&gt;)
for discussion at &lt;span class="caps"&gt;UDS&lt;/span&gt;.  These are deliberately open-ended skeleton sessions,
and I&amp;#8217;ll try to make sure they&amp;#8217;re scheduled fairly early in the week, so
that we have time for break-out sessions later on.  If you&amp;#8217;re interested,
please come along and give your&amp;nbsp;feedback!&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Top ideas on Ubuntu Brainstorm (August 2011)</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/brainstorm-review.html" rel="alternate"/><published>2011-10-06T16:58:51+01:00</published><updated>2011-10-06T16:58:51+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2011-10-06:/~cjwatson/blog/brainstorm-review.html</id><summary type="html">&lt;p&gt;The Ubuntu Technical Board conducts a regular review of the most popular &lt;a href="http://brainstorm.ubuntu.com/"&gt;Ubuntu Brainstorm&lt;/a&gt; ideas (previous reviews conducted by &lt;a href="http://mdzlog.alcor.net/2010/12/10/ubuntu-brainstorm-top-10-for-december-2010/"&gt;Matt Zimmerman&lt;/a&gt; and &lt;a href="http://www.piware.de/2011/04/top-ideas-on-ubuntu-brainstorm-march-2011/"&gt;Martin Pitt&lt;/a&gt;).  This time it was my turn.  Apologies for the late arrival of this&amp;nbsp;review.&lt;/p&gt;
&lt;h2&gt;Contact lens in the Unity Dash (&lt;a href="http://brainstorm.ubuntu.com/idea/27584/"&gt;#27584&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Unity supports &lt;a href="https://wiki.ubuntu.com/Unity/Lenses"&gt;Lenses&lt;/a&gt;, which provide …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The Ubuntu Technical Board conducts a regular review of the most popular &lt;a href="http://brainstorm.ubuntu.com/"&gt;Ubuntu Brainstorm&lt;/a&gt; ideas (previous reviews conducted by &lt;a href="http://mdzlog.alcor.net/2010/12/10/ubuntu-brainstorm-top-10-for-december-2010/"&gt;Matt Zimmerman&lt;/a&gt; and &lt;a href="http://www.piware.de/2011/04/top-ideas-on-ubuntu-brainstorm-march-2011/"&gt;Martin Pitt&lt;/a&gt;).  This time it was my turn.  Apologies for the late arrival of this&amp;nbsp;review.&lt;/p&gt;
&lt;h2&gt;Contact lens in the Unity Dash (&lt;a href="http://brainstorm.ubuntu.com/idea/27584/"&gt;#27584&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Unity supports &lt;a href="https://wiki.ubuntu.com/Unity/Lenses"&gt;Lenses&lt;/a&gt;, which provide a consistent way for users to quickly search for information via the Dash.  Current lenses include Applications, Files, and Music, but a number of people have asked for contacts to be accessible using the same&amp;nbsp;interface.&lt;/p&gt;
&lt;p&gt;While Canonical&amp;#8217;s &lt;span class="caps"&gt;DX&lt;/span&gt; team isn&amp;#8217;t currently working on this for Ubuntu 11.10 or 12.04, we&amp;#8217;d love somebody who&amp;#8217;s interested in this to get involved.  Allison Randal &lt;a href="http://allisonrandal.com/2011/09/27/contacts-lens/"&gt;explains how to get started&lt;/a&gt;, including some skeleton example code and several useful&amp;nbsp;links.&lt;/p&gt;
&lt;h2&gt;Displaying Ubuntu version information (&lt;a href="http://brainstorm.ubuntu.com/idea/27460/"&gt;#27460&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Several people have asked for it to be more obvious what Ubuntu version they&amp;#8217;re running, as well as other general information about their&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;John Lea, user experience architect on the Unity team, responds that in Ubuntu 11.10 the new LightDM greeter shows the Ubuntu version number, making that basic information very easily visible.  For more detail, System Settings -&amp;gt; System Info provides a simple&amp;nbsp;summary.&lt;/p&gt;
&lt;h2&gt;Volume adjustments for headphone use (&lt;a href="http://brainstorm.ubuntu.com/idea/27275/"&gt;#27275&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;People often find that they need to adjust their sound volume when plugging in or removing headphones.  It seems as though the computer ought to be able to remember this kind of thing and do it automatically; after all, a major goal of Ubuntu is to make the desktop Just&amp;nbsp;Work.&lt;/p&gt;
&lt;p&gt;David Henningson, a member of Canonical&amp;#8217;s &lt;span class="caps"&gt;OEM&lt;/span&gt; Services group and an Ubuntu audio developer, &lt;a href="http://voices.canonical.com/david.henningsson/2011/09/29/independent-volume-for-headphones-and-speakers/"&gt;responds&lt;/a&gt; on his blog with a summary of how PulseAudio jack detection has improved matters in Ubuntu 11.10, and what&amp;#8217;s left to&amp;nbsp;do:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The good news: in the upcoming Ubuntu Oneiric (11.10), this is actually
working.  The bad news: it isn&amp;#8217;t working for&amp;nbsp;everyone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Making it easier to find software to handle a file (&lt;a href="http://brainstorm.ubuntu.com/idea/28148/"&gt;#28148&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Ubuntu is not always as helpful as it could be when you don&amp;#8217;t have the right software installed to handle a particular&amp;nbsp;file.&lt;/p&gt;
&lt;p&gt;Michael Vogt, one of the developers of the Ubuntu Software Center, responded to this.  It seems that most of the pieces to make this work nicely are in place, but there are a few more bits of glue&amp;nbsp;required:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks a lot for this suggestion.  I like the idea and it&amp;#8217;s something that
software-center itself supports now.  In the coming version 5.0 we will
offer to &amp;#8220;sort by top-rated&amp;#8221; (based on the ratings&amp;amp;reviews data).  It&amp;#8217;s
also possible to search for an application based on its mime data.  To
search for a mime-type, you can enter &amp;#8220;mime:text/html&amp;#8221; or &amp;#8220;mime:audio/ogg&amp;#8221;
into the search field.  What is needed however is better integration into
the file manager nautilus.  I will make sure this gets attention at the
next developer meeting and filed
&lt;a href="https://launchpad.net/bugs/860536"&gt;bug #860536&lt;/a&gt; about&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;In nautilus, there is now a button called &amp;#8220;Find applications online&amp;#8221;
available as an option when opening an unknown file or when the user
selects &amp;#8220;open with&amp;#8230;other application&amp;#8221; in the context menu.  But that
will not use the data from&amp;nbsp;software-center.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Show pop-up alert on low battery (&lt;a href="http://brainstorm.ubuntu.com/idea/28037/"&gt;#28037&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Some users have reported on Brainstorm that they are not alerted frequently enough when their laptop&amp;#8217;s battery is low, as they clearly ought to&amp;nbsp;be.&lt;/p&gt;
&lt;p&gt;This is an odd one, because there are already several power alert levels and this has been working well for us for some time.  Nevertheless, enough people have voted for this idea that there must be something behind it, perhaps a bug that only affects certain systems.  Martin Pitt, technical lead of the Ubuntu desktop team, has &lt;a href="http://brainstorm.ubuntu.com/idea/28037/"&gt;responded&lt;/a&gt; directly to the Brainstorm idea with a description of the current system and how to file a bug when it does not work as&amp;nbsp;intended.&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>man-db 2.6.0</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-2.6.0.html" rel="alternate"/><published>2011-04-09T20:45:17+01:00</published><updated>2011-04-09T20:45:17+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2011-04-09:/~cjwatson/blog/man-db-2.6.0.html</id><content type="html">&lt;p&gt;I&amp;#8217;ve released man-db 2.6.0
(&lt;a href="http://lists.nongnu.org/archive/html/man-db-announce/2011-04/msg00000.html"&gt;announcement&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS?id=2.6.0"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;&lt;/a&gt;,
&lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/ChangeLog?id=2.6.0"&gt;ChangeLog&lt;/a&gt;),
and uploaded it to Debian unstable.  Ubuntu is rapidly approaching beta
freeze so I&amp;#8217;m not going to try to cram this into 11.04; it&amp;#8217;ll be in&amp;nbsp;11.10.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Wubi bug 693671</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/wubi-bug-693671.html" rel="alternate"/><published>2011-03-14T12:56:57+00:00</published><updated>2011-03-15T10:12:09+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2011-03-14:/~cjwatson/blog/wubi-bug-693671.html</id><summary type="html">&lt;p&gt;I spent most of last week working on &lt;a href="https://bugs.launchpad.net/bugs/693671"&gt;Ubuntu bug
693671&lt;/a&gt; (&amp;#8220;wubi install will not boot
- phase 2 stops with: Try (hd0,0): &lt;span class="caps"&gt;NTFS5&lt;/span&gt;&amp;#8221;), which was quite a challenge to
debug since it involved digging into parts of the Wubi boot process I&amp;#8217;d
never really touched before.  Since I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I spent most of last week working on &lt;a href="https://bugs.launchpad.net/bugs/693671"&gt;Ubuntu bug
693671&lt;/a&gt; (&amp;#8220;wubi install will not boot
- phase 2 stops with: Try (hd0,0): &lt;span class="caps"&gt;NTFS5&lt;/span&gt;&amp;#8221;), which was quite a challenge to
debug since it involved digging into parts of the Wubi boot process I&amp;#8217;d
never really touched before.  Since I don&amp;#8217;t think much of this is very
well-documented, I&amp;#8217;d like to spend a bit of time explaining what was
involved, in the hope that it will help other developers in the&amp;nbsp;future.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Wubi_%28Ubuntu_installer%29"&gt;Wubi&lt;/a&gt; is a system
for installing Ubuntu into a file in a Windows filesystem, so that it
doesn&amp;#8217;t require separate partitions and can be uninstalled like any other
Windows application.  The purpose of this is to make it easy for Windows
users to try out Ubuntu without the need to worry about repartitioning,
before they commit to a full installation.  Wubi started out as an external
project, and initially patched the installer on the fly to do all the rather
unconventional things it needed to do; we integrated it into Ubuntu 8.04
&lt;span class="caps"&gt;LTS&lt;/span&gt;, which involved turning these patches into proper installer facilities
that could be accessed using preseeding, so that Wubi only needs to handle
the Windows user interface and other Windows-specific&amp;nbsp;tasks.&lt;/p&gt;
&lt;p&gt;Anyone familiar with a &lt;span class="caps"&gt;GNU&lt;/span&gt;/Linux system&amp;#8217;s boot process will immediately see
that this isn&amp;#8217;t as simple as it sounds.  Of course,
&lt;a href="http://www.tuxera.com/community/ntfs-3g-download/"&gt;ntfs-3g&lt;/a&gt; is a pretty
solid piece of software so we can handle the Windows filesystem without too
much trouble, and loopback mounts are well-understood so we can just have
the initramfs loop-mount the root filesystem.  Where are you going to get
the kernel and initramfs from, though?  Well, we used to copy them out to
the &lt;span class="caps"&gt;NTFS&lt;/span&gt; filesystem so that &lt;span class="caps"&gt;GRUB&lt;/span&gt; could read them, but this was overly
complicated and error-prone.  When we switched to &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2, we could instead
use its built-in loopback facilities, and we were able to simplify this.  So
all was more or less well, except for the elephant in the room.  How are you
going to load &lt;span class="caps"&gt;GRUB&lt;/span&gt;?&lt;/p&gt;
&lt;p&gt;In a Wubi installation, &lt;span class="caps"&gt;NTLDR&lt;/span&gt; (or &lt;span class="caps"&gt;BOOTMGR&lt;/span&gt; in Windows Vista and newer) still
owns the boot process.  Ubuntu is added as a boot menu option using BCDEdit.
You might then think that you can just have the Windows boot loader
chain-load &lt;span class="caps"&gt;GRUB&lt;/span&gt;.  Unfortunately, &lt;span class="caps"&gt;NTLDR&lt;/span&gt; only loads 16 sectors - 8192 bytes -
from disk.  &lt;span class="caps"&gt;GRUB&lt;/span&gt; won&amp;#8217;t fit in that: the smallest core.img you can generate
at the moment is over 18 kilobytes.  Thus, you need something that is small
enough to be loaded by &lt;span class="caps"&gt;NTLDR&lt;/span&gt;, but that is intelligent enough to understand
&lt;span class="caps"&gt;NTFS&lt;/span&gt; to the point where it can find a particular file in the root directory
of a filesystem, load boot loader code from it, and jump to that.  The
answer for this was &lt;a href="http://gna.org/projects/grub4dos/"&gt;&lt;span class="caps"&gt;GRUB4DOS&lt;/span&gt;&lt;/a&gt;.  Most of
&lt;span class="caps"&gt;GRUB4DOS&lt;/span&gt; is based on &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy, which is not of much interest to us any
more, but it includes an assembly-language program called &lt;span class="caps"&gt;GRLDR&lt;/span&gt; that
supports doing this very thing for &lt;span class="caps"&gt;FAT&lt;/span&gt;, &lt;span class="caps"&gt;NTFS&lt;/span&gt;, and ext2.  In Wubi, we build
&lt;span class="caps"&gt;GRLDR&lt;/span&gt; as &lt;code&gt;wubildr.mbr&lt;/code&gt;, and build a specially-configured &lt;span class="caps"&gt;GRUB&lt;/span&gt; core image as
&lt;code&gt;wubildr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, the messages shown in the bug report suggested a failure either within
&lt;span class="caps"&gt;GRLDR&lt;/span&gt; or very early in &lt;span class="caps"&gt;GRUB&lt;/span&gt;.  The first thing I did was to remember that
&lt;span class="caps"&gt;GRLDR&lt;/span&gt; has been integrated into the grub-extras &lt;code&gt;ntldr-img&lt;/code&gt; module suitable
for use with &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2, so I tried building &lt;code&gt;wubildr.mbr&lt;/code&gt; from that; no change,
but this gave me a modern baseline to work on.  &lt;span class="caps"&gt;OK&lt;/span&gt;; now to try &lt;span class="caps"&gt;QEMU&lt;/span&gt; (you can
use tricks like &lt;code&gt;qemu -hda /dev/sda&lt;/code&gt; if you&amp;#8217;re very careful not to do
anything that might involve writing to the host filesystem from within the
guest, such as recursively booting your host &lt;span class="caps"&gt;OS&lt;/span&gt; &amp;#8230; [&lt;strong&gt;update:&lt;/strong&gt; Tollef Fog
Heen and Zygmunt Krynicki both point out that you can use the &lt;code&gt;-snapshot&lt;/code&gt;
option to make this safer]).  No go; it hung somewhere in the middle of
&lt;span class="caps"&gt;NTLDR&lt;/span&gt;.  Still, I could at least insert debug statements, copy the built
&lt;code&gt;wubildr.mbr&lt;/code&gt; over to my test machine, and reboot for each test, although it
would be slow and tedious.  Couldn&amp;#8217;t&amp;nbsp;I?&lt;/p&gt;
&lt;p&gt;Well, yes, I mostly could, but that 8192-byte limit came back to bite me,
along with an internal 2048-byte limit that &lt;span class="caps"&gt;GRLDR&lt;/span&gt; allocates for its &lt;span class="caps"&gt;NTFS&lt;/span&gt;
bootstrap code.  There were only a few spare bytes.  Something like this
would more or less fit, to print a single mark character at various points
so that I could see how far it was&amp;nbsp;getting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;pushal&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;xorw&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;%bx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%bx&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* video page 0 */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;movw&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;$0x0e4d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%ax&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* print &amp;#39;M&amp;#39; */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="no"&gt;$0x10&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;popal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In a few places, if I removed some code I didn&amp;#8217;t need on my test machine
(say, &lt;span class="caps"&gt;CHS&lt;/span&gt; compatibility), I could even fit in cheap and nasty code to print
a single register in hex (as long as you didn&amp;#8217;t mind &amp;#8216;A&amp;#8217; to &amp;#8216;F&amp;#8217; actually
being &amp;#8216;:&amp;#8217; to &amp;#8216;?&amp;#8217; in &lt;span class="caps"&gt;ASCII&lt;/span&gt;; and note that this is real-mode code, so the loop
counter is &lt;code&gt;%cx&lt;/code&gt; not &lt;code&gt;%ecx&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* print %edx in dumbed-down hex */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;pushal&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;xorw&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;%bx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%bx&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;movb&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;$0xe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%ah&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;movw&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;$8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%cx&lt;/span&gt;
&lt;span class="err"&gt;1:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;roll&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;$4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%edx&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;movb&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;%dl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%al&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;andb&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="no"&gt;$0xf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%al&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="no"&gt;$0x10&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="no"&gt;b&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nf"&gt;popal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a considerable amount of work tracking down problems by bisection like
this, I also observed that &lt;span class="caps"&gt;GRLDR&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;NTFS&lt;/span&gt; code bears quite a bit of
resemblance in its logical flow to &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2&amp;#8217;s &lt;span class="caps"&gt;NTFS&lt;/span&gt; module, and indeed the same
person wrote much of both.  Since I knew that the latter worked, I could use
it to relieve my brain of trying to understand assembly code logic directly,
and could compare the two to look for discrepancies.  I did find a few of
these, and corrected a simple one.  Testing at this point suggested that the
boot process was getting as far as &lt;span class="caps"&gt;GRUB&lt;/span&gt; but still wasn&amp;#8217;t printing anything.
I removed some Ubuntu patches which quieten down &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;#8217;s startup: still
nothing - so I switched my attentions to
&lt;a href="http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=grub-core/kern/i386/pc/startup.S;hb=HEAD"&gt;grub-core/kern/i386/pc/startup.S&lt;/a&gt;,
which contains the first code executed from &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;#8217;s core image.  Code before
the first call to &lt;code&gt;real_to_prot&lt;/code&gt; (which switches the processor into
protected mode) succeeded, while code after that point failed.  Even more
mysteriously, code added to &lt;code&gt;real_to_prot&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; the actual switch to
protected mode failed too.  Now I was clearly getting somewhere interesting,
but what was going on?  What I really wanted was to be able to single-step,
or at least see what was at the memory location it was supposed to be
jumping&amp;nbsp;to.&lt;/p&gt;
&lt;p&gt;Around this point I was venting on &lt;span class="caps"&gt;IRC&lt;/span&gt;, and somebody asked if it was
reproducible in &lt;span class="caps"&gt;QEMU&lt;/span&gt;.  Although I&amp;#8217;d tried that already, I went back and
tried again.  Ubuntu&amp;#8217;s &lt;code&gt;qemu&lt;/code&gt; is actually built from qemu-kvm, and if I used
&lt;code&gt;qemu -no-kvm&lt;/code&gt; then it worked much better.  Excellent!  Now I could use &lt;span class="caps"&gt;GDB&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(gdb) target remote | qemu -gdb stdio -no-kvm -hda /dev/sda
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This let me run until the point when &lt;span class="caps"&gt;NTLDR&lt;/span&gt; was about to hand over control,
then interrupt and set a breakpoint at &lt;code&gt;0x8200&lt;/code&gt; (the entry point of
&lt;code&gt;startup.S&lt;/code&gt;).  This revealed that the address that should have been
&lt;code&gt;real_to_prot&lt;/code&gt; was in fact garbage.  I set a breakpoint at &lt;code&gt;0x7c00&lt;/code&gt; (&lt;span class="caps"&gt;GRLDR&lt;/span&gt;&amp;#8217;s
entry point) and stepped all the way through to ensure it was doing the
right thing.  In the process it was helpful to know that &lt;a href="http://sourceware.org/ml/gdb/2009-01/msg00008.html"&gt;&lt;span class="caps"&gt;GDB&lt;/span&gt; and &lt;span class="caps"&gt;QEMU&lt;/span&gt; don&amp;#8217;t
handle real mode very well between
them&lt;/a&gt;.  Useful tricks
here&amp;nbsp;were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;set architecture i8086&lt;/code&gt; before disassembling real-mode code (and
   &lt;code&gt;set architecture i386&lt;/code&gt; to switch&amp;nbsp;back).&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;GDB&lt;/span&gt; prints addresses relative to the current segment base, but if you
   want to enter an address then you need to calculate a linear address
   yourself.  For example, breakpoints must be set at &lt;code&gt;(CS &amp;lt;&amp;lt; 4) + IP&lt;/code&gt;,
   rather than just at &lt;code&gt;IP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Single-stepping showed that &lt;span class="caps"&gt;GRLDR&lt;/span&gt; was loading the entirety of &lt;code&gt;wubildr&lt;/code&gt;
correctly and jumping to it.  The first instruction it jumped to wasn&amp;#8217;t in
&lt;code&gt;startup.S&lt;/code&gt;, though, and then I remembered that we prefix the core image
with
&lt;a href="http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=grub-core/boot/i386/pc/lnxboot.S;hb=edde54e656a3219a6ad5e7118e0212d50af01697"&gt;grub-core/boot/i386/pc/lnxboot.S&lt;/a&gt;.
Stepping through this required a clear head since it copies itself around
and changes segment registers a few times.  The interesting part was at
&lt;code&gt;real_code_2&lt;/code&gt;, where it copies a sector of the kernel to the target load
address, and then checks a known offset to find out whether the &amp;#8220;kernel&amp;#8221; is
in fact &lt;span class="caps"&gt;GRUB&lt;/span&gt; rather than a Linux kernel.  I checked that offset by hand, and
there was the smoking gun.  &lt;span class="caps"&gt;GRUB&lt;/span&gt; recently acquired Reed-Solomon error
correction on its core image, to allow it to recover from other software
writing over sectors in the boot track.  This moved the magic number
&lt;code&gt;lnxboot.S&lt;/code&gt; was checking somewhat further into the core image, after the
first sector.  &lt;code&gt;lnxboot.S&lt;/code&gt; couldn&amp;#8217;t find it because it hadn&amp;#8217;t copied it yet!
A bit of
&lt;a href="http://git.savannah.gnu.org/gitweb/?p=grub.git;a=commitdiff;h=9b43bf396a61b60a0ee4b8a1591634b1120b8906"&gt;adjustment&lt;/a&gt;
and all was well&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;The lesson for me from all of this has been to try hard to get an
interactive debugger working.  Really hard.  It&amp;#8217;s worth quite a bit of
up-front effort if it saves you from killing neurons stepping through pages
of code by hand.  I think the real-mode debugging tricks I picked up should
be useful for working on &lt;span class="caps"&gt;GRUB&lt;/span&gt; in the&amp;nbsp;future.&lt;/p&gt;</content><category term="grub"/><category term="grub"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>libpipeline 1.1.0 released</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/libpipeline-1.1.0-released.html" rel="alternate"/><published>2010-12-11T15:47:39+00:00</published><updated>2010-12-11T15:50:23+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-12-11:/~cjwatson/blog/libpipeline-1.1.0-released.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline 1.1.0&lt;/a&gt;, and
uploaded it to Debian unstable.  The changes are mostly just to add a few
occasionally useful&amp;nbsp;interfaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;pipecmd_exec&lt;/code&gt; to execute a single command, replacing the current
   process; this is analogous to &lt;code&gt;execvp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;pipecmd_clearenv&lt;/code&gt; to clear a command&amp;#8217;s environment; this …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline 1.1.0&lt;/a&gt;, and
uploaded it to Debian unstable.  The changes are mostly just to add a few
occasionally useful&amp;nbsp;interfaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;pipecmd_exec&lt;/code&gt; to execute a single command, replacing the current
   process; this is analogous to &lt;code&gt;execvp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;pipecmd_clearenv&lt;/code&gt; to clear a command&amp;#8217;s environment; this is
   analogous to &lt;code&gt;clearenv&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;pipecmd_get_nargs&lt;/code&gt; to get the number of arguments to a&amp;nbsp;command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The shared library actually ends up being a few kilobytes smaller on Debian
than 1.0.0, probably because I tweaked the set of Gnulib modules I&amp;#8217;m&amp;nbsp;using.&lt;/p&gt;</content><category term="libpipeline"/><category term="libpipeline"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>NTP synchronisation problems</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ntp-synchronisation-problems.html" rel="alternate"/><published>2010-12-06T12:58:29+00:00</published><updated>2010-12-06T13:05:02+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-12-06:/~cjwatson/blog/ntp-synchronisation-problems.html</id><summary type="html">&lt;p&gt;The Ubuntu Technical Board is currently conducting a review of the top ten
Brainstorm issues users have raised about Ubuntu, and Matt asked me to
investigate and respond to &lt;a href="http://brainstorm.ubuntu.com/idea/25301/"&gt;Idea #25301: Keeping the time accurate over the
Internet by default&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My first reaction was &amp;#8220;hey, that&amp;#8217;s odd - I thought …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The Ubuntu Technical Board is currently conducting a review of the top ten
Brainstorm issues users have raised about Ubuntu, and Matt asked me to
investigate and respond to &lt;a href="http://brainstorm.ubuntu.com/idea/25301/"&gt;Idea #25301: Keeping the time accurate over the
Internet by default&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My first reaction was &amp;#8220;hey, that&amp;#8217;s odd - I thought we already did that?&amp;#8221;.
We install the &lt;code&gt;ntpdate&lt;/code&gt; package by default (although it&amp;#8217;s &lt;a href="http://www.eecis.udel.edu/~mills/ntp/html/ntpdate.html"&gt;deprecated
upstream&lt;/a&gt; in favour
of other tools, but that shouldn&amp;#8217;t be important here).  &lt;code&gt;ntpdate&lt;/code&gt; is run
from &lt;code&gt;/etc/network/if-up.d/ntpdate&lt;/code&gt;, in other words every time you connect
to a network, which should be acceptably frequent for most people, so it
really ought to Just Work by default.  But this is one of the top ten
problems where users have gone to the trouble of proposing solutions on
Brainstorm, so it couldn&amp;#8217;t be that simple.  What was going&amp;nbsp;on?&lt;/p&gt;
&lt;p&gt;I brought up a clean virtual machine with a development version of Natty
(the current Ubuntu development version, which will eventually become
11.04), and had a look in its logs: it was indeed synchronising its time
from &lt;code&gt;ntp.ubuntu.com&lt;/code&gt;, and I didn&amp;#8217;t think anything in that area had changed
recently.  On the other hand, I had occasionally noticed that my own laptop
wasn&amp;#8217;t always synchronising its time quite right, but I&amp;#8217;d put it down to
local weirdness as my network isn&amp;#8217;t always very stable.  Maybe this wasn&amp;#8217;t
so local after&amp;nbsp;all?&lt;/p&gt;
&lt;p&gt;So, I started tracing through the scripts to figure out what was going on.
It turned out that I had an empty &lt;code&gt;/etc/ntp.conf&lt;/code&gt; file on my laptop.  The
&lt;code&gt;/usr/sbin/ntpdate-debian&lt;/code&gt; script assumed that that meant I had a full &lt;span class="caps"&gt;NTP&lt;/span&gt;
server installed (I don&amp;#8217;t), and fetched the list of servers from it; since
the file was empty, it ended up synchronising time from no servers, that is,
not synchronising at all.  I removed the file and all was&amp;nbsp;well.&lt;/p&gt;
&lt;p&gt;That left the question of where that file came from.  It didn&amp;#8217;t seem to be
owned by any package; I was pretty sure I hadn&amp;#8217;t created it by hand either.
I had a look through some bug reports, and soon found &lt;a href="https://bugs.launchpad.net/bugs/83604"&gt;ntpdate
1:4.2.2.p4+dfsg-1ubuntu2 has a flawed configuration
file&lt;/a&gt;.  It turns out that
&lt;code&gt;time-admin&lt;/code&gt; (System -&amp;gt; Administration -&amp;gt; Time and Date) creates an empty
&lt;code&gt;/etc/ntp.conf&lt;/code&gt; file if you press the reload button (tooltip: &amp;#8220;Synchronise
now&amp;#8221;), as part of an attempt to update &lt;span class="caps"&gt;NTP&lt;/span&gt; configuration.&amp;nbsp;Aha!&lt;/p&gt;
&lt;p&gt;Once I knew where the problems were, it was easy to fix them.  I&amp;#8217;ve uploaded
the following changes, which will be in the 11.04&amp;nbsp;release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disregard empty &lt;code&gt;ntp.conf&lt;/code&gt; files in &lt;code&gt;ntpdate-debian&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove an empty &lt;code&gt;/etc/ntp.conf&lt;/code&gt; file on fresh installation of the &lt;code&gt;ntp&lt;/code&gt;
   package, so that it doesn&amp;#8217;t interfere with creating the normal
   configuration&amp;nbsp;file.&lt;/li&gt;
&lt;li&gt;Don&amp;#8217;t create the &lt;span class="caps"&gt;NTP&lt;/span&gt; configuration file in the &lt;code&gt;time-admin&lt;/code&gt; backend if it
   doesn&amp;#8217;t exist&amp;nbsp;already.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ve also sent these changes to
&lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=606107"&gt;Debian&lt;/a&gt; and
&lt;a href="https://bugzilla.gnome.org/show_bug.cgi?id=449267"&gt;&lt;span class="caps"&gt;GNOME&lt;/span&gt;&lt;/a&gt; as&amp;nbsp;appropriate.&lt;/p&gt;
&lt;p&gt;There are still a few problems.  The &amp;#8220;Synchronise now&amp;#8221; button doesn&amp;#8217;t work
quite right in general
(&lt;a href="https://bugs.launchpad.net/bugs/90524"&gt;bug #90524&lt;/a&gt;), and if your network
doesn&amp;#8217;t allow time synchronisation from &lt;code&gt;ntp.ubuntu.com&lt;/code&gt; then you&amp;#8217;ll have to
change the value of &lt;code&gt;NTPSERVERS&lt;/code&gt; in &lt;code&gt;/etc/default/ntpdate&lt;/code&gt;.  Furthermore,
the &lt;code&gt;time-admin&lt;/code&gt; interface is confusing and makes it seem as though the
default is not to synchronise the time automatically; this interface is
being &lt;a href="https://wiki.ubuntu.com/TimeAndDate"&gt;redesigned&lt;/a&gt; at the moment, which
should be a good opportunity to make it less confusing, and I will contact
the designers to mention this problem.  On the whole, though, I think that
many fewer people should have this kind of problem in Ubuntu&amp;nbsp;11.04.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s always possible that I missed some other problem that breaks automatic
time synchronisation for people.  Please do file a bug report if it still
doesn&amp;#8217;t work for you in 11.04, or contact me directly (cjwatson at&amp;nbsp;ubuntu.com).&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>man-db on Fedora</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-on-fedora.html" rel="alternate"/><published>2010-12-02T14:06:58+00:00</published><updated>2010-12-02T14:09:22+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-12-02:/~cjwatson/blog/man-db-on-fedora.html</id><summary type="html">&lt;p&gt;I just found out by chance that &lt;a href="http://fedoraproject.org/"&gt;Fedora&lt;/a&gt; 14
switched from their old man package to &lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt;.
This is great news: it should now be the beginning of the end of the
divergence of man implementations that happened way back in the mid-1990s,
when two different people took John W …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I just found out by chance that &lt;a href="http://fedoraproject.org/"&gt;Fedora&lt;/a&gt; 14
switched from their old man package to &lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt;.
This is great news: it should now be the beginning of the end of the
divergence of man implementations that happened way back in the mid-1990s,
when two different people took John W. Eaton&amp;#8217;s man package and developed it
in different directions without being aware of each other&amp;#8217;s existence.  For
a while it looked as though man-db was stuck on just the Debian family and
openSUSE, but a number of distributions have switched over in the last few
years.  As of now, the only remaining major distribution not using man-db is
Gentoo, and they have a &lt;a href="http://bugs.gentoo.org/show_bug.cgi?id=284822"&gt;bug for
switching&lt;/a&gt; which I think
should be unblocked fairly&amp;nbsp;soon.&lt;/p&gt;
&lt;p&gt;In some ways man-db&amp;#8217;s package name didn&amp;#8217;t help it; people thought that the
main difference was that man-db had a database backend stuck around apropos.
These days, the database is one of the least important parts of man-db as
far as I&amp;#8217;m concerned.  Other ways in which it&amp;#8217;s very significantly superior
to anything man could do without years of equivalent effort include correct
encoding support, robust child process handling, and use of more modern
development facilities (dear catgets: you belong to a previous millennium,
so please go away).  I&amp;#8217;m glad that Fedora has recognised&amp;nbsp;this.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>libpipeline 1.0.0 released</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/libpipeline-released.html" rel="alternate"/><published>2010-10-29T21:23:26+01:00</published><updated>2010-10-29T21:23:26+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-10-29:/~cjwatson/blog/libpipeline-released.html</id><summary type="html">&lt;p&gt;In my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/pipeline-library.html"&gt;previous post&lt;/a&gt;, I described the
pipeline library from man-db and asked whether people were interested in a
standalone release of it.  Several people expressed interest, and so I&amp;#8217;ve
now released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline&lt;/a&gt; version 1.0.0.
It&amp;#8217;s in the Debian &lt;span class="caps"&gt;NEW&lt;/span&gt; queue, and &lt;a href="https://launchpad.net/~cjwatson/+archive/ppa"&gt;my
&lt;span class="caps"&gt;PPA&lt;/span&gt;&lt;/a&gt; contains packages …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/pipeline-library.html"&gt;previous post&lt;/a&gt;, I described the
pipeline library from man-db and asked whether people were interested in a
standalone release of it.  Several people expressed interest, and so I&amp;#8217;ve
now released &lt;a href="http://libpipeline.nongnu.org/"&gt;libpipeline&lt;/a&gt; version 1.0.0.
It&amp;#8217;s in the Debian &lt;span class="caps"&gt;NEW&lt;/span&gt; queue, and &lt;a href="https://launchpad.net/~cjwatson/+archive/ppa"&gt;my
&lt;span class="caps"&gt;PPA&lt;/span&gt;&lt;/a&gt; contains packages of it
for Ubuntu lucid and&amp;nbsp;maverick.&lt;/p&gt;
&lt;p&gt;I gave a lightning talk on this at &lt;span class="caps"&gt;UDS&lt;/span&gt; in Orlando, and my
&lt;a href="http://libpipeline.nongnu.org/libpipeline-lightning-talk.odp"&gt;slides&lt;/a&gt; are
available.  I hope there&amp;#8217;ll be a video at some point which I can link&amp;nbsp;to.&lt;/p&gt;
&lt;p&gt;Thanks to Scott James Remnant for code review (some time back), Ian Jackson
for an extensive design review, and Kees Cook and Matthias Klose for helpful&amp;nbsp;conversations.&lt;/p&gt;</content><category term="libpipeline"/><category term="libpipeline"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Pipeline library</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/pipeline-library.html" rel="alternate"/><published>2010-10-03T22:59:11+01:00</published><updated>2010-10-03T22:59:11+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-10-03:/~cjwatson/blog/pipeline-library.html</id><summary type="html">&lt;p&gt;When I took over &lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt; in 2001, one of the
major problems that became evident after maintaining it for a while was the
way it handled subprocesses.  The nature of man and friends means that it
spends a lot of time calling sequences of programs such as &lt;code&gt;zsoelim &amp;lt;
input-file | tbl …&lt;/code&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;When I took over &lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt; in 2001, one of the
major problems that became evident after maintaining it for a while was the
way it handled subprocesses.  The nature of man and friends means that it
spends a lot of time calling sequences of programs such as &lt;code&gt;zsoelim &amp;lt;
input-file | tbl | nroff -mandoc -Tutf8&lt;/code&gt;.  Back then, it was using C library
facilities such as &lt;code&gt;system&lt;/code&gt; and &lt;code&gt;popen&lt;/code&gt; for all this, and I had to deal with
several bugs where those functions were being called with untrusted input as
arguments without properly escaping metacharacters.  Of course it was
possible to chase around every such call inserting appropriate escaping
functions, but this was always bound to be error-prone and one of the tasks
that rapidly became important to me was arranging to start subprocesses in a
way that was fundamentally immune to this kind of&amp;nbsp;bug.&lt;/p&gt;
&lt;p&gt;In higher-level languages, there are usually standard constructs which are
safer than just passing a command line to the shell.  For example, in Perl
you can use &lt;code&gt;system([$command, $arg1, $arg2, ...])&lt;/code&gt; to invoke a program with
arguments without the interference of the shell, and &lt;code&gt;perlipc(1)&lt;/code&gt; describes
various facilities for connecting them together.  In Python, the
&lt;a href="http://docs.python.org/library/subprocess.html"&gt;subprocess&lt;/a&gt; module allows
you to create pipelines easily and safely (as long as you remember the
&lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/python-sigpipe.html"&gt;&lt;span class="caps"&gt;SIGPIPE&lt;/span&gt; gotcha&lt;/a&gt;).  C has the &lt;code&gt;fork&lt;/code&gt; and
&lt;code&gt;execve&lt;/code&gt; primitives, but assembling these to construct full-blown pipelines
correctly is difficult and error-prone, so many programmers don&amp;#8217;t bother and
use the simple but unsafe library facilities&amp;nbsp;instead.&lt;/p&gt;
&lt;p&gt;I wrote a couple of thousand lines of library code in man-db to address this
problem, loosely and now quite distantly based on code in
&lt;a href="http://www.gnu.org/software/groff/"&gt;groff&lt;/a&gt;.  In the following examples,
function names starting with &lt;code&gt;command_&lt;/code&gt;, &lt;code&gt;pipeline_&lt;/code&gt;, or &lt;code&gt;decompress_&lt;/code&gt; are
real functions in the library, while any other function names are&amp;nbsp;pseudocode.&lt;/p&gt;
&lt;p&gt;Constructing the simplified example pipeline from my first paragraph using
this library looks like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pipeline_new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;want_infile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;input-file&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pipeline_command_args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;zsoelim&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_command_args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tbl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_command_args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nroff&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-mandoc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-Tutf8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pipeline_wait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You might want to construct a command more&amp;nbsp;dynamically:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;manconv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command_new_args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;manconv&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-f&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-t&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quiet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;command_arg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manconv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-q&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manconv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Perhaps you want an environment variable set only while running a certain&amp;nbsp;command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;less&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command_new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;less&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;command_setenv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;less&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;LESSCHARSET&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lesscharset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You might find yourself needing to pass the output of one pipeline to
several other pipelines, in a &amp;#8220;tee&amp;#8221;&amp;nbsp;arrangement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sink1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sink2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;sink1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_sink1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;sink2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_sink2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;pipeline_connect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sink1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sink2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/* Pump data among these pipelines until there&amp;#39;s nothing left. */&lt;/span&gt;
&lt;span class="n"&gt;pipeline_pump&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sink1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sink2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sink2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sink1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Maybe one of your commands is actually an in-process function, rather than
an external&amp;nbsp;program:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;inproc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command_new_function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;in-process&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inproc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sometimes your program needs to consume the output of a pipeline, rather
than sending it all to some other&amp;nbsp;subprocess:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make_pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pipeline_peekline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;strstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;coding: UTF-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unicode text follows:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pipeline_readline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;  %s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline_free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;man-db deals with compressed files a lot, so I wrote an add-on library for
opening compressed files (which is somewhat man-db-specific, but the
implementation wasn&amp;#8217;t difficult given the underlying&amp;nbsp;library):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;decomp_file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;decompress_open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compressed_filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;decomp_stdin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;decompress_fdopen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileno&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This library has been in production in man-db for over five years now.  The
very careful signal handling code has been reviewed independently and the
whole thing has been run through multiple static analysis tools, although I
would always welcome more review; in particular I have no idea what it would
take to make it safe for use in threaded programs since I generally avoid
threading wherever possible.  There have been a handful of bugs, which I&amp;#8217;ve
fixed promptly, and I&amp;#8217;ve added various new features to support particular
requirements of man-db (though in as general a way as possible).  Every so
often I see somebody asking about subprocess handling in C, and I wonder if
I should split this library out into a standalone package so that it can be
used elsewhere.  Web searches for things like &amp;#8220;pipeline library&amp;#8221; and
&amp;#8220;libpipeline&amp;#8221; don&amp;#8217;t reveal anything that&amp;#8217;s a particularly close match for
what I have.  The licensing would be GPLv2 or later; this isn&amp;#8217;t likely to be
negotiable since some of the original code wasn&amp;#8217;t mine and in any case I
don&amp;#8217;t feel particularly bad about &lt;a href="http://www.gnu.org/licenses/why-not-lgpl.html"&gt;giving an advantage to GPLed
programs&lt;/a&gt;.  For more details
on the interface, the &lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/lib/pipeline.h?id=017a4c1e639d20e85d92ed11786a728913104953"&gt;header
file&lt;/a&gt;
is&amp;nbsp;well-commented.&lt;/p&gt;
&lt;p&gt;Is there enough interest in this to make the effort of producing a separate
library package worthwhile?  As well as the general effort of creating a new
package, I&amp;#8217;d need to do some work to disentangle it from a few bits and
pieces specific to man-db.  If you maintain a specific package that could
use this and you&amp;#8217;re interested, please contact me with details, mentioning
any extensions you think you&amp;#8217;d need.  I intentionally haven&amp;#8217;t enabled
comments on my blog for various reasons, but you can e-mail me at cjwatson
at debian.org or man-db-devel at&amp;nbsp;nongnu.org.&lt;/p&gt;</content><category term="libpipeline"/><category term="libpipeline"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Windows applications making GRUB 2 unbootable</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/windows-applications-making-grub2-unbootable.html" rel="alternate"/><published>2010-08-28T00:47:21+01:00</published><updated>2010-08-28T00:47:21+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-08-28:/~cjwatson/blog/windows-applications-making-grub2-unbootable.html</id><summary type="html">&lt;p&gt;If you find that running Windows makes a &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2-based system unbootable
(&lt;a href="http://bugs.debian.org/550702"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://bugs.launchpad.net/bugs/441941"&gt;Ubuntu
bug&lt;/a&gt;), then I&amp;#8217;d like to hear from
you.  This is a bug in which some proprietary Windows-based software
overwrites particular sectors in the gap between the master boot record and
the first partition, sometimes …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you find that running Windows makes a &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2-based system unbootable
(&lt;a href="http://bugs.debian.org/550702"&gt;Debian bug&lt;/a&gt;, &lt;a href="https://bugs.launchpad.net/bugs/441941"&gt;Ubuntu
bug&lt;/a&gt;), then I&amp;#8217;d like to hear from
you.  This is a bug in which some proprietary Windows-based software
overwrites particular sectors in the gap between the master boot record and
the first partition, sometimes called the &amp;#8220;embedding area&amp;#8221;.  &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy and
&lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 both normally use this part of the disk to store one of their key
components: &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy calls this component Stage 1.5, while &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 calls
it the core image
(&lt;a href="http://www.gnu.org/software/grub/manual/grub.html#Images"&gt;comparison&lt;/a&gt;).
However, Stage 1.5 is less useful than the core image (for example, the
latter provides a rescue shell which can be used to recover from some
problems), and is therefore rather smaller: somewhere around &lt;span class="caps"&gt;10KB&lt;/span&gt; vs. &lt;span class="caps"&gt;24KB&lt;/span&gt;
for the common case of ext[234] on plain block devices.  It seems that the
Windows-based software writes to a sector which is after the end of Stage
1.5, but before the end of the core image.  This is why the problem appears
to be new with &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;2.&lt;/p&gt;
&lt;p&gt;At least some occurrences of this are with software which writes a signature
to the embedding area which hangs around even after uninstallation (even
with one of those tools that tracks everything the installation process did
and reverses it, I gather), so that you cannot uninstall and reinstall the
application to defeat a trial period.  This seems like a fine example of an
&lt;a href="http://wiki.mako.cc/Antifeatures"&gt;antifeature&lt;/a&gt;, especially given its
destructive consequences for free software, and is in general a poor piece
of engineering; what happens if multiple such programs want to use the same
sector, I wonder?  They clearly aren&amp;#8217;t doing much checking that the sector
is unused, not that that&amp;#8217;s really possible anyway.  While I do not normally
think that &lt;span class="caps"&gt;GRUB&lt;/span&gt; should go to any great lengths to accommodate proprietary
software, this is a case where we need to defend ourselves against the
predatory practices of some companies making us look bad: a relatively small
number of people do enough detective work to realise that it&amp;#8217;s the fault of
a particular Windows application, but many more simply blame our operating
system because it won&amp;#8217;t start any&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;I believe that it may be possible to assemble a collection of signatures of
such software, and arrange to avoid the disk sectors they have stolen.
Indeed, I have a first draft of the necessary code.  This is not a
particularly pleasant solution, but it seems to be the most practical way
around the problem; I&amp;#8217;m hoping that several of the programs at fault are
using common &amp;#8220;licence manager&amp;#8221; code or something like that, so that we can
address most of the problems with a relatively small number of signatures.
In order to do this, I need to hear from as many people as possible who are
affected by this&amp;nbsp;problem.&lt;/p&gt;
&lt;p&gt;If you suffer from this problem, then please do the&amp;nbsp;following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Save the output of &lt;code&gt;fdisk -lu&lt;/code&gt; to a file.  In this output, take note of
   the start sector of the first partition (usually 63, but might also be
   2048 on recent installations, or occasionally something else).  If this
   is something other than 63, then replace 63 in the following items with
   your&amp;nbsp;number.&lt;/li&gt;
&lt;li&gt;Save the contents of the embedding area to a file (replace &lt;code&gt;/dev/sda&lt;/code&gt;
   with your disk device if it&amp;#8217;s something else): &lt;code&gt;dd if=/dev/sda of=sda.1
   count=63&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Do whatever you do to make &lt;span class="caps"&gt;GRUB&lt;/span&gt; unbootable (presumably starting Windows),
   then boot into a recovery environment.  Before you reinstall &lt;span class="caps"&gt;GRUB&lt;/span&gt;, save
   the new contents of the embedding area to a different file: &lt;code&gt;dd
   if=/dev/sda of=sda.2 count=63&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Follow up to either the Debian or the Ubuntu bug with these three files
   (the output of &lt;code&gt;fdisk -lu&lt;/code&gt;, and the embedding area before and after
   making &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;unbootable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope that this will help me to assemble enough information to fix this bug
at least for most people, and of course if you provide this information then
I can make sure to fix your particular version of this problem.  Thanks in&amp;nbsp;advance!&lt;/p&gt;</content><category term="grub"/><category term="grub"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>debhelper statistics, redux</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debhelper-statistics-redux.html" rel="alternate"/><published>2010-07-10T23:40:20+01:00</published><updated>2010-07-10T23:42:45+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-07-10:/~cjwatson/blog/debhelper-statistics-redux.html</id><summary type="html">&lt;p&gt;Apropos of &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debhelper-statistics.html"&gt;my previous post&lt;/a&gt;, I see
that dh has now overtaken &lt;span class="caps"&gt;CDBS&lt;/span&gt; as the most popular rules helper system of
its kind in Debian unstable, and shows no particular sign of slowing its
rate of uptake any time soon.  The resolution of the graph is such that you
can …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Apropos of &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debhelper-statistics.html"&gt;my previous post&lt;/a&gt;, I see
that dh has now overtaken &lt;span class="caps"&gt;CDBS&lt;/span&gt; as the most popular rules helper system of
its kind in Debian unstable, and shows no particular sign of slowing its
rate of uptake any time soon.  The resolution of the graph is such that you
can&amp;#8217;t see it yet, but dh drew dead level with &lt;span class="caps"&gt;CDBS&lt;/span&gt; on Thursday, and today
3836 packages are using dh as opposed to 3823 using &lt;span class="caps"&gt;CDBS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="debhelper statistics" src="http://people.debian.org/~cjwatson/dhstats.png"&gt;&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>GRUB 2: With luck …</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/grub2-with-luck.html" rel="alternate"/><published>2010-07-02T22:27:35+01:00</published><updated>2010-07-02T22:27:35+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-07-02:/~cjwatson/blog/grub2-with-luck.html</id><summary type="html">&lt;p&gt;&amp;#8230; this version, or something not too far away from it, might actually
stand a chance of getting into&amp;nbsp;testing.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve just uploaded grub2 1.98+20100702-1.  The most significant set of
changes in this release is that it switches &lt;code&gt;/boot/grub/device.map&lt;/code&gt; and the
&lt;code&gt;grub-pc/install_devices&lt;/code&gt; debconf question …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&amp;#8230; this version, or something not too far away from it, might actually
stand a chance of getting into&amp;nbsp;testing.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve just uploaded grub2 1.98+20100702-1.  The most significant set of
changes in this release is that it switches &lt;code&gt;/boot/grub/device.map&lt;/code&gt; and the
&lt;code&gt;grub-pc/install_devices&lt;/code&gt; debconf question over to stable device names under
&lt;code&gt;/dev/disk/by-id&lt;/code&gt; (on Linux kernels).  The code implementing this is
reasonably careful, and it should make it quite difficult for people to
accidentally fail to upgrade their installed &lt;span class="caps"&gt;GRUB&lt;/span&gt; core image; I explained
the problems that tends to cause in the &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/grub2-boot-problems.html"&gt;previous post in this
series&lt;/a&gt;.  There will probably be a few
small glitches I need to clear up, but I&amp;#8217;ve given this much more extensive
testing than usual so I hope I won&amp;#8217;t break too many people&amp;#8217;s computers&amp;nbsp;(again).&lt;/p&gt;
&lt;p&gt;I did this work first in Ubuntu as one of my major goals for 10.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;,
which exposed a few problems that I wanted to fix before inflicting it on
Debian as well (fixes for those are now under testing for 10.04.1).  Most
significantly, I felt it was necessary to start offering partitions in the
select list for &lt;code&gt;grub-pc/install_devices&lt;/code&gt;, but I went a bit overboard and
offered all partitions in a giant list.  This seemed like a good idea at the
time, but it tended to confuse people into just selecting everything in the
list, which in particular tended to make Windows unbootable!  So I dialled
that back a bit, and in the version I just merged it will only offer the
partitions mounted on &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/boot&lt;/code&gt;, and &lt;code&gt;/boot/grub&lt;/code&gt; (de-duplicating if
necessary).  This seems like a reasonable compromise between confusing
people too much and forcing them to install only to&amp;nbsp;MBRs.&lt;/p&gt;
&lt;p&gt;My next priority will be making whatever fixes are necessary to get this
version into testing, since the problems with &lt;code&gt;/dev/mapper&lt;/code&gt; symlinks in
testing aren&amp;#8217;t getting any less urgent, and this is finally a version that
shouldn&amp;#8217;t break for most people due to the kernel&amp;#8217;s switch to libata.  I
expect that I&amp;#8217;ll try to get mdadm 1.x metadata sorted out immediately after&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;Other improvements since my last entry have&amp;nbsp;included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Further documentation work.  Thanks to Vladimir Serbinenko (and to Jordan
   Uggla for hosting it temporarily), there&amp;#8217;s now an &lt;a href="http://www.gnu.org/software/grub/manual/"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; version of the
   &lt;span class="caps"&gt;GRUB&lt;/span&gt; manual from trunk&lt;/a&gt; online,
   which includes new sections on embedded configuration files, the various
   &lt;span class="caps"&gt;GRUB&lt;/span&gt; image files, &lt;code&gt;device.map&lt;/code&gt;, and (shortly) a summary of changes from
   &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;Legacy.&lt;/li&gt;
&lt;li&gt;Video improvements: among other things, &lt;span class="caps"&gt;UEFI&lt;/span&gt; systems whose firmware uses
   the Graphics Output Protocol should now work rather better, and &lt;span class="caps"&gt;GRUB&lt;/span&gt; now
   includes specific support for some cards often used with minimal firmware
   support under&amp;nbsp;emulation.&lt;/li&gt;
&lt;li&gt;A fix to handle large memory maps exposed by some &lt;span class="caps"&gt;UEFI&lt;/span&gt;&amp;nbsp;firmware.&lt;/li&gt;
&lt;li&gt;Automatic configuration support for Fedora 13.  You may need &lt;a href="http://packages.qa.debian.org/o/os-prober/news/20100628T171748Z.html"&gt;os-prober
   1.39&lt;/a&gt;
   from unstable as&amp;nbsp;well.&lt;/li&gt;
&lt;li&gt;Automatic configuration support for Linux on&amp;nbsp;Xen.&lt;/li&gt;
&lt;li&gt;Skip &lt;span class="caps"&gt;LVM&lt;/span&gt; snapshots rather than failing when they&amp;#8217;re&amp;nbsp;present.&lt;/li&gt;
&lt;/ul&gt;</content><category term="grub"/><category term="grub"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>GRUB 2 boot problems</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/grub2-boot-problems.html" rel="alternate"/><published>2010-06-21T11:52:10+01:00</published><updated>2010-06-21T11:52:10+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-06-21:/~cjwatson/blog/grub2-boot-problems.html</id><summary type="html">&lt;p&gt;(This is partly a repost of material I&amp;#8217;ve posted to bug reports and to
debian-release, put together with some more detail for a wider&amp;nbsp;audience.)&lt;/p&gt;
&lt;p&gt;You could be forgiven for looking at the &lt;span class="caps"&gt;RC&lt;/span&gt; bug activity on
&lt;a href="http://bugs.debian.org/src:grub2"&gt;grub2&lt;/a&gt; over the last couple of days and
thinking that it&amp;#8217;s …&lt;/p&gt;</summary><content type="html">&lt;p&gt;(This is partly a repost of material I&amp;#8217;ve posted to bug reports and to
debian-release, put together with some more detail for a wider&amp;nbsp;audience.)&lt;/p&gt;
&lt;p&gt;You could be forgiven for looking at the &lt;span class="caps"&gt;RC&lt;/span&gt; bug activity on
&lt;a href="http://bugs.debian.org/src:grub2"&gt;grub2&lt;/a&gt; over the last couple of days and
thinking that it&amp;#8217;s all gone to hell in a handbasket with recent uploads.  In
fact, aside from an interesting case which turned out to be due to botched
handling of the &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy to &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 chainloading setup (which prompted me
to fix three other &lt;span class="caps"&gt;RC&lt;/span&gt; bugs along the way), all the recent problems people
have been having have been duplicates of one of these bugs which have
existed essentially&amp;nbsp;forever:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://bugs.debian.org/554790"&gt;#554790 - grub-pc/install_devices uses unstable device&amp;nbsp;names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bugs.debian.org/583271"&gt;#583271 - device.map uses unstable device&amp;nbsp;names&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When &lt;span class="caps"&gt;GRUB&lt;/span&gt; boots, its boot sector first loads its &amp;#8220;core image&amp;#8221;, which is
usually embedded in the gap between the boot sector and the first partition
on the same disk as the boot sector.  This core image then figures out where
to find /boot/grub, and loads grub.cfg from it as well as more &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;modules.&lt;/p&gt;
&lt;p&gt;The thing that tends to go wrong here is that the core image must be from
the same version of &lt;span class="caps"&gt;GRUB&lt;/span&gt; as any modules it loads.  &lt;code&gt;/boot/grub/*.mod&lt;/code&gt; are
updated only by grub-install, so this normally works &lt;span class="caps"&gt;OK&lt;/span&gt;.  However, for
various reasons (deliberate or accidental) some people install &lt;span class="caps"&gt;GRUB&lt;/span&gt; to
multiple disks.  In this case, grub-install might update &lt;code&gt;/boot/grub/*.mod&lt;/code&gt;
along with the core image on one disk, but your &lt;span class="caps"&gt;BIOS&lt;/span&gt; might actually be
booting from a different disk.  The effect of this will be that you&amp;#8217;ll have
an old core image and new modules, which will probably blow up in any number
of possible ways.  Quite often, this problem lies dormant for a while
because &lt;span class="caps"&gt;GRUB&lt;/span&gt; happens not to change in a way that causes incompatibility
between the core image and modules, but then we get massive spikes of bug
reports any time the interface does change.  Since these bugs sometimes bite
people upgrading from testing to unstable, they get interpreted as
regressions from the version in testing even though that isn&amp;#8217;t strictly true
(but it tends not to be very productive to argue this line; after all,
people&amp;#8217;s computers suddenly don&amp;#8217;t boot!).  Any problem that causes the core
image to be installed to a disk other than the one actually being booted
from, or not to be installed at all, will show up this way sooner or&amp;nbsp;later.&lt;/p&gt;
&lt;p&gt;On 2010-06-10, there was a substantial upstream change to the handling of
list iterators (to reduce core image size and make code clearer and faster)
which introduced an incompatibility between old core images and newer
modules.  This caused a bunch of dormant problems to flare up again, and so
there was a flood of reports of booting problems with 1.98+20100614-1 and
newer, often described as &amp;#8220;the unaligned pointer bug&amp;#8221; due to how it happened
to manifest this time round.  In previous cases, &lt;span class="caps"&gt;GRUB&lt;/span&gt; reported undefined
symbols on boot, but it&amp;#8217;s all essentially the same problem even though there
are different&amp;nbsp;symptoms.&lt;/p&gt;
&lt;p&gt;The confusing bit when handling bug reports is that not only are there
different symptoms with the same cause, but there are also multiple causes
for the same symptom!  This takes a certain amount of untangling, especially
when lots of people have thought &amp;#8220;ooh, that bug looks a bit like mine&amp;#8221; and
jumped in with their own comments.  Working through this was a worthwhile
exercise, as it came up with an entirely new cause for a problem I thought
was fairly well-understood (thanks to debugging assistance from Sedat
Dilek).  If you had set up &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 to be automatically chainloaded from &lt;span class="caps"&gt;GRUB&lt;/span&gt;
Legacy (which happens automatically on upgrade from the latter to the
former), never got round to running &lt;code&gt;upgrade-from-grub-legacy&lt;/code&gt; once you
confirmed it worked, and then later ran &lt;code&gt;grub-install&lt;/code&gt; by hand for one
reason or another, then the core image you installed by hand would never be
updated and would eventually &lt;a href="http://bugs.debian.org/586143"&gt;fall over&lt;/a&gt; the
next time the core/modules interface changed.  Fixing future cases of this
was easy enough, but fixing existing cases involved figuring out how to
detect whether an installed &lt;span class="caps"&gt;GRUB&lt;/span&gt; boot sector came from &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy or &lt;span class="caps"&gt;GRUB&lt;/span&gt;
2, which isn&amp;#8217;t as easy as you might think.  Fortunately, it turns out that
there are a limited number of jump offsets that have ever been used in the
second byte of the boot sector, and none of the &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 values clash with the
only value ever used in &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy; so, if you still have
&lt;code&gt;/boot/grub/stage2&lt;/code&gt; et al on upgrade, we scan all disks for a &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 boot
sector, and if we find one then we offer to complete the upgrade to &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;2.&lt;/p&gt;
&lt;p&gt;Unless anything new shows up, that just leaves the problems that were
already understood.  Today, I posted a &lt;a href="http://lists.gnu.org/archive/html/grub-devel/2010-06/msg00118.html"&gt;patch to generate stable device
names in device.map by
default&lt;/a&gt;.
If this is accepted, then we can do something or other to fix up device.map
on upgrade, switch over to &lt;code&gt;/dev/disk/by-id&lt;/code&gt; names in
&lt;code&gt;grub-pc/install_devices&lt;/code&gt; at the same time, and that should take care of the
vast majority of this kind of upgrade bug.  I think at that point it should
be feasible to get a new version into testing, and we should be down from 18
&lt;span class="caps"&gt;RC&lt;/span&gt; bugs towards the end of last month to around 6.  We can then start
attacking things like the lack of support for mdadm 1.x&amp;nbsp;metadata.&lt;/p&gt;
&lt;p&gt;Since my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/hacking-on-grub2.html"&gt;last blog entry on &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2&lt;/a&gt;,
improvements have&amp;nbsp;included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Substantial work on &lt;code&gt;info grub&lt;/code&gt;, with, among other things, new sections
   on &lt;code&gt;/etc/default/grub&lt;/code&gt; and on configuring&amp;nbsp;authentication.&lt;/li&gt;
&lt;li&gt;A workaround for &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;#8217;s inability to probe dm-crypt devices, thanks to
   Marc&amp;nbsp;Haber.&lt;/li&gt;
&lt;li&gt;Several build fixes for architectures I wasn&amp;#8217;t testing, and a fix for
   broken nested partition handling on Debian &lt;span class="caps"&gt;GNU&lt;/span&gt;/kFreeBSD.  I&amp;#8217;m now testing
   &lt;span class="caps"&gt;GNU&lt;/span&gt;/kFreeBSD&amp;nbsp;locally.&lt;/li&gt;
&lt;li&gt;Rather less cruft in &lt;code&gt;fs.lst&lt;/code&gt;, &lt;code&gt;partmap.lst&lt;/code&gt;, and &lt;code&gt;video.lst&lt;/code&gt;, which
   should speed up booting a bit by e.g. avoiding unnecessary filesystem&amp;nbsp;probing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;upgrade-from-grub-legacy&lt;/code&gt; actually now installs &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 to the boot
   sector&amp;nbsp;(!).&lt;/li&gt;
&lt;li&gt;Ask for confirmation if &lt;code&gt;grub-pc/install_devices&lt;/code&gt; is left&amp;nbsp;empty.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next upstream snapshot will bring several improvements to &lt;span class="caps"&gt;EFI&lt;/span&gt; video
support, mainly thanks to Vladimir Serbinenko.  I&amp;#8217;ve been working on making
&lt;code&gt;grub-install&lt;/code&gt; actually work on &lt;span class="caps"&gt;UEFI&lt;/span&gt; systems as one of my goals for the next
Ubuntu release, and I hope to get this landed in the not-too-distant&amp;nbsp;future.&lt;/p&gt;</content><category term="grub"/><category term="grub"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Hacking on grub2</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/hacking-on-grub2.html" rel="alternate"/><published>2010-06-04T22:57:07+01:00</published><updated>2010-06-04T23:00:54+01:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-06-04:/~cjwatson/blog/hacking-on-grub2.html</id><summary type="html">&lt;p&gt;Various people observed in a &lt;a href="http://lists.debian.org/debian-devel/2010/05/msg00769.html"&gt;long thread on
debian-devel&lt;/a&gt;
that the grub2 package was in a bit of a mess in terms of its
release-critical bug count, and &lt;a href="http://oskuro.net/blog"&gt;Jordi&lt;/a&gt; and
&lt;a href="http://upsilon.cc/~zack/blog/planet-debian/"&gt;Stefano&lt;/a&gt; both got in touch
with me directly to gently point out that I probably ought to be doing
something …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Various people observed in a &lt;a href="http://lists.debian.org/debian-devel/2010/05/msg00769.html"&gt;long thread on
debian-devel&lt;/a&gt;
that the grub2 package was in a bit of a mess in terms of its
release-critical bug count, and &lt;a href="http://oskuro.net/blog"&gt;Jordi&lt;/a&gt; and
&lt;a href="http://upsilon.cc/~zack/blog/planet-debian/"&gt;Stefano&lt;/a&gt; both got in touch
with me directly to gently point out that I probably ought to be doing
something about it as one of the&amp;nbsp;co-maintainers.&lt;/p&gt;
&lt;p&gt;Actually, I don&amp;#8217;t think grub2 was in quite as bad a state as its 18 &lt;span class="caps"&gt;RC&lt;/span&gt; bugs
suggested.  Of course every boot loader failure is critical to the person
affected by it, not to mention that &lt;span class="caps"&gt;GRUB&lt;/span&gt; 2 offers more complex functionality
than any other boot loader (e.g. &lt;span class="caps"&gt;LVM&lt;/span&gt; and &lt;span class="caps"&gt;RAID&lt;/span&gt;), and so it tends to
accumulate &lt;span class="caps"&gt;RC&lt;/span&gt; bugs at rather a high rate.  That said, we&amp;#8217;d been neglecting
its bug list for some time; &lt;a href="http://robertmh.wordpress.com/"&gt;Robert&lt;/a&gt; and
Felix have both been taking some time off, Jordi mostly only cared about
PowerPC and can&amp;#8217;t do that any more due to hardware failure, and I hadn&amp;#8217;t
been able to pick up the&amp;nbsp;slack.&lt;/p&gt;
&lt;p&gt;Most of my projects at &lt;a href="http://www.ubuntu.com/"&gt;work&lt;/a&gt; for the next while
involve &lt;span class="caps"&gt;GRUB&lt;/span&gt; in one way or another, so I decided it was a perfectly
reasonable use of work time to do something about this; I was going to need
fully up-to-date snapshots anyway, and practically all the Debian grub2 bugs
affect Ubuntu too.  Thus, with the exception of some other little things
like releasing the first Maverick alpha, I&amp;#8217;ve spent pretty much the last
week and a half solidly trying to get the grub2 package back into shape,
with four uploads so&amp;nbsp;far.&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;RC&lt;/span&gt; issues that remain&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;upgrade-from-grub-legacy&lt;/code&gt; problems
    (&lt;a href="http://bugs.debian.org/547944"&gt;#547944&lt;/a&gt;,
    &lt;a href="http://bugs.debian.org/550477"&gt;#550477&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;I think this has just been traditionally undertested.  I&amp;#8217;m setting up a
&lt;span class="caps"&gt;KVM&lt;/span&gt; image now with &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy which I can snapshot just before and
after running &lt;code&gt;upgrade-from-grub-legacy&lt;/code&gt;, and I should be able to unpick
the bugs this&amp;nbsp;way.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;LVM&lt;/span&gt; snapshots break &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;LVM&lt;/span&gt; module
    (&lt;a href="http://bugs.debian.org/574863"&gt;#574863&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.seanius.net/feeds/planet-debian/"&gt;Sean&lt;/a&gt; has been working on
this and seems to be nearly there.&amp;nbsp;Yay.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt; metadata version 1.x not supported
    (&lt;a href="http://bugs.debian.org/492897"&gt;#492897&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;This became rather more of an issue recently since &lt;code&gt;mdadm&lt;/code&gt; switched its
default from the old 0.90 format which &lt;span class="caps"&gt;GRUB&lt;/span&gt; understood.  Felix put
together a branch implementing the hard parts of this a while back, and
I&amp;#8217;ve been trying to finish it off.  The hard bit is dealing with device
naming, especially as the new-format and rather more useful names under
&lt;code&gt;/dev/md/&lt;/code&gt; don&amp;#8217;t show up during
&lt;a href="http://www.debian.org/devel/debian-installer"&gt;d-i&lt;/a&gt; after creating &lt;span class="caps"&gt;RAID&lt;/span&gt;
volumes; I think this is because we always create them as &lt;code&gt;/dev/md0&lt;/code&gt;
etc.  It&amp;#8217;s looking tractable,&amp;nbsp;though.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Another odd problem probing &lt;span class="caps"&gt;RAID&lt;/span&gt;
    (&lt;a href="http://bugs.debian.org/548648"&gt;#548648&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;Not sure about this one, and I&amp;#8217;ll need to work with Josip on it as soon
as I get a&amp;nbsp;chance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stable device naming &lt;a href="http://bugs.debian.org/554790"&gt;#554790&lt;/a&gt;) and
    consequential problems due to &lt;code&gt;grub-install&lt;/code&gt; not being properly run
    (&lt;a href="http://bugs.debian.org/557425"&gt;#557425&lt;/a&gt; and many other sub-&lt;span class="caps"&gt;RC&lt;/span&gt;&amp;nbsp;bugs):&lt;/p&gt;
&lt;p&gt;Ubuntu&amp;#8217;s been carrying a patch to rearrange device presentation in the
postinst, which Robert OKed in principle ages ago and so I&amp;#8217;ve been
intending to merge it for a while, but there are a few known problems
with it that I need to fix first.  One known unfixable problem is that
it will have to ask some people which devices they want &lt;span class="caps"&gt;GRUB&lt;/span&gt; to be
installed on, even if they&amp;#8217;d answered that question before: this will be
one-time, and it&amp;#8217;s because it recorded the answer using unstable device
names and so has in some sense forgotten.  Simple cases (e.g.
single-disk) can be handled without needing to ask again,&amp;nbsp;though.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alignment errors on &lt;span class="caps"&gt;SPARC&lt;/span&gt; (&lt;a href="http://bugs.debian.org/560823"&gt;#560823&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;I have no idea what&amp;#8217;s going on here, I&amp;#8217;m afraid.  I&amp;#8217;ll try to trace it,
but may have to downgrade it at some point since after all we don&amp;#8217;t
install &lt;span class="caps"&gt;GRUB&lt;/span&gt; by default on &lt;span class="caps"&gt;SPARC&lt;/span&gt;&amp;nbsp;yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fonts not shown in gfxmenu (&lt;a href="http://bugs.debian.org/564844"&gt;#564844&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;Apparently fixed upstream, but I couldn&amp;#8217;t find the responsible commit so
I want to make sure I can get gfxmenu working before closing&amp;nbsp;this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sensitivity to out-of-date &lt;code&gt;device.map&lt;/code&gt; files
    (&lt;a href="http://bugs.debian.org/575076"&gt;#575076&lt;/a&gt; and other sub-&lt;span class="caps"&gt;RC&lt;/span&gt;&amp;nbsp;bugs):&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re trying to get rid of &lt;code&gt;device.map&lt;/code&gt; in general.  It was fine in the
1990s but it&amp;#8217;s hopeless now.  Unfortunately there are still a small
number of problems with running entirely without one, and one of my
patches to help is controversial upstream, so we probably won&amp;#8217;t get to
that for squeeze.  In the meantime we&amp;#8217;ll probably just need some extra
sanity-checking and robustness in the event that there&amp;#8217;s an incorrect or
out-of-date &lt;code&gt;device.map&lt;/code&gt; lying around, which we may just be able to do
in the maintainer scripts or something if&amp;nbsp;necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seriously weird failures to load initramfs
    (&lt;a href="http://bugs.debian.org/582342"&gt;#582342&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;If anyone can produce a reproduction recipe for this, that would really
help me out.  There are too many reports to discount as user error, but
I haven&amp;#8217;t seen this myself&amp;nbsp;yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build failure on sparc&amp;nbsp;(unfiled):&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve been discussing this upstream, but for the time being I&amp;#8217;m just
going to stop building &lt;code&gt;grub-emu&lt;/code&gt; on sparc as a&amp;nbsp;workaround.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we can fix that lot, or even just the ones that are reasonably
well-understood, I think we&amp;#8217;ll be in reasonable shape.  I&amp;#8217;d also like to
make &lt;code&gt;grub-mkconfig&lt;/code&gt; a bit more robust in the event that the root filesystem
isn&amp;#8217;t one that &lt;span class="caps"&gt;GRUB&lt;/span&gt; understands (&lt;a href="http://bugs.debian.org/561855"&gt;#561855&lt;/a&gt;,
&lt;a href="http://bugs.debian.org/562672"&gt;#562672&lt;/a&gt;), and I&amp;#8217;d quite like to write some
more&amp;nbsp;documentation.&lt;/p&gt;
&lt;p&gt;On the upside, progress has been good.  We have multiple terminal support
thanks to a new upstream snapshot
(&lt;a href="http://bugs.debian.org/506707"&gt;#506707&lt;/a&gt;), &lt;code&gt;update-grub&lt;/code&gt; runs much faster
(&lt;a href="http://bugs.debian.org/508834"&gt;#508834&lt;/a&gt;,
&lt;a href="http://bugs.debian.org/574088"&gt;#574088&lt;/a&gt;), we have &lt;span class="caps"&gt;DM&lt;/span&gt;-&lt;span class="caps"&gt;RAID&lt;/span&gt; support with a
following wind (&lt;a href="http://bugs.debian.org/579919"&gt;#579919&lt;/a&gt;), the new scheme
with symlinks under &lt;code&gt;/dev/mapper/&lt;/code&gt; works
(&lt;a href="http://bugs.debian.org/550704"&gt;#550704&lt;/a&gt;), we have basic support for btrfs
&lt;code&gt;/&lt;/code&gt; as long as you have something &lt;span class="caps"&gt;GRUB&lt;/span&gt; understands properly on &lt;code&gt;/boot&lt;/code&gt;
(&lt;a href="http://bugs.debian.org/540786"&gt;#540786&lt;/a&gt;), we have full info documentation
covering all the user-adjustable settings in &lt;code&gt;/etc/default/grub&lt;/code&gt;, and a host
of other smaller fixes.  I&amp;#8217;m hoping we can keep this&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;d like to help, contact me, especially if there&amp;#8217;s something
particular that isn&amp;#8217;t being handled that you think you could work on.  &lt;span class="caps"&gt;GRUB&lt;/span&gt;
2 is actually quite a pleasant codebase to work on once you get used to its
layout; it&amp;#8217;s certainly much easier to fix bugs in than &lt;span class="caps"&gt;GRUB&lt;/span&gt; Legacy ever was,
as far as I&amp;#8217;m concerned.  Thanks to tools like &lt;code&gt;grub-probe&lt;/code&gt; and
&lt;code&gt;grub-fstest&lt;/code&gt;, it&amp;#8217;s very often possible to fix problems without needing to
reboot for anything other than a final sanity check (although &lt;span class="caps"&gt;KVM&lt;/span&gt; certainly
helps), and you can often debug very substantial bits of the boot loader -
the bits that actually go wrong - using standard tools such as &lt;code&gt;strace&lt;/code&gt; and
&lt;code&gt;gdb&lt;/code&gt;.  Upstream is helpful and I&amp;#8217;ve been able to get many of the problems
above fixed directly there.  If you have a sound knowledge of C and a decent
level of understanding of the environment a boot loader needs to operate in
- or for that matter specialist knowledge of interesting device types - then
you should be able to find something to&amp;nbsp;do.&lt;/p&gt;</content><category term="grub"/><category term="grub"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>OpenSSH 5.5p1 for Lucid</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/openssh-5.5p1-for-lucid.html" rel="alternate"/><published>2010-05-10T10:29:51+02:00</published><updated>2010-05-10T10:29:51+02:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-05-10:/~cjwatson/blog/openssh-5.5p1-for-lucid.html</id><summary type="html">&lt;p&gt;For various reasons, I chose to leave Ubuntu 10.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; using OpenSSH 5.3p1.
The &lt;a href="http://www.openssh.org/txt/release-5.4"&gt;new features in 5.4p1&lt;/a&gt; such as
certificate authentication, the new smartcard handling, netcat mode, and
tab-completion in sftp are great, but unfortunately it was available just a
little bit too late for me …&lt;/p&gt;</summary><content type="html">&lt;p&gt;For various reasons, I chose to leave Ubuntu 10.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; using OpenSSH 5.3p1.
The &lt;a href="http://www.openssh.org/txt/release-5.4"&gt;new features in 5.4p1&lt;/a&gt; such as
certificate authentication, the new smartcard handling, netcat mode, and
tab-completion in sftp are great, but unfortunately it was available just a
little bit too late for me to be able to land it for 10.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;.  I realise
that many Lucid users want to make use of these features for one reason or
another, though, so as a compromise here&amp;#8217;s a &lt;span class="caps"&gt;PPA&lt;/span&gt; containing &lt;a href="https://launchpad.net/~cjwatson/+archive/openssh"&gt;OpenSSH 5.5p1
for Lucid&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I intend to keep this up to date for as long as I reasonably can, and I&amp;#8217;m
happy to accept bug reports on it in the &lt;a href="https://bugs.launchpad.net/ubuntu/+source/openssh"&gt;usual
place&lt;/a&gt;.&lt;/p&gt;</content><category term="ubuntu"/><category term="openssh"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Thoughts on 3.0 (quilt) format</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/thoughts-on-3.0-quilt-format.html" rel="alternate"/><published>2010-03-25T23:45:28+00:00</published><updated>2010-03-26T01:00:06+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-03-25:/~cjwatson/blog/thoughts-on-3.0-quilt-format.html</id><summary type="html">&lt;p&gt;Note: I wrote most of this before &lt;a href="http://www.linux.codehelp.co.uk/serendipity/index.php?/archives/201-lintian,-source-format-3.0-and-blog-comments.html"&gt;Neil Williams&amp;#8217; recent comments on the 3.0
family of
formats&lt;/a&gt;,
so despite the timing this isn&amp;#8217;t really a reaction to that although I do
have a couple of responses.  On the whole I think I agree that the Lintian
message is …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Note: I wrote most of this before &lt;a href="http://www.linux.codehelp.co.uk/serendipity/index.php?/archives/201-lintian,-source-format-3.0-and-blog-comments.html"&gt;Neil Williams&amp;#8217; recent comments on the 3.0
family of
formats&lt;/a&gt;,
so despite the timing this isn&amp;#8217;t really a reaction to that although I do
have a couple of responses.  On the whole I think I agree that the Lintian
message is a bit heavy-handed and I&amp;#8217;m not sure I&amp;#8217;m thrilled about the idea
of the default source format being changed (though I can see why the dpkg
maintainers are interested in that).  That said, as far as I personally am
concerned, there is a vast cognitive benefit to me in having as much as
possible be common to all my packages.  Once I have more than a couple of
packages that require patching and benefit from the &lt;code&gt;3.0 (quilt)&lt;/code&gt; format as
a result, I find it in my interest to use it for all my non-native packages
even if they&amp;#8217;re patchless right now, so that for instance if they need
patches in the future I can handle them the same way.  It&amp;#8217;s not unheard of
for me to apply temporary patches even to packages I actively maintain
upstream, so I don&amp;#8217;t discount those either.  I haven&amp;#8217;t decided what to do
with my native packages yet; unless they&amp;#8217;re big enough for bzip2 compression
to be worthwhile, there doesn&amp;#8217;t seem to be much immediate advantage to &lt;code&gt;3.0
(native)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, on to the main body of this&amp;nbsp;post:&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been one of the holdouts resisting use of patch systems for a long
time, on the basis that I felt strongly that &lt;code&gt;dpkg-source -x&lt;/code&gt; ought to give
you the source that&amp;#8217;s actually built, rather than having to mess around with
&lt;code&gt;debian/rules&lt;/code&gt; targets in order to see it.  Now that the &lt;code&gt;3.0 (quilt)&lt;/code&gt;
format is available to fix this bug, I felt that I ought to revisit my
resistance and start trying to use it.  Migrating to it from monolithic
diffs is of course a bit more work than migrating to it from other patch
systems, so it&amp;#8217;s taken me a little while to get round to it.  I&amp;#8217;d been
thinking about holding off until there was better integration with revision
control (e.g. bzr looms), as I feel that patch files really ought to be an
export format, but I eventually decided that I shouldn&amp;#8217;t let the perfect be
the enemy of the good.  I have enough experience with co-maintaining
packages that use build-time patch systems to be able to compare my&amp;nbsp;reactions.&lt;/p&gt;
&lt;p&gt;After experimenting with a couple of small packages, I moved over to the
deep end and &lt;a href="http://packages.qa.debian.org/o/openssh/news/20100228T035004Z.html"&gt;converted
openssh&lt;/a&gt;
a few weekends ago, since quite a few people have requested over the years
that the Debian changes to openssh be easier to audit.  This was a
substantial job - over 6000 lines of upstream patches - but not actually as
much work as I expected.  I took a fairly simplistic approach: first, I
unapplied all the upstream patches from my tree; then I ran &lt;code&gt;bzr di |
interdiff -q /dev/stdin /dev/null &amp;gt;x&lt;/code&gt;, reduced it to a single
logically-discrete patch, applied it to a new quilt patch using &lt;code&gt;quilt
fold&lt;/code&gt;, and repeated until &lt;code&gt;x&lt;/code&gt; was empty.  This was maybe an hour or two of
work, and then I went through and tagged all the patches according to
&lt;a href="http://dep.debian.net/deps/dep3/"&gt;&lt;span class="caps"&gt;DEP&lt;/span&gt;-3&lt;/a&gt;, which took another few hours.
After the first pass, I ended up with 38 patches and a much clearer idea of
what has been forwarded upstream and what hasn&amp;#8217;t; I currently have 5 patches
to forward or eliminate, down from&amp;nbsp;18.&lt;/p&gt;
&lt;p&gt;Good&amp;nbsp;things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don&amp;#8217;t lose any of my history.  Since all the patches remain applied to
   the tree in revision control (this is what &lt;code&gt;dpkg-source -x&lt;/code&gt; gives you, so
   it&amp;#8217;s the natural representation in revision control too), &lt;code&gt;bzr blame&lt;/code&gt;
   works just as you&amp;#8217;d expect and displays both upstream and Debian changes
   at once.  I rely on tools like blame a lot, and I really hate the way
   build-time patch systems make it hard to use revision control when the
   tree is in a built state, so this was a hard requirement for&amp;nbsp;me.&lt;/li&gt;
&lt;li&gt;I&amp;#8217;ve used patch tagging before, so I was expecting some benefits, but
   viscerally I feel much more in &lt;em&gt;control&lt;/em&gt;.  It&amp;#8217;s so much less laborious
   now to see what I need to do by way of forwarding.  I don&amp;#8217;t regret
   waiting for 3.0 (quilt) to become available, but I hadn&amp;#8217;t realised quite
   how much I was being held back&amp;nbsp;beforehand.&lt;/li&gt;
&lt;li&gt;Adding new patches is pretty natural, much more so than with build-time
   patch systems.  You can create and apply the patch, test-build, and
   commit when it works.  I much prefer this over having to clean the tree
   before committing (or commit just part of the tree, which is
   error-prone).  The more that committing to a Debian package feels like
   committing to an upstream project, the&amp;nbsp;better.&lt;/li&gt;
&lt;li&gt;There&amp;#8217;s definitely something to be said for
   &lt;a href="http://patch-tracker.debian.org/package/openssh"&gt;patch-tracker&lt;/a&gt; being
   more useful.  It deals with &lt;span class="caps"&gt;DEP&lt;/span&gt;-3 to the extent of linkifying URLs,
   although it might be nice if patch descriptions were displayed on the
   overview page for each&amp;nbsp;version.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bad&amp;nbsp;things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;#8217;s a bit awkward to set things up when checking out from revision
   control; I didn&amp;#8217;t really want to check in the &lt;code&gt;.pc&lt;/code&gt; directory, and the
   tree checks out in the patched state (as it should), so I needed some way
   for developers to get quilt working easily after a checkout.  This is
   sort of the reverse of the previous problem, where users had to do
   something special after &lt;code&gt;dpkg-source -x&lt;/code&gt;, and I consider it less serious
   so I&amp;#8217;m willing to put up with it.  I ended up with &lt;a href="http://bugs.debian.org/572204"&gt;a rune in
   debian/rules that ought to live somewhere more
   common&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Everything ends up represented twice in revision control: the patch
   files, plus the changes to the patched files themselves.  I&amp;#8217;m &lt;span class="caps"&gt;OK&lt;/span&gt; with
   this although it is a little&amp;nbsp;inelegant.&lt;/li&gt;
&lt;li&gt;Although I haven&amp;#8217;t had to do it yet, I expect that merging new upstream
   releases will be a bit harder.  bzr will deal with resolving conflicts in
   the patched files themselves, and that&amp;#8217;s why I use a revision control
   system after all, but then I&amp;#8217;ll have to go and refresh all the patches
   and will probably end up doing some of the same conflict resolution a
   second time.  I think the best answer right now is to &lt;code&gt;quilt pop -a&lt;/code&gt;,
   force a merge despite the modified working tree, and then &lt;code&gt;quilt push &amp;amp;&amp;amp;
   quilt refresh -pab&lt;/code&gt; until I get back to the top of the stack, modulo
   slight fiddliness when a patch disappears entirely; thus effectively
   using quilt&amp;#8217;s conflict resolution rather than bzr&amp;#8217;s.  I suppose this will
   serve as additional incentive to reduce my patch count.  I know that
   people have been working on making this work nicely with topgit, although
   I&amp;#8217;m certainly not going to put up with the rest of git due to that; I&amp;#8217;m
   happy to wait for looms to become usable and integrated.&amp;nbsp;:-)&lt;/li&gt;
&lt;li&gt;It would be nice if there were some standard &lt;span class="caps"&gt;DEP&lt;/span&gt;-3 way to note that a
   patch has been accepted or rejected upstream, beyond just putting it in
   the description.  In particular, it seems to me that listing patches
   accepted upstream could be used to speed up the process of merging new
   upstream&amp;nbsp;releases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the whole I&amp;#8217;m satisfied with this, and the benefits definitely outweigh
the costs.  Thanks to the dpkg team for all their work on&amp;nbsp;this!&lt;/p&gt;</content><category term="misc"/><category term="dpkg"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>parted 2.2 transition</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/parted-2.2-transition.html" rel="alternate"/><published>2010-03-22T01:12:48+00:00</published><updated>2010-03-22T01:12:48+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-03-22:/~cjwatson/blog/parted-2.2-transition.html</id><content type="html">&lt;p&gt;I&amp;#8217;ve started the &lt;a href="http://lists.debian.org/debian-release/2010/03/msg00121.html"&gt;transition of parted 2.2 to
unstable&lt;/a&gt;.
This is a major update needed for sensible support of newer hard disks with
alignment requirements different from the archaic cylinder alignment
tradition.  I posted to debian-boot with a &lt;a href="http://lists.debian.org/debian-boot/2010/03/msg00420.html"&gt;summary of the partman changes
involved&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"/><category term="parted"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>debhelper statistics</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debhelper-statistics.html" rel="alternate"/><published>2010-03-03T00:22:19+00:00</published><updated>2010-03-03T00:22:19+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-03-03:/~cjwatson/blog/debhelper-statistics.html</id><summary type="html">&lt;p&gt;I don&amp;#8217;t know if anyone else has been tracking this recently, but a while
back I got curious about the relative proportions of dh(1) and &lt;span class="caps"&gt;CDBS&lt;/span&gt; in the
archive, and started running some daily analysis on the Lintian lab.
Apologies for my poor graphing abilities, but the graph …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I don&amp;#8217;t know if anyone else has been tracking this recently, but a while
back I got curious about the relative proportions of dh(1) and &lt;span class="caps"&gt;CDBS&lt;/span&gt; in the
archive, and started running some daily analysis on the Lintian lab.
Apologies for my poor graphing abilities, but the graph is here
(occasionally&amp;nbsp;updated):&lt;/p&gt;
&lt;p&gt;&lt;img alt="debhelper statistics" src="http://people.debian.org/~cjwatson/dhstats.png"&gt;&lt;/p&gt;
&lt;p&gt;Although dh is still a bit behind &lt;span class="caps"&gt;CDBS&lt;/span&gt;, the steady upward trend is quite
striking - it looks set to break 20% soon, up from under 13% in September -
compared with &lt;span class="caps"&gt;CDBS&lt;/span&gt; which has been sitting within half a percentage point of
25% the whole&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;Incidentally, was that an ftpmaster trying to sign his name in the graph
over Christmas or something?&amp;nbsp;:-)&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Catching up</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/catching-up.html" rel="alternate"/><published>2010-02-21T20:04:55+00:00</published><updated>2010-02-21T20:04:55+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2010-02-21:/~cjwatson/blog/catching-up.html</id><summary type="html">&lt;p&gt;I did a bit of catching up on my Debian backlog over the last week or so.
Among the things I got round&amp;nbsp;to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I released man-db 2.5.7.  This was mostly an &amp;#8220;I&amp;#8217;ve been meaning to do
   this for ages&amp;#8221; kind of thing to reduce the bug …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;I did a bit of catching up on my Debian backlog over the last week or so.
Among the things I got round&amp;nbsp;to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I released man-db 2.5.7.  This was mostly an &amp;#8220;I&amp;#8217;ve been meaning to do
   this for ages&amp;#8221; kind of thing to reduce the bug list a bit, closing ten
   Debian bugs, but there were a few interesting things in there as well,
   such as always saving cat pages in &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 and recoding to the user&amp;#8217;s
   locale at display time (long overdue), adjusting the search order for
   localised manual pages by request of quite a few non-native English
   speakers to prefer a page in the right section over a page in the right
   language, and a cute gimmick to make things like &lt;code&gt;man /usr/bin/time&lt;/code&gt;
   display the appropriate manual page rather than the text of the
   executable.  See the &lt;a href="http://git.savannah.gnu.org/cgit/man-db.git/tree/NEWS"&gt;&lt;span class="caps"&gt;NEWS&lt;/span&gt;
   file&lt;/a&gt; for more&amp;nbsp;details.&lt;/li&gt;
&lt;li&gt;binfmt-support now &lt;a href="http://bugs.debian.org/565109"&gt;installs cleanly on non-Linux
   systems&lt;/a&gt;, even if it doesn&amp;#8217;t do anything
   useful&amp;nbsp;yet.&lt;/li&gt;
&lt;li&gt;I fixed a couple of &lt;a href="http://bugs.debian.org/256226"&gt;shell&lt;/a&gt;
   &lt;a href="http://bugs.debian.org/547750"&gt;bugs&lt;/a&gt; in&amp;nbsp;groff.&lt;/li&gt;
&lt;li&gt;halibut now &lt;a href="http://bugs.debian.org/464821"&gt;complies with the Debian Vim
   policy&lt;/a&gt;, even though I can&amp;#8217;t say I
   entirely agree with it in this&amp;nbsp;case.&lt;/li&gt;
&lt;li&gt;I fixed a &lt;a href="http://lists.debian.org/debian-devel-changes/2010/02/msg02219.html"&gt;really odd build failure in
   troffcvt&lt;/a&gt;.
   Yay imake, or&amp;nbsp;something.&lt;/li&gt;
&lt;li&gt;All Debian patches to putty are now upstream, or will be once I upload a
   new snapshot.  Thanks to Simon Tatham and Jacob&amp;nbsp;Nevins.&lt;/li&gt;
&lt;li&gt;I did a few bits and pieces of packaging cleanup with an eye on my
   &lt;a href="http://qa.debian.org/developer.php"&gt;&lt;span class="caps"&gt;DDPO&lt;/span&gt;&lt;/a&gt; list, and added some watch
   files where they were&amp;nbsp;missing.&lt;/li&gt;
&lt;li&gt;Responded to an offer to take over icoutils&amp;nbsp;maintenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So nothing really earth-shaking, and as ever &lt;a href="http://lists.debian.org/debian-ssh/2010/01/msg00017.html"&gt;openssh could use some
attention&lt;/a&gt;, but I
feel a bit better about my backlog now.  I do still have a &lt;a href="http://bugs.debian.org/564559"&gt;critical bug in
makepasswd&lt;/a&gt; to fix, and a sponsored upload of
parrot; those are the next two things on my to-do&amp;nbsp;list.&lt;/p&gt;</content><category term="misc"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Tissue of lies</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/tissue-of-lies.html" rel="alternate"/><published>2009-11-13T17:37:36+00:00</published><updated>2009-11-13T19:56:01+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-11-13:/~cjwatson/blog/tissue-of-lies.html</id><summary type="html">&lt;p&gt;In case it isn&amp;#8217;t obvious, in &lt;a href="http://ubuman.wordpress.com/2009/11/13/ubuntu-9-10-sp1-coming-in-spring-2010/"&gt;&amp;#8220;Ubuntu 9.10 &lt;span class="caps"&gt;SP1&lt;/span&gt; coming in spring
2010&amp;#8221;&lt;/a&gt;,
&amp;#8220;Ubuman&amp;#8221; is blatantly lying in attributing a number of statements to me.
None of the text there was written by me, and if you thought any of it was
true then you should probably make …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In case it isn&amp;#8217;t obvious, in &lt;a href="http://ubuman.wordpress.com/2009/11/13/ubuntu-9-10-sp1-coming-in-spring-2010/"&gt;&amp;#8220;Ubuntu 9.10 &lt;span class="caps"&gt;SP1&lt;/span&gt; coming in spring
2010&amp;#8221;&lt;/a&gt;,
&amp;#8220;Ubuman&amp;#8221; is blatantly lying in attributing a number of statements to me.
None of the text there was written by me, and if you thought any of it was
true then you should probably make sure your troll radar is working
properly.  Nice joke, but try harder next time - it doesn&amp;#8217;t even look like
my writing&amp;nbsp;style.&lt;/p&gt;
&lt;p&gt;(I wouldn&amp;#8217;t normally bother to respond, since I&amp;#8217;m probably just giving it
more publicity, but apparently one or two people may already have been taken
in by it.  One person was sensible enough to write to me and check the&amp;nbsp;facts.)&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Keysigning bits</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/keysigning-bits.html" rel="alternate"/><published>2009-07-31T11:31:44+00:00</published><updated>2009-07-31T11:31:44+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-07-31:/~cjwatson/blog/keysigning-bits.html</id><summary type="html">&lt;p&gt;If you&amp;#8217;re generating one of these shiny new &lt;span class="caps"&gt;RSA&lt;/span&gt; keys, do please remember to
&lt;a href="http://ekaia.org/blog/2009/05/10/creating-new-gpgkey/"&gt;generate an encryption subkey
too&lt;/a&gt; if you expect
people to sign it - at least your more obscure UIDs.  I&amp;#8217;m not going to mail
unencrypted signatures around unless I have some out-of-band knowledge that
the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you&amp;#8217;re generating one of these shiny new &lt;span class="caps"&gt;RSA&lt;/span&gt; keys, do please remember to
&lt;a href="http://ekaia.org/blog/2009/05/10/creating-new-gpgkey/"&gt;generate an encryption subkey
too&lt;/a&gt; if you expect
people to sign it - at least your more obscure UIDs.  I&amp;#8217;m not going to mail
unencrypted signatures around unless I have some out-of-band knowledge that
the e-mail address actually belongs to the person I&amp;nbsp;met.&lt;/p&gt;
&lt;p&gt;I generated a new 4096-bit &lt;span class="caps"&gt;RSA&lt;/span&gt; key myself at DebConf (baa!), and have just
published a &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/key-transition"&gt;key transition
document&lt;/a&gt;.
Please consider signing my new key if you signed my old&amp;nbsp;one.&lt;/p&gt;</content><category term="misc"/><category term="keysigning"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>man-db: ‘man -K’</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-K.html" rel="alternate"/><published>2009-07-14T15:36:45+00:00</published><updated>2009-07-14T15:36:45+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-07-14:/~cjwatson/blog/man-db-K.html</id><summary type="html">&lt;p&gt;I recently implemented &lt;code&gt;man -K&lt;/code&gt; (full-text search over all manual pages) in
&lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt;.  This was inspired by a similar feature
in Federico Lucifredi&amp;#8217;s &lt;a href="http://primates.ximian.com/~flucifredi/man/"&gt;man&lt;/a&gt;
package (formerly maintained by Andries Brouwer).  I think I did a much
better job of it, though.  The man package just forks grep for every …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently implemented &lt;code&gt;man -K&lt;/code&gt; (full-text search over all manual pages) in
&lt;a href="http://man-db.nongnu.org/"&gt;man-db&lt;/a&gt;.  This was inspired by a similar feature
in Federico Lucifredi&amp;#8217;s &lt;a href="http://primates.ximian.com/~flucifredi/man/"&gt;man&lt;/a&gt;
package (formerly maintained by Andries Brouwer).  I think I did a much
better job of it, though.  The man package just forks grep for every manual
page; man-db takes advantage of the pipeline library I wrote for it a while
back and does it entirely in-process (decompression requires a fork but no
exec, while the man package has to exec gunzip as&amp;nbsp;well).&lt;/p&gt;
&lt;p&gt;The upshot is that, with a hot cache, man-db takes around 40 seconds to
search all manual pages on my laptop; the man package (also with a hot
cache) takes around five minutes, and interactive performance goes down the
drain while it&amp;#8217;s doing it since it&amp;#8217;s spawning subprocesses like crazy.  If I
limit to a single section, the disparity is closer to 3x than 10x, but it&amp;#8217;s
still very noticeable.  It&amp;#8217;s interesting how much good libraries can do to
help guide efficient approaches to&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;Of course, a proper full-text search engine would be much better still, but
that&amp;#8217;s a project for some other time&amp;nbsp;&amp;#8230;&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Python SIGPIPE handling</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/python-sigpipe.html" rel="alternate"/><published>2009-07-02T08:14:26+00:00</published><updated>2009-07-02T08:14:26+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-07-02:/~cjwatson/blog/python-sigpipe.html</id><summary type="html">&lt;p&gt;&lt;a href="http://www.enricozini.org/2009/debian/python-pipes/"&gt;Enrico&lt;/a&gt; writes about
creating pipelines with Python&amp;#8217;s &lt;code&gt;subprocess&lt;/code&gt; module, and notes that you
need to take care to close stdout in non-final subprocesses so that
subprocesses get &lt;code&gt;SIGPIPE&lt;/code&gt; correctly.  This is correct as far as it goes
(and true in any language, although there&amp;#8217;s a &lt;a href="http://bugs.python.org/issue1615376"&gt;Python bug report …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="http://www.enricozini.org/2009/debian/python-pipes/"&gt;Enrico&lt;/a&gt; writes about
creating pipelines with Python&amp;#8217;s &lt;code&gt;subprocess&lt;/code&gt; module, and notes that you
need to take care to close stdout in non-final subprocesses so that
subprocesses get &lt;code&gt;SIGPIPE&lt;/code&gt; correctly.  This is correct as far as it goes
(and true in any language, although there&amp;#8217;s a &lt;a href="http://bugs.python.org/issue1615376"&gt;Python bug report requesting
that &lt;code&gt;subprocess&lt;/code&gt; be able to do this
itself&lt;/a&gt;, but there&amp;#8217;s an additional
gotcha with Python that you&amp;nbsp;missed.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;Python ignores &lt;code&gt;SIGPIPE&lt;/code&gt; on startup, because it prefers to check every write
and raise an &lt;code&gt;IOError&lt;/code&gt; exception rather than taking the signal.  This is all
well and good for Python itself, but most Unix subprocesses don&amp;#8217;t expect to
work this way.  Thus, when you are creating subprocesses from Python, it is
&lt;strong&gt;very important&lt;/strong&gt; to set &lt;code&gt;SIGPIPE&lt;/code&gt; back to the default action.  Before I
realised this was necessary, I wrote code that caused serious data loss due
to a child process carrying on out of control after its parent process&amp;nbsp;died!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;signal&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;subprocess&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;subprocess_setup&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Python installs a SIGPIPE handler by default. This is usually not what&lt;/span&gt;
    &lt;span class="c1"&gt;# non-Python subprocesses expect.&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGPIPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIG_DFL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preexec_fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess_setup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I filed a &lt;a href="http://bugs.python.org/issue1652"&gt;patch&lt;/a&gt; a while back to add a
&lt;code&gt;restore_sigpipe&lt;/code&gt; option to &lt;code&gt;subprocess.Popen&lt;/code&gt;, which would take care of
this.  As I say in that bug report, in a future release I think this ought
to be made the default, as it&amp;#8217;s very easy to get things dangerously wrong
right&amp;nbsp;now.&lt;/p&gt;</content><category term="misc"/><category term="python"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>code_swarm video of Ubuntu uploads</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/code_swarm.html" rel="alternate"/><published>2009-05-28T20:29:55+00:00</published><updated>2009-05-28T20:32:12+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-05-28:/~cjwatson/blog/code_swarm.html</id><summary type="html">&lt;p&gt;Joey Hess posted a
&lt;a href="http://lists.debian.org/debian-boot/2009/05/msg00265.html"&gt;draft&lt;/a&gt; of a
&lt;a href="http://code.google.com/p/codeswarm/"&gt;code_swarm&lt;/a&gt; video for d-i a couple of
weeks ago, which reminded me that I&amp;#8217;ve been meaning to do something similar
for Ubuntu for a while now as it&amp;#8217;s just about our archive&amp;#8217;s fifth birthday.
I have a more or less …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Joey Hess posted a
&lt;a href="http://lists.debian.org/debian-boot/2009/05/msg00265.html"&gt;draft&lt;/a&gt; of a
&lt;a href="http://code.google.com/p/codeswarm/"&gt;code_swarm&lt;/a&gt; video for d-i a couple of
weeks ago, which reminded me that I&amp;#8217;ve been meaning to do something similar
for Ubuntu for a while now as it&amp;#8217;s just about our archive&amp;#8217;s fifth birthday.
I have a more or less complete archive of all our -changes mailing lists
locally (I think I&amp;#8217;m missing some of the very early ones, before the end of
July 2004; let me know if you were one of the very early Canonical employees
and have a record of these), and with the aid of
&lt;a href="https://help.launchpad.net/API/launchpadlib"&gt;launchpadlib&lt;/a&gt; it&amp;#8217;s fairly easy
to map all the e-mail addresses into Launchpad user names, massage out some
of the more obvious duplicates, and then treat the stream of uploads as if
it were a stream of&amp;nbsp;commits.&lt;/p&gt;
&lt;p&gt;If you haven&amp;#8217;t seen code_swarm before, each dot represents an upload, and
the dots &amp;#8220;swarm&amp;#8221; around their corresponding committers&amp;#8217; names; more active
committers have larger swarms of dots and brighter names.  I assigned a
colour to each of our archive components (uploads aren&amp;#8217;t really at the C
code vs. Python code vs. translations vs. whatever kind of granularity that
you see in other code_swarm videos), which mostly means that people who
predominantly upload to main are in roughly an Ubuntu tan colour, people who
predominantly upload to universe are coloured bluish, and people with a good
mixture tend to come out coloured green.  If I get a bit more time I may try
to figure out enough about video editing software to add some&amp;nbsp;captions.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/ubuntu-uploads.ogv"&gt;video&lt;/a&gt; (194 &lt;span class="caps"&gt;MB&lt;/span&gt;).&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Bug triage, redux</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/bug-triage-redux.html" rel="alternate"/><published>2009-03-05T11:04:02+00:00</published><updated>2009-03-05T11:04:02+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-03-05:/~cjwatson/blog/bug-triage-redux.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve been a bit surprised by the strong positive response to my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/bug-triage-rants.html"&gt;previous
post&lt;/a&gt;.
People generally seemed to think it was quite non-ranty; maybe I should
clean the rust off my flamethrower. :-)  My hope was that I&amp;#8217;d be able to
persuade people to change some practices, so I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve been a bit surprised by the strong positive response to my &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/bug-triage-rants.html"&gt;previous
post&lt;/a&gt;.
People generally seemed to think it was quite non-ranty; maybe I should
clean the rust off my flamethrower. :-)  My hope was that I&amp;#8217;d be able to
persuade people to change some practices, so I guess that&amp;#8217;s a good&amp;nbsp;thing.&lt;/p&gt;
&lt;p&gt;Of course, there are many very smart people doing bug triage very well, and
I don&amp;#8217;t want to impugn their fine work.  Like its medical namesake, bug
triage is a skilled discipline.  While it&amp;#8217;s often repetitive, and there are
lots of people showing up with similar symptoms, a triage nurse can really
make a difference by spotting urgent cases, cleaning up some of the initial
blood, and referring the patient quickly to a doctor for attention.  Or, if
a pattern of cases suddenly appears, a triage nurse might be able to warn of
an incipient epidemic.  [Note: I have no medical experience, so please
excuse me if I&amp;#8217;m talking crap here. :-)]  The bug triagers who do this well
are an absolute godsend; especially when they respond to repetitive tasks
with tremendously useful pieces of automation like
&lt;a href="https://launchpad.net/bughelper"&gt;bughelper&lt;/a&gt;.  The cases I have trouble with
are more like somebody showing up untrained, going through everyone in the
waiting room, and telling each of them that they just need to go home, get
some rest, and stop complaining so much.  Sometimes of course they&amp;#8217;ll be
right, but without taking the time to understand the problem they&amp;#8217;re
probably going to do more harm than&amp;nbsp;good.&lt;/p&gt;
&lt;p&gt;Ian Jackson reminded me that it&amp;#8217;s worth mentioning the purpose of bug
reports on free software: namely, &lt;strong&gt;to improve the software&lt;/strong&gt;.  The &lt;span class="caps"&gt;GNU&lt;/span&gt;
Project has some &lt;a href="http://www.gnu.org/prep/maintain/maintain.html#Mail"&gt;advice to
maintainers&lt;/a&gt; on this.
I think sometimes we stray into regarding bug reports more like support
tickets.  In that case it would be appropriate to focus on resolving each
case as quickly as possible, if necessary by means of a workaround rather
than by a software change, and only bother the developers when necessary.
This is the wrong way to look at bug reports, though.  The reason that we
needed to set up a bug triage community in Ubuntu was that we had a
relatively low developer-to-package ratio and a very high user-to-developer
ratio, and we were getting a lot of bug reports that weren&amp;#8217;t fleshed out
enough for a developer to investigate them without spending a lot of time in
back-and-forth with the reporter, so a number of people volunteered to take
care of the initial back-and-forth so that good clear bug reports could be
handed over to developers.  This is all well and good, and indeed I
encouraged it because I was personally finding myself unable to keep up with
incoming bugs and actually fix anything at the same time.  Somewhere along
the way, though, some people got the impression that what we wanted was a
first-line support firewall to try to defend developers from users, which of
course naturally leads to ideas such as closing wishlist bugs containing
ideas because obviously those important developers wouldn&amp;#8217;t want to be
bothered by them, and closing old bugs because clearly they must just be
getting in developers&amp;#8217; way.  Let me be clear about this now: I absolutely
appreciate help getting bug reports into a state where I can deal with them
efficiently, but &lt;strong&gt;I do not want to be defended from my users&lt;/strong&gt;!  I don&amp;#8217;t
have a basis from which to state that all developers feel the same way, but
my guess is that most&amp;nbsp;do.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://antti-juhani.kaijanaho.fi/newblog/archives/471"&gt;Antti-Juhani
Kaijanaho&lt;/a&gt; said he&amp;#8217;d
experienced most of these problems in Debian.  I hadn&amp;#8217;t actually intended my
post to go to Planet Debian - I&amp;#8217;d forgotten that the &amp;#8220;ubuntu&amp;#8221; category on my
blog goes there too, which generally I see as a feature, but if I&amp;#8217;d
remembered that I would have been a little clearer that I was talking about
Ubuntu bug triage.  If I had been talking about Debian bug triage I&amp;#8217;d
probably have emphasised different things.  Nevertheless, it&amp;#8217;s interesting
that at least one Debian (and non-Ubuntu) developer had experienced similar&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jldugger.livejournal.com/25994.html"&gt;Justin Dugger&lt;/a&gt; mentions a
practice of marking duplicate bugs invalid that he has problems with.  I
agree that this is suboptimal and try not to do it myself.  That said, this
is not something I object to to the same extent.  Given that the purpose of
bugs is to improve the software, the real goal is to be able to spend more
time fixing bugs, not to get bugs into the ideal state when the underlying
problem has already been solved.  If it&amp;#8217;s a choice between somebody having
to spend time tracking down the exact duplicate bug number versus fixing
another bug, I know which I&amp;#8217;d take.  Obviously, when doing this, it&amp;#8217;s worth
apologising that you weren&amp;#8217;t able to find the original bug number, and
explaining what the user can do if they believe that you&amp;#8217;re mistaken
(particularly if it&amp;#8217;s a bug that&amp;#8217;s believed to be fixed); the stock text
people often use for this doesn&amp;#8217;t seem informative enough to&amp;nbsp;me.&lt;/p&gt;
&lt;p&gt;Sebastien Bacher commented that preferred bug triage practices differ among
teams: for instance, the Ubuntu desktop team deals with packages that are
very much to the forefront of users&amp;#8217; attention and so get a lot of duplicate
bugs.  Indeed - and bug triagers who are working closely with the desktop
team on this are almost certainly doing things the way the developers on the
desktop team prefer, so I have no problem with that.  The best advice I can
give bug triagers is that their ultimate aim is to help developers, and so
they should figure out which developers they need to work with and &lt;strong&gt;go and
talk to them&lt;/strong&gt;!  That way, rather than duplicating work or being
counterproductive, they can tailor their work to be most effective.
Everybody&amp;nbsp;wins.&lt;/p&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Bug triage rants</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/bug-triage-rants.html" rel="alternate"/><published>2009-03-02T14:51:37+00:00</published><updated>2009-03-02T14:51:37+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2009-03-02:/~cjwatson/blog/bug-triage-rants.html</id><summary type="html">&lt;p&gt;I hate to say this, but often when somebody does lots of bug triage on a
package I work on, I find it to be a net loss for me.  I end up having to go
through all the things that were changed, correct a bunch of them,
occasionally pacify …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I hate to say this, but often when somebody does lots of bug triage on a
package I work on, I find it to be a net loss for me.  I end up having to go
through all the things that were changed, correct a bunch of them,
occasionally pacify angry bug submitters, and all the rest of it, and often
the benefits are minimal at&amp;nbsp;best.&lt;/p&gt;
&lt;p&gt;I would very much like this not to be the case.  Bug triage is supposed to
help developers be more efficient, and I think most people who do bug triage
are generally well-intentioned and eager to help.  Accordingly, here is a
series of mini-rants intended to have educational&amp;nbsp;value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bugs are not like&amp;nbsp;fruit.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fruit goes bad if you leave it too long.  By and large, bugs don&amp;#8217;t,
especially if they&amp;#8217;re on software that doesn&amp;#8217;t change very much.  There
is no reason why a bug filed against a package in Ubuntu 4.10 where the
relevant code hasn&amp;#8217;t changed much since shouldn&amp;#8217;t still be perfectly
valid.  Even if it isn&amp;#8217;t, it deserves proper&amp;nbsp;consideration.&lt;/p&gt;
&lt;p&gt;My biggest single annoyance with bug triage is people coming around and
asking if bugs are still valid when they haven&amp;#8217;t put any effort into
reproducing them themselves.  This annoys bug submitters too; every so
often somebody replies and says &amp;#8220;didn&amp;#8217;t you even bother to check?&amp;#8221;.
This gives a very bad impression of us as a project - wouldn&amp;#8217;t it be
better if we looked as if we knew what we were talking about?  There is
a good reason to do this kind of check, of course: random undiagnosed
crash reports and the like may well go away due to related changes, and
it is occasionally worth checking.  But if the bug is already
well-understood and/or well-described, you should just go and check
whether it&amp;#8217;s still there rather than&amp;nbsp;asking.&lt;/p&gt;
&lt;p&gt;As I understand it, the intended workflow is that people file bugs, then
if they aren&amp;#8217;t clear enough bug triagers work with the submitter to
gather information until they are, then they&amp;#8217;re passed to developers for
further work.  We seem to have added an extra step wherein submitters
must periodically give their bug a health-check, and if they don&amp;#8217;t then
it gets closed as being out of date.  In a small minority of cases this
is useful; in most cases, frankly, it makes us look a bit clueless.  Can
we please stop doing this?  The more we waste people&amp;#8217;s time doing this,
the less likely it is that they&amp;#8217;ll bother to respond to us, and this
might help our statistics but doesn&amp;#8217;t help the project as a&amp;nbsp;whole.&lt;/p&gt;
&lt;p&gt;I know that there&amp;#8217;s a problem with bug count.  I think every project of
non-trivial size has that problem.  But, honestly, the right answer is
to &lt;em&gt;fix more bugs&lt;/em&gt; - and, personally, I would be able to spend more time
doing that if I weren&amp;#8217;t often running around trying to make sure that
bugs I care about aren&amp;#8217;t getting overenthusiastically closed just
because somebody thinks they&amp;#8217;ve been lying around too&amp;nbsp;long.&lt;/p&gt;
&lt;p&gt;There is a good way to expire bugs like this, of course.  It goes
something like this: &amp;#8220;I&amp;#8217;ve read through your bug and tried to reproduce
it with a current release, but I&amp;#8217;m afraid I can&amp;#8217;t do so.  Are you still
experiencing it?  If not, then I think it might have been fixed by [this
change I found in the package&amp;#8217;s history that seems to be related].&amp;#8221;  You
can&amp;#8217;t do this &lt;em&gt;en masse&lt;/em&gt;, but you&amp;#8217;ll get a much better response from
submitters, you&amp;#8217;ll learn more doing it, and in the process of doing the
necessary investigation of each bug you&amp;#8217;ll find that there are many
cases you don&amp;#8217;t have to ask about at&amp;nbsp;all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wishlist bugs are not intrinsically&amp;nbsp;bad.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are certainly cases where something is far too broad or vague for
a bug report; but there are also plenty of cases, probably far more,
where the wish in question is a relatively small change to the program,
or doesn&amp;#8217;t need any more sophisticated tracking, and a wishlist bug is
just right.  If you don&amp;#8217;t know the program very well, it may be
difficult to tell whether a wishlist bug is appropriate or not; in that
case, just leave the bug&amp;nbsp;alone.&lt;/p&gt;
&lt;p&gt;Please, for the love of all that&amp;#8217;s holy, don&amp;#8217;t close wishlist bugs
saying that people should use Brainstorm or write a specification
instead!  If you don&amp;#8217;t want to see wishlist bugs in your statistics,
just filter them out; it&amp;#8217;s quite easy to do.  Even worse, don&amp;#8217;t tell
people that something probably isn&amp;#8217;t a good idea when you aren&amp;#8217;t
familiar with the software; people who have gone to the effort of
writing up their idea for us deserve a response from somebody who knows
the software well.  I&amp;#8217;ve encountered cases where friends of mine
submitted a bug report (sometimes even at my request) and then a triager
told them it was a bad idea and closed their bug.  This sort of thing
puts people off&amp;nbsp;Ubuntu.&lt;/p&gt;
&lt;p&gt;Specifications are software design documents.  As such, they are best
written by software designers.  People who tell other people to go and
write a specification may not realise that as a result of doing this for
three years it&amp;#8217;s now essentially impossible to find anything in the
specification system!  The intent was never that every user of Ubuntu
would need to write a specification to get anything changed;
specifications are used by developers to document the results of
discussions and write up plans.  They are not a straightforward
alternative to wishlist bugs, nor do they turn out to work very well as
what many formal processes call &amp;#8220;requirements documents&amp;#8221;; the process of
refining the latter in the context of Ubuntu might involve wishlist
bugs, mailing list threads, wiki pages, private discussions with
developers, or things of that nature, and probably shouldn&amp;#8217;t involve
creating a specification until the requirements-gathering process is
well&amp;nbsp;underway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Closing a bug is taking an item off somebody&amp;#8217;s to-do&amp;nbsp;list.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You wouldn&amp;#8217;t go up to a colleague&amp;#8217;s whiteboard and take an eraser to it
unless you were sure that was &lt;span class="caps"&gt;OK&lt;/span&gt;, would you?  Yet people seem to do that
all the time with bugs.  It&amp;#8217;s &lt;span class="caps"&gt;OK&lt;/span&gt; when the bug is really just like a
support request - &amp;#8220;help, it crashed, what do I do?&amp;#8221; - and either you&amp;#8217;re
pretty sure it&amp;#8217;s user error or there&amp;#8217;s just no way to get enough
information to fix it.  But once the initial triage process is done, now
it&amp;#8217;s on somebody&amp;#8217;s to-do&amp;nbsp;list.&lt;/p&gt;
&lt;p&gt;This is closely related to&amp;nbsp;&amp;#8230;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If a developer has accepted it, leave it&amp;nbsp;alone.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every so often I find that there&amp;#8217;s a bug that I have accepted by way of
a bug comment or setting to Triaged or whatever, or even a bug that I
filed on a package I work on as a reminder to myself, and somebody comes
along and asks for more information or asks if we can still reproduce it
or something.  The hit rate on this kind of thing is extraordinarily
low.  There&amp;#8217;s a good chance that the developer went and verified the bug
against the code, and in that case it certainly doesn&amp;#8217;t need more
information (or they would have asked for it) and it probably isn&amp;#8217;t
going to go away without anyone&amp;nbsp;noticing.&lt;/p&gt;
&lt;p&gt;In most other free software projects, developers file bug reports
themselves as a reminder about things that need to be done, and people
leave them alone unless they&amp;#8217;re intending to help with the fix.  In
Ubuntu, developers also have to spend time making sure that those to-do
items don&amp;#8217;t get expired.  Nobody is helped by&amp;nbsp;this.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://launchpad.net/launchpad-gm-scripts"&gt;launchpad-gm-scripts&lt;/a&gt;
includes a Greasemonkey script called &lt;code&gt;lp_karma_suffix&lt;/code&gt;, which can help
you to identify developers without having to spend lots of time clicking&amp;nbsp;around.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check whether the package is being actively worked&amp;nbsp;on.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some packages are actively worked on in Ubuntu; some aren&amp;#8217;t (e.g. we
just sync packages from Debian, or they&amp;#8217;re basically orphaned, or
whatever).  It&amp;#8217;s worth checking which is which before doing any kind of
extensive triage work.  If it&amp;#8217;s being actively worked on, why not go and
talk to the developer(s) in question first?  It&amp;#8217;s only polite, and it
will probably help you to do a better&amp;nbsp;job.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><category term="ubuntu"/><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Totem BBC plugin</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/totem-bbc-plugin.html" rel="alternate"/><published>2008-10-27T12:40:48+00:00</published><updated>2008-10-27T12:40:48+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-10-27:/~cjwatson/blog/totem-bbc-plugin.html</id><summary type="html">&lt;p&gt;A while back, the &lt;a href="http://www.bbc.co.uk/"&gt;&lt;span class="caps"&gt;BBC&lt;/span&gt;&lt;/a&gt; approached
&lt;a href="http://www.canonical.com/"&gt;Canonical&lt;/a&gt; about providing seamless access to
unencumbered &lt;span class="caps"&gt;BBC&lt;/span&gt; content for all &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; users (in
the &lt;span class="caps"&gt;UK&lt;/span&gt; and elsewhere).  We agreed to approach this by way of a plugin for
our primary media player, &lt;a href="http://www.gnome.org/projects/totem/"&gt;Totem&lt;/a&gt;, and
asked &lt;a href="http://www.collabora.co.uk/"&gt;Collabora Multimedia&lt;/a&gt; to do the plugin
development&amp;nbsp;work …&lt;/p&gt;</summary><content type="html">&lt;p&gt;A while back, the &lt;a href="http://www.bbc.co.uk/"&gt;&lt;span class="caps"&gt;BBC&lt;/span&gt;&lt;/a&gt; approached
&lt;a href="http://www.canonical.com/"&gt;Canonical&lt;/a&gt; about providing seamless access to
unencumbered &lt;span class="caps"&gt;BBC&lt;/span&gt; content for all &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; users (in
the &lt;span class="caps"&gt;UK&lt;/span&gt; and elsewhere).  We agreed to approach this by way of a plugin for
our primary media player, &lt;a href="http://www.gnome.org/projects/totem/"&gt;Totem&lt;/a&gt;, and
asked &lt;a href="http://www.collabora.co.uk/"&gt;Collabora Multimedia&lt;/a&gt; to do the plugin
development&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;The results are in what will shortly be released as Ubuntu 8.10, and are
looking really rather good.  At the moment the content available from the
&lt;span class="caps"&gt;BBC&lt;/span&gt; at present is mostly audio, but support for video is in place and the
feed is expected to be fleshed out here over time.  We have a genre
classification scheme in place, and will see how that scales as the amount
of available content grows.  The code has been &lt;a href="http://bugzilla.gnome.org/show_bug.cgi?id=555823"&gt;submitted
upstream&lt;/a&gt;, although there
are still a few issues to work out&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;This is not the same thing as iPlayer; all the content available here is
&lt;span class="caps"&gt;DRM&lt;/span&gt;-free.  Some of it is geographically restricted to the &lt;span class="caps"&gt;UK&lt;/span&gt;, and these
restrictions are handled on the server side to make sure that the client is
free of&amp;nbsp;encumbrances.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.gnome.org/uraeus/"&gt;Christian Schaller&lt;/a&gt; from Collabora
&lt;a href="http://blogs.gnome.org/uraeus/2008/10/08/868/"&gt;posted&lt;/a&gt; about this a little
while ago.  Since then, the &lt;span class="caps"&gt;UI&lt;/span&gt; has been improved somewhat and some I/O
issues have been fixed to the point where we felt comfortable enabling the
&lt;span class="caps"&gt;BBC&lt;/span&gt; plugin (as well as the YouTube plugin) by default in Ubuntu 8.10.
Here&amp;#8217;s a screenshot of the current&amp;nbsp;interface:&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/totem-bbc-2.png"&gt;&lt;/p&gt;
&lt;p&gt;This is exciting stuff with a lot of potential.  To try it out, run
Applications -&amp;gt; Sound &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Video -&amp;gt; Movie Player and select the &amp;#8220;&lt;span class="caps"&gt;BBC&lt;/span&gt;&amp;#8221; entry
from the drop-down box labelled &amp;#8220;Playlist&amp;#8221;.  If you find bugs, please
&lt;a href="https://bugs.launchpad.net/ubuntu/+source/totem/+filebug"&gt;report&lt;/a&gt;&amp;nbsp;them!&lt;/p&gt;</content><category term="ubuntu"/><category term="planet-ubuntu"/></entry><entry><title>Re: Perl is strange</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/reply-perl-is-strange.html" rel="alternate"/><published>2008-06-23T15:58:08+00:00</published><updated>2008-06-23T15:59:12+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-06-23:/~cjwatson/blog/reply-perl-is-strange.html</id><content type="html">&lt;p&gt;&lt;a href="http://www.df7cb.de/blog/2008/Perl_is_strange.html"&gt;Christoph&lt;/a&gt;: That&amp;#8217;s
because &lt;code&gt;=~&lt;/code&gt; binds more tightly than &lt;code&gt;+&lt;/code&gt;.  This does what you&amp;nbsp;meant:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;perl&lt;span class="w"&gt; &lt;/span&gt;-le&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;print &amp;quot;yoo&amp;quot; if (1 + 1) =~ /3/&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;perlop(1)&lt;/code&gt; has a useful table of&amp;nbsp;precedence.&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/></entry><entry><title>Don’t use sshkeygen.com to generate keys!</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/ssh-keygen.html" rel="alternate"/><published>2008-06-23T09:31:57+00:00</published><updated>2008-06-23T09:54:53+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-06-23:/~cjwatson/blog/ssh-keygen.html</id><summary type="html">&lt;p&gt;To my horror, I recently saw &lt;a href="http://www.sshkeygen.com/"&gt;this online &lt;span class="caps"&gt;SSH&lt;/span&gt; key
generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope nobody reading this needs to be told why this is a bad idea.
However, in case you do, here are a few&amp;nbsp;reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every &lt;span class="caps"&gt;SSH&lt;/span&gt; implementation I know of - certainly all the major ones - that
   support public …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;To my horror, I recently saw &lt;a href="http://www.sshkeygen.com/"&gt;this online &lt;span class="caps"&gt;SSH&lt;/span&gt; key
generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope nobody reading this needs to be told why this is a bad idea.
However, in case you do, here are a few&amp;nbsp;reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every &lt;span class="caps"&gt;SSH&lt;/span&gt; implementation I know of - certainly all the major ones - that
   support public key authentication also provide a key generation utility.
   Even aside from all the good reasons not to, there is simply no reason
   why you should need to use a web-based tool in the first&amp;nbsp;place.&lt;/li&gt;
&lt;li&gt;How can you trust the person running this site?  Without implying that I
   know he or she is untrustworthy (I don&amp;#8217;t), and with the best will in the
   world, it&amp;#8217;s a big Internet with a lot of nasty people on it.  Do you
   really want somebody you don&amp;#8217;t know in a position to keep a copy of all
   your private&amp;nbsp;keys?&lt;/li&gt;
&lt;li&gt;Even if the person is trustworthy, the server running sshkeygen.com is
   now a giant blinking target.  If lots of people use it, there is every
   incentive in the world for the bad guys to try to take control of it so
   that they can keep a copy of all your private keys.  (Or, as we know from
   recent bitter experience, they can just give out keys from a limited set
   and it will probably take a couple of years before anyone notices&amp;nbsp;&amp;#8230;)&lt;/li&gt;
&lt;li&gt;The front page of sshkeygen.com says that the keys are escrowed.  The
   plain English meaning of this would be that the operator of that site
   keeps a copy of the private key, to be held in trust in case (presumably)
   you lose it and need to retrieve it.  Normally this sort of thing depends
   on a legal trust relationship, perhaps linked to a contract.  What does
   it mean here?  Is it just a buzzword?  If it isn&amp;#8217;t, then this just makes
   sshkeygen.com even more of a&amp;nbsp;target.&lt;/li&gt;
&lt;li&gt;sshkeygen.com delivers keys to you over unencrypted &lt;span class="caps"&gt;HTTP&lt;/span&gt;.  Yes, this is
   on its &lt;a href="http://www.sshkeygen.com/about.php"&gt;to-do list&lt;/a&gt;.  That isn&amp;#8217;t
   really an&amp;nbsp;excuse.&lt;/li&gt;
&lt;li&gt;Even if keys were delivered over &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, that still relies on people
   diligently checking the authenticity of the certificate.  A
   self-signature (as suggested as an alternative in the to-do list) would
   be impossible to check with any reliability; and will people who have
   trouble with non-web-based key generation software really be able or
   inclined to confirm the signature chain?  Browsers typically don&amp;#8217;t
   enforce this very strictly, or if they do they provide fairly simple ways
   to bypass the enforcement, simply because so many sites have broken or
   poorly-signed &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates, and keeping up with all the CAs is pretty
   hard work&amp;nbsp;too.&lt;/li&gt;
&lt;li&gt;Furthermore, delivering private keys over &lt;span class="caps"&gt;HTTPS&lt;/span&gt; makes that &lt;span class="caps"&gt;SSL&lt;/span&gt;
   certificate a single giant blinking target.  Might it be compromised?
   How would you tell?  What servers would need to be compromised in order
   to get a copy of the private &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;nbsp;key?&lt;/li&gt;
&lt;li&gt;Sure, Debian is in an awkward position here given the recent OpenSSL
   random number generation vulnerability.  However, how do you know that
   sshkeygen.com is running on a system that doesn&amp;#8217;t suffer from this?  (As
   it happens, I have checked, and it doesn&amp;#8217;t appear to suffer from this
   vulnerability - but most people won&amp;#8217;t check and won&amp;#8217;t know how to&amp;nbsp;check.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I &lt;em&gt;think&lt;/em&gt; this is probably being done in innocent seriousness (although I
kind of hope it&amp;#8217;s a joke in poor taste), and have e-mailed the contact
address offering to explain why it&amp;#8217;s a bad&amp;nbsp;idea.&lt;/p&gt;</content><category term="misc"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Desktop automounting pain</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/desktop-automount-pain.html" rel="alternate"/><published>2008-04-12T07:46:12+00:00</published><updated>2008-04-12T07:46:12+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-04-12:/~cjwatson/blog/desktop-automount-pain.html</id><summary type="html">&lt;p&gt;Ubuntu&amp;#8217;s live &lt;span class="caps"&gt;CD&lt;/span&gt; installer, Ubiquity, needs to suppress desktop automounting
while it&amp;#8217;s doing partitioning and generally messing about with mount points,
otherwise its temporary mount points end up busy on unmount due to some
smart-arse desktop component that decides to open a window for&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;To date, it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ubuntu&amp;#8217;s live &lt;span class="caps"&gt;CD&lt;/span&gt; installer, Ubiquity, needs to suppress desktop automounting
while it&amp;#8217;s doing partitioning and generally messing about with mount points,
otherwise its temporary mount points end up busy on unmount due to some
smart-arse desktop component that decides to open a window for&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;To date, it employs the following methods, each of which was sufficient at
the&amp;nbsp;time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set the &lt;code&gt;/desktop/gnome/volume_manager/automount_drives&lt;/code&gt; and
   &lt;code&gt;/desktop/gnome/volume_manager/automount_media&lt;/code&gt; gconf keys to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Tell &lt;code&gt;kded&lt;/code&gt; to unload its &lt;code&gt;medianotifier&lt;/code&gt; module, and load it again just
   before the installer&amp;nbsp;exits.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;/apps/nautilus/desktop/volumes_visible&lt;/code&gt; gconf key to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;AutomountDrives&lt;/code&gt; and &lt;code&gt;AutomountMedia&lt;/code&gt; keys in
   &lt;code&gt;$HOME/.config/Thunar/volmanrc&lt;/code&gt; to &lt;code&gt;FALSE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;/apps/nautilus/preferences/media_automount&lt;/code&gt; and
   &lt;code&gt;/apps/nautilus/preferences/media_automount_open&lt;/code&gt; gconf keys to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The entire installer is run under &lt;code&gt;hal-lock --interface
   org.freedesktop.Hal.Device.Storage --exclusive&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;/apps/nautilus/preferences/media_autorun_never&lt;/code&gt; gconf key to
   &lt;code&gt;true&lt;/code&gt; (&lt;a href="https://bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/210620"&gt;experimental, but apparently now required since nautilus uses
   the gio volume
   monitor&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is getting &lt;strong&gt;ridiculous&lt;/strong&gt;.  Dear desktop implementors: please pick a
configuration mechanism and stick to it, and provide backward compatibility
if you can&amp;#8217;t.  This is not a rocket-science&amp;nbsp;concept.&lt;/p&gt;
&lt;p&gt;I rather liked the &lt;code&gt;hal-lock&lt;/code&gt; mechanism; it was simple and involved minimal
fuss.  I had hoped that it might end up as a standard, but I guess that
would be too&amp;nbsp;easy.&lt;/p&gt;</content><category term="ubuntu"/><category term="planet-ubuntu"/></entry><entry><title>Vim omni completion for Launchpad bugs</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/vim-lpbug-omnicomplete.html" rel="alternate"/><published>2008-01-31T11:17:58+00:00</published><updated>2008-01-31T11:19:27+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-01-31:/~cjwatson/blog/vim-lpbug-omnicomplete.html</id><summary type="html">&lt;p&gt;I hacked together a little timesaver for developers this morning: omni
completion for Launchpad bugs in Vim&amp;#8217;s debchangelog mode.  To use it,
install vim 7.1-138+1ubuntu3 once it hits the mirrors, open up a
&lt;code&gt;debian/changelog&lt;/code&gt; file, type &amp;#8220;&lt;span class="caps"&gt;LP&lt;/span&gt;: #&amp;#8221;, and hit Ctrl-X Ctrl-O.  It&amp;#8217;ll think
for a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I hacked together a little timesaver for developers this morning: omni
completion for Launchpad bugs in Vim&amp;#8217;s debchangelog mode.  To use it,
install vim 7.1-138+1ubuntu3 once it hits the mirrors, open up a
&lt;code&gt;debian/changelog&lt;/code&gt; file, type &amp;#8220;&lt;span class="caps"&gt;LP&lt;/span&gt;: #&amp;#8221;, and hit Ctrl-X Ctrl-O.  It&amp;#8217;ll think
for a while and then give you a list of all the bugs open in Launchpad
against the package in question, from which you can select to insert the bug
number into your&amp;nbsp;changelog.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a screenshot to make it&amp;nbsp;clearer:&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot" src="https://www.chiark.greenend.org.uk/~cjwatson/blog/images/lp-omnicomplete.png"&gt;&lt;/p&gt;
&lt;p&gt;Thanks to Stefano Zacchiroli for doing the same for Debian bugs back in&amp;nbsp;July.&lt;/p&gt;</content><category term="ubuntu"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>UTF-8 manual pages</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/utf-8-manual-pages.html" rel="alternate"/><published>2008-01-29T01:57:51+00:00</published><updated>2008-01-29T01:57:51+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2008-01-29:/~cjwatson/blog/utf-8-manual-pages.html</id><summary type="html">&lt;p&gt;See &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-encodings.html"&gt;Encodings in man-db&lt;/a&gt; for&amp;nbsp;context.&lt;/p&gt;
&lt;p&gt;Yesterday, I uploaded &lt;a href="http://lists.debian.org/debian-devel-changes/2008/01/msg02665.html"&gt;man-db
2.5.1-1&lt;/a&gt;
to unstable.  With this version, not only is it possible to install manual
pages in &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 (as with 2.5.0, although with fewer bugs), but it&amp;#8217;s also
possible to ask man to produce a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;See &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-encodings.html"&gt;Encodings in man-db&lt;/a&gt; for&amp;nbsp;context.&lt;/p&gt;
&lt;p&gt;Yesterday, I uploaded &lt;a href="http://lists.debian.org/debian-devel-changes/2008/01/msg02665.html"&gt;man-db
2.5.1-1&lt;/a&gt;
to unstable.  With this version, not only is it possible to install manual
pages in &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 (as with 2.5.0, although with fewer bugs), but it&amp;#8217;s also
possible to ask man to produce a version of an arbitrary page in the
encoding of your choice, and have it guess the source encoding for you
fairly reliably.  This finally provides enough support to have debhelper
&lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=462937"&gt;automatically recode manual pages to
&lt;span class="caps"&gt;UTF&lt;/span&gt;-8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;ll probably take a little while to shake out the corner-case bugs, but
I&amp;#8217;m generally pretty happy with this.  Once the new man-db and debhelper
land in testing, I&amp;#8217;ll send a note to debian-devel-announce and push harder
on my &lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=440420"&gt;policy
amendment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Considering the historical state of man-db when it comes to localisation,
and all of the dependencies and general yak-shaving that had to be tackled
to get here, this represents the end of probably several hundred hours of
work, so I&amp;#8217;m pretty happy that this is out the door.  The only remaining
step is to add &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 input support to groff, which fortunately Brian M.
Carlson is
&lt;a href="http://lists.gnu.org/archive/html/groff/2007-11/msg00018.html"&gt;working&lt;/a&gt;
&lt;a href="http://lists.gnu.org/archive/html/groff/2008-01/msg00004.html"&gt;on&lt;/a&gt;.  After
that, we can reasonably claim to have dragged manual pages kicking and
screaming into the 21st&amp;nbsp;century.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>aptitude safe-upgrade</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/safe-upgrade.html" rel="alternate"/><published>2007-11-29T20:51:23+00:00</published><updated>2007-11-29T20:51:23+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2007-11-29:/~cjwatson/blog/safe-upgrade.html</id><summary type="html">&lt;p&gt;&lt;a href="http://blog.drinsama.de/erich/en/linux/debian/2007112801-dist-upgrade-hints.html"&gt;Erich&lt;/a&gt;:
I do sometimes wonder why we don&amp;#8217;t relax the definition of &amp;#8220;safe&amp;#8221; upgrades
to include installing new packages but still not removing old ones.  I know
that many of my uses of dist-upgrade are just for when something grows a new
dependency that I didn&amp;#8217;t previously have …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="http://blog.drinsama.de/erich/en/linux/debian/2007112801-dist-upgrade-hints.html"&gt;Erich&lt;/a&gt;:
I do sometimes wonder why we don&amp;#8217;t relax the definition of &amp;#8220;safe&amp;#8221; upgrades
to include installing new packages but still not removing old ones.  I know
that many of my uses of dist-upgrade are just for when something grows a new
dependency that I didn&amp;#8217;t previously have&amp;nbsp;installed.&lt;/p&gt;
&lt;p&gt;(Of course this wouldn&amp;#8217;t always help as it wouldn&amp;#8217;t account for a new
dependency that conflicted with an old dependency, but never mind.  It would
certainly do wonders for the metapackage&amp;nbsp;case.)&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Encodings in man-db</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/man-db-encodings.html" rel="alternate"/><published>2007-09-17T07:28:20+00:00</published><updated>2007-09-17T07:28:20+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2007-09-17:/~cjwatson/blog/man-db-encodings.html</id><summary type="html">&lt;p&gt;I&amp;#8217;ve spent some quality upstream time lately with man-db.  Specifically,
I&amp;#8217;ve been upgrading its locale support.  I recently published a pre-release,
&lt;a href="http://people.debian.org/~cjwatson/man-db/man-db-2.5.0-pre2.tar.gz"&gt;man-db
2.5.0-pre2&lt;/a&gt;
mainly for translators, but other people may be interested in having a look
at it as well.  I hope to release 2.5 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;ve spent some quality upstream time lately with man-db.  Specifically,
I&amp;#8217;ve been upgrading its locale support.  I recently published a pre-release,
&lt;a href="http://people.debian.org/~cjwatson/man-db/man-db-2.5.0-pre2.tar.gz"&gt;man-db
2.5.0-pre2&lt;/a&gt;
mainly for translators, but other people may be interested in having a look
at it as well.  I hope to release 2.5.0 quite soon so that all of this can
land in&amp;nbsp;Debian.&lt;/p&gt;
&lt;p&gt;Firstly, man-db now supports creating and using databases for per-locale
hierarchies of manual pages, not just English.  This means that &lt;a href="http://bugs.debian.org/29448"&gt;apropos and
whatis can now display information about localised manual
pages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Secondly, I&amp;#8217;ve been working on the transition to &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 manual pages.  Now,
modulo some hacks, groff can&amp;#8217;t yet deal with Unicode input; some possible
input characters are reserved for its internal use which makes full 32-bit
input difficult to do properly until that&amp;#8217;s fixed.  However, with a few
exceptions, manual pages generally just need the subset of Unicode that
corresponds to their language&amp;#8217;s usual legacy character set, so for now it&amp;#8217;s
good enough to just recode on the fly from &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 to some appropriate 8-bit
character set and use groff&amp;#8217;s support for&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;man-db has actually supported doing this kind of thing for a while, but it&amp;#8217;s
been difficult to use since it only applies to &lt;code&gt;/usr/share/man/ll_CC.UTF-8/&lt;/code&gt;
directories, while manual pages usually aren&amp;#8217;t country-specific.  So, man-db
2.5.0 supports using &lt;code&gt;/usr/share/man/ll.UTF-8/&lt;/code&gt; instead, which is a bit more
appropriate.  Also, following a &lt;a href="http://lists.debian.org/debian-mentors/2007/09/msg00245.html"&gt;discussion with Adam
Borowski&lt;/a&gt;,
man-db can now try decoding manual pages as &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 and fall back to 8-bit
encodings even in directories without an explicit encoding tag; if this
fails for some reason, you can put a &lt;code&gt;'\" -*- coding: UTF-8 -*-&lt;/code&gt; line at the
top of the&amp;nbsp;page.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m still debating whether Debian policy should recommend installing &lt;span class="caps"&gt;UTF&lt;/span&gt;-8
manual pages in &lt;code&gt;/usr/share/man/ll.UTF-8/&lt;/code&gt; or just in &lt;code&gt;/usr/share/man/ll/&lt;/code&gt;.
Initially I was very strongly in favour of an encoding declaration, but now
that man-db can do a pretty good job of guesswork I&amp;#8217;m coming round to Adam
Borowski&amp;#8217;s position that people should be able to forget about character
sets with &lt;span class="caps"&gt;UTF&lt;/span&gt;-8.  Opinions here would be welcome.  One thing I haven&amp;#8217;t moved
on is that any design that assumes that the encoding of manual pages on the
filesystem has anything to do with the user&amp;#8217;s locale is demonstrably
incorrect and broken; I&amp;#8217;m not going to use &lt;code&gt;LC_CTYPE&lt;/code&gt; for anything except
output.  However, maybe &amp;#8220;&lt;span class="caps"&gt;UTF&lt;/span&gt;-8 or the usual legacy encoding provided that
the latter is not typically confused for the former&amp;#8221; is a good enough
specification, and that still has the desirable property of not requiring a
flag day.  I&amp;#8217;ll try to come down from the fence before unleashing this code
on the&amp;nbsp;world.&lt;/p&gt;</content><category term="man-db"/><category term="man-db"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Keysigning public service announcement</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/keysigning-psa.html" rel="alternate"/><published>2007-07-04T17:45:39+00:00</published><updated>2007-07-04T17:45:39+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2007-07-04:/~cjwatson/blog/keysigning-psa.html</id><content type="html">&lt;p&gt;If your key has so many UIDs and such a combinatorially exploded number of
signatures on it that it takes &lt;code&gt;gpg&lt;/code&gt; minutes just to start up in
&lt;code&gt;--edit-key&lt;/code&gt; mode, then I probably won&amp;#8217;t bother signing it.  &lt;span class="caps"&gt;HTH&lt;/span&gt;, &lt;span class="caps"&gt;HAND&lt;/span&gt;.&lt;/p&gt;</content><category term="misc"/><category term="keysigning"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Moving conffiles between packages, redux</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/moving-conffiles.html" rel="alternate"/><published>2006-12-23T23:37:08+00:00</published><updated>2006-12-23T23:37:08+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-12-23:/~cjwatson/blog/moving-conffiles.html</id><summary type="html">&lt;p&gt;I spent far too much of today cleaning up an upgrade bug to do with
conffiles, which I suspect also affects other packages that have attempted
to work around dpkg conffile prompts when moving conffiles between packages.
If you maintain such a package, please review your code to make sure …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I spent far too much of today cleaning up an upgrade bug to do with
conffiles, which I suspect also affects other packages that have attempted
to work around dpkg conffile prompts when moving conffiles between packages.
If you maintain such a package, please review your code to make sure that it
works properly when upgrading both with sarge&amp;#8217;s dpkg and with etch&amp;#8217;s dpkg.
See &lt;a href="http://lists.debian.org/debian-devel/2006/12/msg00647.html"&gt;my debian-devel&amp;nbsp;post&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;for a full&amp;nbsp;description.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="misc"/><category term="dpkg"/><category term="openssh"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Google Summer of Code project started (Ubuntu)</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/gsoc-ubiquity-migration-started.html" rel="alternate"/><published>2006-05-26T20:13:13+00:00</published><updated>2006-05-26T20:13:13+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-05-26:/~cjwatson/blog/gsoc-ubiquity-migration-started.html</id><summary type="html">&lt;p&gt;More on the &lt;a href="http://code.google.com/soc/"&gt;Google Summer of Code&lt;/a&gt;: as well as
the &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/gsoc-d-i-hurd-started.html"&gt;project I&amp;#8217;m mentoring for Debian&lt;/a&gt;,
I&amp;#8217;m mentoring Evan Dandrea (no blog yet?), writing a &lt;a href="https://wiki.ubuntu.com/MigrationAssistance"&gt;migration
assistant&lt;/a&gt; for&amp;nbsp;Ubiquity.&lt;/p&gt;
&lt;p&gt;I haven&amp;#8217;t talked much about Ubiquity, mostly because I&amp;#8217;ve been far too busy
writing it. Ubuntu has …&lt;/p&gt;</summary><content type="html">&lt;p&gt;More on the &lt;a href="http://code.google.com/soc/"&gt;Google Summer of Code&lt;/a&gt;: as well as
the &lt;a href="https://www.chiark.greenend.org.uk/~cjwatson/blog/gsoc-d-i-hurd-started.html"&gt;project I&amp;#8217;m mentoring for Debian&lt;/a&gt;,
I&amp;#8217;m mentoring Evan Dandrea (no blog yet?), writing a &lt;a href="https://wiki.ubuntu.com/MigrationAssistance"&gt;migration
assistant&lt;/a&gt; for&amp;nbsp;Ubiquity.&lt;/p&gt;
&lt;p&gt;I haven&amp;#8217;t talked much about Ubiquity, mostly because I&amp;#8217;ve been far too busy
writing it. Ubuntu has needed an installer for its live &lt;span class="caps"&gt;CD&lt;/span&gt; for a while,
partly because, well, loads of users want it, and partly because it will cut
Canonical&amp;#8217;s costs quite a lot if we only have to send out half the number of
CDs in shipit (apparently single-&lt;span class="caps"&gt;CD&lt;/span&gt; packaging is significantly cheaper than
double-&lt;span class="caps"&gt;CD&lt;/span&gt; packaging). I&amp;#8217;d been resisting doing something from scratch
because I love d-i and I think it would be a really bad idea to end up
maintaining two installer implementations from the ground up (live CDs are
nice, but they don&amp;#8217;t cut it for everyone). So when I was given the task of
doing a shiny live &lt;span class="caps"&gt;CD&lt;/span&gt; installer with a custom-designed &lt;span class="caps"&gt;UI&lt;/span&gt;, while I started
with a more-or-less from-scratch implementation put together by
&lt;a href="http://www.guadalinex.org/"&gt;Guadalinex&lt;/a&gt; (thanks!), I fairly quickly
diverged from that and morphed it into something that uses d-i code for as
much of the backend operation and logic as it sensibly can. I&amp;#8217;d call it a
sort of debconf frontend except that its design is almost opposite to how a
debconf frontend should work, in that it&amp;#8217;s highly specialised to react to
particular question names. This had a lot of advantages in terms of being
fairly quick to write, although in the long term I think I might prefer
something closer to cdebconf plugins for the job; we&amp;#8217;ll see how things turn&amp;nbsp;out.&lt;/p&gt;
&lt;p&gt;Evan wanted to write an extension to this to automatically migrate settings
and documents from an existing Windows installation, which I think would be
an absolutely excellent thing to have: automatic migration is a real killer
feature in an installer. In fact, d-i already has a start at this, namely
os-prober, which in conjunction with some bootloader installer code
magically sets up boot menu entries for other operating systems on your
disk. So, I suggested to Evan that he might want to put most of the clever
logic in a udeb, so that it can be used in d-i too, and to my relief he
seemed quite enthused by the idea. He&amp;#8217;s starting on the preliminary work now
and I look forward to seeing his&amp;nbsp;progress.&lt;/p&gt;
&lt;p&gt;Best of luck,&amp;nbsp;Evan!&lt;/p&gt;</content><category term="summerofcode"/><category term="summerofcode-2006"/><category term="planet-ubuntu"/></entry><entry><title>Google Summer of Code project started (Debian)</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/gsoc-d-i-hurd-started.html" rel="alternate"/><published>2006-05-26T17:23:00+00:00</published><updated>2006-05-26T20:11:52+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-05-26:/~cjwatson/blog/gsoc-d-i-hurd-started.html</id><summary type="html">&lt;p&gt;I&amp;#8217;m mentoring &lt;a href="http://xsunblog.blogspot.com/"&gt;Matheus Morais&lt;/a&gt; in the &lt;a href="http://code.google.com/soc/"&gt;Google
Summer of Code&lt;/a&gt;, porting d-i to the Hurd. We&amp;#8217;ve
exchanged a few mails and he has in hand all the preliminary (but not yet
functional; wouldn&amp;#8217;t want to make it too easy :-)) patches I&amp;#8217;ve put together
in the past …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;m mentoring &lt;a href="http://xsunblog.blogspot.com/"&gt;Matheus Morais&lt;/a&gt; in the &lt;a href="http://code.google.com/soc/"&gt;Google
Summer of Code&lt;/a&gt;, porting d-i to the Hurd. We&amp;#8217;ve
exchanged a few mails and he has in hand all the preliminary (but not yet
functional; wouldn&amp;#8217;t want to make it too easy :-)) patches I&amp;#8217;ve put together
in the past. I think I should be reasonably well-placed to judge his&amp;nbsp;progress.&lt;/p&gt;
&lt;p&gt;Best of luck,&amp;nbsp;Matheus!&lt;/p&gt;</content><category term="summerofcode"/><category term="summerofcode-2006"/><category term="planet-debian"/></entry><entry><title>Unix tools: sponge</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/sponge.html" rel="alternate"/><published>2006-02-06T20:45:38+00:00</published><updated>2006-02-06T20:45:38+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-02-06:/~cjwatson/blog/sponge.html</id><summary type="html">&lt;p&gt;Joey
&lt;a href="http://kitenet.net/~joey/blog/entry/unix_tools_vidir-2006-02-05-21-33.html"&gt;writes&lt;/a&gt;
about the lack of new tools that fit into the Unix philosophy.  My favourite
of such things I&amp;#8217;ve written is
&lt;a href="http://riva.ucam.org/svn/cjwatson/bin/sponge"&gt;sponge&lt;/a&gt;.  It addresses the
problem of editing files in-place with Unix tools, namely that if you just
redirect output to the file you&amp;#8217;re trying to edit …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Joey
&lt;a href="http://kitenet.net/~joey/blog/entry/unix_tools_vidir-2006-02-05-21-33.html"&gt;writes&lt;/a&gt;
about the lack of new tools that fit into the Unix philosophy.  My favourite
of such things I&amp;#8217;ve written is
&lt;a href="http://riva.ucam.org/svn/cjwatson/bin/sponge"&gt;sponge&lt;/a&gt;.  It addresses the
problem of editing files in-place with Unix tools, namely that if you just
redirect output to the file you&amp;#8217;re trying to edit then the redirection takes
effect (clobbering the contents of the file) before the first command in the
pipeline gets round to reading from the file.  Switches like &lt;code&gt;sed -i&lt;/code&gt; and
&lt;code&gt;perl -i&lt;/code&gt; work around this, but not every command you might want to use in a
pipeline has such an option, and you can&amp;#8217;t use that approach with
multiple-command pipelines&amp;nbsp;anyway.&lt;/p&gt;
&lt;p&gt;I normally use sponge a bit like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sed &amp;#39;...&amp;#39; file | grep &amp;#39;...&amp;#39; | sponge file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since it&amp;#8217;s so trivial I imagine lots of other people have written something
similar (another common name for it seems to be inplace; my name indicates
soaking up all the input and then squeezing it all out again); but I do keep
meaning to try to get a rewritten version into coreutils at some&amp;nbsp;point.&lt;/p&gt;</content><category term="misc"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>debconf/cdebconf coinstallability</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/debconf-cdebconf-coinstallable.html" rel="alternate"/><published>2006-01-27T02:55:06+00:00</published><updated>2006-01-27T02:55:06+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-01-27:/~cjwatson/blog/debconf-cdebconf-coinstallable.html</id><summary type="html">&lt;p&gt;&lt;a href="http://kitenet.net/~joey/blog/"&gt;Joey&lt;/a&gt; has been
&lt;a href="http://lists.debian.org/debian-devel/2005/08/msg00136.html"&gt;campaigning&lt;/a&gt;
for a while to get everything in the archive changed to depend on &lt;code&gt;debconf |
debconf-2.0&lt;/code&gt; or similar rather than just &lt;code&gt;debconf&lt;/code&gt;, in order that we can
start rolling out &lt;code&gt;cdebconf&lt;/code&gt; as its replacement.  Like most jobs that
involve touching the bulk of the archive, this …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="http://kitenet.net/~joey/blog/"&gt;Joey&lt;/a&gt; has been
&lt;a href="http://lists.debian.org/debian-devel/2005/08/msg00136.html"&gt;campaigning&lt;/a&gt;
for a while to get everything in the archive changed to depend on &lt;code&gt;debconf |
debconf-2.0&lt;/code&gt; or similar rather than just &lt;code&gt;debconf&lt;/code&gt;, in order that we can
start rolling out &lt;code&gt;cdebconf&lt;/code&gt; as its replacement.  Like most jobs that
involve touching the bulk of the archive, this looks set to take quite a
while, as the &lt;a href="http://bugs.debian.org/328498"&gt;list of bugs&lt;/a&gt; should&amp;nbsp;indicate.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;Recently it occurred to me that we didn&amp;#8217;t necessarily have to do it that way
round.  In a bout of late-night hacking while staying awake to look after a
sick child (he seems mostly &lt;span class="caps"&gt;OK&lt;/span&gt; now, although the rushed trip to the hospital
earlier was a bit on the nerve-wracking side), I&amp;#8217;ve shuffled things around
in the cdebconf package so that it no longer has any file conflicts with
debconf or debconf-doc, and changed the debconf confmodule to fire up the
cdebconf frontend rather than its own if the &lt;code&gt;DEBCONF_USE_CDEBCONF&lt;/code&gt;
environment variable is non-empty.  (The details of this may change before
it actually gets uploaded, as I&amp;#8217;d like to get Joey to look it over and
approve it first.)  This allows you to install cdebconf, set that
environment variable, and play around with cdebconf with relative ease; when
we come to switch to cdebconf for real, instead of a huge conflicting mess
that apt will probably have trouble resolving, it&amp;#8217;ll just be a matter of
changing a couple of lines in &lt;code&gt;/usr/share/debconf/confmodule&lt;/code&gt;.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;Of course, don&amp;#8217;t expect cdebconf to be a complete working replacement for
debconf just yet; if you try using it for a dist-upgrade run it&amp;#8217;ll fall
over.  Due to its d-i heritage, it doesn&amp;#8217;t yet load templates automatically;
that has to be done by hand.  Frontend names differ from debconf&amp;#8217;s, which
will need some migration code.  At the moment it can only handle &lt;span class="caps"&gt;UTF&lt;/span&gt;-8
templates, which are mandated in the installer but only optional in the rest
of the system.  It doesn&amp;#8217;t have all of debconf&amp;#8217;s rich array of database
modules.  I haven&amp;#8217;t adapted the Perl or Python confmodules yet.  The list
goes on.  However, I think we at least stand a chance of getting a handle on
the problem&amp;nbsp;now.&lt;/p&gt;
&lt;p&gt;(I&amp;#8217;ll post this article to debian-devel once the changes have been reviewed
and&amp;nbsp;uploaded.)&lt;/p&gt;</content><category term="misc"/><category term="debconf"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry><entry><title>Killer apps: bzr shelve</title><link href="https://www.chiark.greenend.org.uk/~cjwatson/blog/bzr-shelve.html" rel="alternate"/><published>2006-01-09T16:47:43+00:00</published><updated>2006-01-09T16:47:43+00:00</updated><author><name>Colin Watson</name></author><id>tag:www.chiark.greenend.org.uk,2006-01-09:/~cjwatson/blog/bzr-shelve.html</id><summary type="html">&lt;p&gt;Working on free software has made me fairly revision control
system-agnostic; I can&amp;#8217;t afford to get too wedded to any one system because
as soon as I do somebody will invent something new and I&amp;#8217;ll have to convert
again, so I just work with whatever other people on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Working on free software has made me fairly revision control
system-agnostic; I can&amp;#8217;t afford to get too wedded to any one system because
as soon as I do somebody will invent something new and I&amp;#8217;ll have to convert
again, so I just work with whatever other people on the same project are
using.  Even &lt;span class="caps"&gt;CVS&lt;/span&gt; doesn&amp;#8217;t make a lot of difference to the way I work as long
as I&amp;#8217;m working online and have cvsps handy.  And of course I usually don&amp;#8217;t
bother with revision control if I&amp;#8217;m just tweaking somebody else&amp;#8217;s Debian
source package a bit (in which case I just use debdiff for&amp;nbsp;paranoia).&lt;/p&gt;
&lt;p&gt;Using bzr at work, though, I think I just found my killer app in Michael
Ellerman&amp;#8217;s &lt;a href="http://wiki.bazaar.canonical.com/BzrShelveExample"&gt;shelve&lt;/a&gt;
plugin.  My working style generally involves alternating between doing lots
and lots of stuff in the one working copy and (after testing) going through
and committing it in logical chunks.  This is fine if everything&amp;#8217;s in
separate files (most revision control systems let you commit just some
files), but if several of the chunks are in the one file then I&amp;#8217;m reduced to
saving diffs and manually editing out the bits I don&amp;#8217;t want to commit yet,
which is obviously pretty tedious and&amp;nbsp;error-prone.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bzr shelve&lt;/code&gt; presents each diff hunk in your working copy to you in turn and
asks you whether you want to keep it.  If you say no, that hunk gets
unapplied and goes into a &amp;#8220;shelf&amp;#8221;, where &lt;code&gt;bzr unshelve&lt;/code&gt; can later reapply
it.  In the meantime commits act as though the shelved hunks didn&amp;#8217;t exist.
This doesn&amp;#8217;t help if you want to defer only one of two immediately adjacent
changes that end up in the same hunk, of course, but it vastly reduces the
scale of the&amp;nbsp;problem.&lt;/p&gt;
&lt;p&gt;I suppose it would be easy enough to write a shelve-a-like for any other
system; it&amp;#8217;s just that I haven&amp;#8217;t seen it for any other system yet.  If
working with systems that lack it really starts to annoy me, I may have to
rip out the guts of shelve and figure out how to make it&amp;nbsp;generic.&lt;/p&gt;</content><category term="misc"/><category term="bzr"/><category term="planet-debian"/><category term="planet-ubuntu"/></entry></feed>