[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#987372: marked as done (buster-pu: package distro-info-data/0.41+deb10u3 OR (distro-info/1.0~deb10u1 AND distro-info-data/0.47~deb10u1))



Your message dated Sat, 09 Oct 2021 12:11:43 +0100
with message-id <896b7609401ceb0e1c537222e26587ea2351415d.camel@adam-barratt.org.uk>
and subject line Closing bugs for fixes included in the 10.11 point release
has caused the Debian Bug report #987372,
regarding buster-pu: package distro-info-data/0.41+deb10u3 OR (distro-info/1.0~deb10u1 AND distro-info-data/0.47~deb10u1)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
987372: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=987372
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: bdrung@debian.org

There's a new Ubuntu release, so it's time to upload a distro-info-data
update for buster. I missed 0.46, but there was nothing urgent in it.
The changes in unstable since the last update are:

distro-info-data (0.47) unstable; urgency=medium

  * Add Ubuntu 21.04, Impish Indri.

 -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 10:30:18 -0400

distro-info-data (0.46) unstable; urgency=medium

  * Add "eol-server" dates matching "eol", for LTS releases, as there hasn't
    been a distinction between the two, for a while.
    (Closes: #922090, LP: #1814976).
  * Add "eol-esm" column: EOL for Ubuntu Extended Security Maintenance support.
    (LP: #1808038)
  * Drop ancient Replaces: distro-info (<< 0.3~). No longer needed.
  * Add "eol-lts" for Debian LTS (Closes: #782685)
  * Add estimated dates for Buster EOL and Buster LTS EOL.
  * Publish the data to GitLab pages. (Closes: #973904)
  * Bump Standards-Version to 4.5.1, no changes needed.
  * Bump copyright years.
  * Correct the EOL date for Debian Jessie.
  * Add Debian 13 "Trixie", with a rough date.
  * Add "up-to-date" testing tool.
  * Add an autopkgtest, running the validation and up-to-date tests.
  * "black" Python.
  * Add "eol-elts" for Debian ELTS.
  * Tweak eol and eol-esm dates, by a couple of days, for Ubuntu 6.10, 9.10,
    10.04, 12.04, 15.04, 15.10, 19.04 to match announced EOL dates.

 -- Stefano Rivera <stefanor@debian.org>  Fri, 29 Jan 2021 13:41:20 -0700

[ Reason ]
I want to update distro-info-data, so that it knows about the current
Ubuntu development release, and future Debian releases.

[ Impact ]
Currently on a Buster system:
$ ubuntu-distro-info --devel
ubuntu-distro-info: Distribution data outdated.
Please check for an update for distro-info-data. See /usr/share/doc/distro-info-data/README.Debian for details.

With this change:
$ ubuntu-distro-info --devel
impish

[ Tests ]
distro-info-data is just a data package. There are automated tests for
correctness and freshness.

distro-info has automated unit and integration tests.

[ Risks ]
The intention for distro-info and distro-info-data was that the data
could always be trivially backported to stable releases, however this
time there are a few changes there that make this a non-trivial update.
They got batched together, because once you're breaking the world, you
may as well do it properly:

1. New columns. distro-info didn't support unknown columns in the CSV
   data until 1.0.
2. Date corrections. distro-info used historical dates in the test
   suite, so changes break build time tests and autopkgtests.

So, I offer you two choices:
1. We backport distro-info-data 0.47 and distro-info 1.0 to buster.
   Bringing new features, and simplified unmodified backport data
   updates in the future.
   * distro-info_1.0~deb10u1.debdiff
   * distro-info-data_0.47~deb10u1.debdiff
2. We cherry-pick the important changes in distro-info-data (excluding
   those historical date corrections that break tests, and new columns).
   Future updates for buster will have to continue to do this.
   * distro-info-data_0.41+deb10u4.debdiff

With the backport approach:
    Users will need to install 2 updates together:
    distro-info Depends: distro-info-data (>= 0.46~)
    distro-info-data Breaks: distro-info (<< 1.0~)

    Other code that interprets distro-info-data directly may be surprised
    by new columns. All reverse-dependencies in the archive have been
    checked, and won't be affected.

With the cherry-pick approach:
    Negligible risk to users, it's a new entry in the Debian & Ubuntu
    releases tables, and EOL updates for Jessie and Buster (guessed).

    Future updates will have to continue to cherry-pick, which means
    they won't be tested as well as straight backports.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in stable
  [x] the issue is verified as fixed in unstable

[ Changes ]

backport approach:

    distro-info-data (0.47~deb10u1) buster; urgency=medium

      * Backport 0.47 to buster. Highlights:
        - Add "eol-esm" for Ubuntu Extended Security Maintenance support.
        - Add "eol-lts" for Debian LTS (Closes: #782685)
        - Add "eol-elts" for Debian ELTS.
        - Add estimated dates for Buster EOL and Buster LTS EOL.
        - Add Debian 13 "Trixie", with a rough date.
        - Correct the EOL date for Debian Jessie.
        - Tweak eol and eol-esm dates, by a couple of days, for Ubuntu 6.10, 9.10,
          10.04, 12.04, 15.04, 15.10, 19.04 to match announced EOL dates.
        - Add Ubuntu 21.04, Impish Indri.

    -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:46:22 -0400

    distro-info-data (0.47) unstable; urgency=medium

      * Add Ubuntu 21.04, Impish Indri.

     -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 10:30:18 -0400

    distro-info-data (0.46) unstable; urgency=medium

      * Add "eol-server" dates matching "eol", for LTS releases, as there hasn't
        been a distinction between the two, for a while.
        (Closes: #922090, LP: #1814976).
      * Add "eol-esm" column: EOL for Ubuntu Extended Security Maintenance support.
        (LP: #1808038)
      * Drop ancient Replaces: distro-info (<< 0.3~). No longer needed.
      * Add "eol-lts" for Debian LTS (Closes: #782685)
      * Add estimated dates for Buster EOL and Buster LTS EOL.
      * Publish the data to GitLab pages. (Closes: #973904)
      * Bump Standards-Version to 4.5.1, no changes needed.
      * Bump copyright years.
      * Correct the EOL date for Debian Jessie.
      * Add Debian 13 "Trixie", with a rough date.
      * Add "up-to-date" testing tool.
      * Add an autopkgtest, running the validation and up-to-date tests.
      * "black" Python.
      * Add "eol-elts" for Debian ELTS.
      * Tweak eol and eol-esm dates, by a couple of days, for Ubuntu 6.10, 9.10,
        10.04, 12.04, 15.04, 15.10, 19.04 to match announced EOL dates.

     -- Stefano Rivera <stefanor@debian.org>  Fri, 29 Jan 2021 13:41:20 -0700

    and

    distro-info (1.0~deb10u1) buster; urgency=medium

      * Backport distro-info 1.0 to buster. Highlights:
        - Add support for Debian LTS (Closes: #782685)
        - Add support for Debian ELTS.
        - Provide support for the milestone eol-esm and add filters for
          supported-esm to ubuntu-distro-info along with the python and perl
          modules. (LP: #1808038)
        - Handle currently unknown columns in CSV data.
      * Re-instate python2 support.
      * Revert: Rename build dependency pylint3 to pylint.
      * Revert: Switch to debhelper 13.
      * Tweak Python indentation to please an older pylint.
      * Adjust {Build-,}Depends on distro-info-data to (>= 0.46~).

     -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:54:50 -0400

    distro-info (1.0) unstable; urgency=medium

      [ Debian Janitor ]
      * Mark libdistro-info-perl as Multi-Arch: foreign.

      [ Stefano Rivera ]
      * Bump standards-Version to 4.5.1, no changes needed.
      * Bump copyright years.
      * Re-black Python.
      * Add support for Debian LTS (Closes: #782685)
      * Depend on distro-info-data (>= 0.46), with extra columns for
        Debian LTS and Ubuntu ESM.
      * Ignore W503 warnings from flake8, they are PEP-8 incompatible.
      * Handle currently unknown columns in CSV data.
      * Drop old Breaks+Replaces on ubuntu-dev-tools, no longer needed.
      * Reorganise help into a slightly more logical order.
      * Add support for Debian ELTS.
      * Update tests to match old date adjustments in distro-info-data 0.46.

      [ Brian Murray ]
      * Provide support for the milestone eol-esm and add filters for
        supported-esm to ubuntu-distro-info along with the python and perl
        modules. (LP: #1808038)
      * Only include LTS releases when filtering by supported-esm.

      [ Steve Langasek ]
      * Override uninteresting flake8 warnings about imports and doc strings.
      * Don't run tests over the distro_info_test directory, which is pointless
        and recursive.

     -- Stefano Rivera <stefanor@debian.org>  Fri, 29 Jan 2021 13:35:30 -0700

    distro-info (0.24) unstable; urgency=medium

      * Fix issues found by pylint 2.6.0 (Closes: #971094)
      * Blacken Python code
      * python: Define sets directly
      * Bump Standards-Version to 4.5.0
      * Switch to debhelper 13

     -- Benjamin Drung <bdrung@debian.org>  Mon, 28 Sep 2020 19:36:32 +0200

    distro-info (0.23) unstable; urgency=medium

      * Drop python2 support; Closes: #943052, #936408

     -- Sandro Tosi <morph@debian.org>  Wed, 08 Jan 2020 23:06:26 -0500

    distro-info (0.22) unstable; urgency=medium

      * Drop testing Python 2 code with Pylint
      * Rename build dependency pylint3 to pylint (Closes: #940178)
      * Switch to debhelper 12
      * Bump Standards-Version to 4.4.0 (no changes needed)

     -- Benjamin Drung <bdrung@debian.org>  Sat, 14 Sep 2019 15:44:13 +0200

cherry-pick approach:

    distro-info-data (0.41+deb10u4) UNRELEASED; urgency=medium

      * Update data to 0.46, without new columns:
        - Add estimated date for Buster EOL.
        - Correct the EOL date for Debian Jessie.
        - Add Debian 13 "Trixie", with a rough date.
        - Add Ubuntu 21.04, Impish Indri.

     -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:07:13 -0400

SR
diff -Nru distro-info-0.21/debian/changelog distro-info-1.0~deb10u1/debian/changelog
--- distro-info-0.21/debian/changelog	2019-02-09 19:29:24.000000000 -0400
+++ distro-info-1.0~deb10u1/debian/changelog	2021-04-22 11:54:50.000000000 -0400
@@ -1,3 +1,77 @@
+distro-info (1.0~deb10u1) buster; urgency=medium
+
+  * Backport distro-info 1.0 to buster. Highlights:
+    - Add support for Debian LTS (Closes: #782685)
+    - Add support for Debian ELTS.
+    - Provide support for the milestone eol-esm and add filters for
+      supported-esm to ubuntu-distro-info along with the python and perl
+      modules. (LP: #1808038)
+    - Handle currently unknown columns in CSV data.
+  * Re-instate python2 support.
+  * Revert: Rename build dependency pylint3 to pylint.
+  * Revert: Switch to debhelper 13.
+  * Tweak Python indentation to please an older pylint.
+  * Adjust {Build-,}Depends on distro-info-data to (>= 0.46~).
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:54:50 -0400
+
+distro-info (1.0) unstable; urgency=medium
+
+  [ Debian Janitor ]
+  * Mark libdistro-info-perl as Multi-Arch: foreign.
+
+  [ Stefano Rivera ]
+  * Bump standards-Version to 4.5.1, no changes needed.
+  * Bump copyright years.
+  * Re-black Python.
+  * Add support for Debian LTS (Closes: #782685)
+  * Depend on distro-info-data (>= 0.46), with extra columns for
+    Debian LTS and Ubuntu ESM.
+  * Ignore W503 warnings from flake8, they are PEP-8 incompatible.
+  * Handle currently unknown columns in CSV data.
+  * Drop old Breaks+Replaces on ubuntu-dev-tools, no longer needed.
+  * Reorganise help into a slightly more logical order.
+  * Add support for Debian ELTS.
+  * Update tests to match old date adjustments in distro-info-data 0.46.
+
+  [ Brian Murray ]
+  * Provide support for the milestone eol-esm and add filters for
+    supported-esm to ubuntu-distro-info along with the python and perl
+    modules. (LP: #1808038)
+  * Only include LTS releases when filtering by supported-esm.
+
+  [ Steve Langasek ]
+  * Override uninteresting flake8 warnings about imports and doc strings.
+  * Don't run tests over the distro_info_test directory, which is pointless
+    and recursive.
+
+ -- Stefano Rivera <stefanor@debian.org>  Fri, 29 Jan 2021 13:35:30 -0700
+
+distro-info (0.24) unstable; urgency=medium
+
+  * Fix issues found by pylint 2.6.0 (Closes: #971094)
+  * Blacken Python code
+  * python: Define sets directly
+  * Bump Standards-Version to 4.5.0
+  * Switch to debhelper 13
+
+ -- Benjamin Drung <bdrung@debian.org>  Mon, 28 Sep 2020 19:36:32 +0200
+
+distro-info (0.23) unstable; urgency=medium
+
+  * Drop python2 support; Closes: #943052, #936408
+
+ -- Sandro Tosi <morph@debian.org>  Wed, 08 Jan 2020 23:06:26 -0500
+
+distro-info (0.22) unstable; urgency=medium
+
+  * Drop testing Python 2 code with Pylint
+  * Rename build dependency pylint3 to pylint (Closes: #940178)
+  * Switch to debhelper 12
+  * Bump Standards-Version to 4.4.0 (no changes needed)
+
+ -- Benjamin Drung <bdrung@debian.org>  Sat, 14 Sep 2019 15:44:13 +0200
+
 distro-info (0.21) unstable; urgency=medium
 
   [ Benjamin Drung ]
diff -Nru distro-info-0.21/debian/compat distro-info-1.0~deb10u1/debian/compat
--- distro-info-0.21/debian/compat	2018-02-04 15:33:03.000000000 -0400
+++ distro-info-1.0~deb10u1/debian/compat	1969-12-31 20:00:00.000000000 -0400
@@ -1 +0,0 @@
-11
diff -Nru distro-info-0.21/debian/control distro-info-1.0~deb10u1/debian/control
--- distro-info-0.21/debian/control	2019-02-09 19:29:24.000000000 -0400
+++ distro-info-1.0~deb10u1/debian/control	2021-04-22 11:54:50.000000000 -0400
@@ -3,10 +3,9 @@
 Priority: optional
 Maintainer: Benjamin Drung <bdrung@debian.org>
 Uploaders: Stefano Rivera <stefanor@debian.org>
-Build-Depends: debhelper (>= 11),
+Build-Depends: debhelper-compat (= 12),
                dh-python,
-               distro-info-data (>= 0.7~),
-               pylint,
+               distro-info-data (>= 0.46~),
                pylint3,
                python-all (>= 2.6.3-3~),
                python-flake8,
@@ -16,17 +15,15 @@
                python3-flake8,
                python3-setuptools,
                shunit2 (>= 2.1.6)
-Standards-Version: 4.3.0
+Standards-Version: 4.5.1
 Rules-Requires-Root: no
 Vcs-Git: https://salsa.debian.org/debian/distro-info.git
 Vcs-Browser: https://salsa.debian.org/debian/distro-info
 
 Package: distro-info
 Architecture: any
-Depends: distro-info-data (>= 0.7~), ${misc:Depends}, ${shlibs:Depends}
+Depends: distro-info-data (>= 0.46~), ${misc:Depends}, ${shlibs:Depends}
 Suggests: shunit2 (>= 2.1.6)
-Breaks: ubuntu-dev-tools (<< 0.133~)
-Replaces: ubuntu-dev-tools (<< 0.127~)
 Description: provides information about the distributions' releases
  Information about all releases of Debian and Ubuntu. The distro-info script
  will give you the codename for e.g. the latest stable release of your
@@ -36,7 +33,8 @@
 Package: libdistro-info-perl
 Architecture: all
 Section: perl
-Depends: distro-info-data, ${misc:Depends}, ${perl:Depends}
+Depends: distro-info-data (>= 0.46~), ${misc:Depends}, ${perl:Depends}
+Multi-Arch: foreign
 Description: information about distributions' releases (Perl module)
  Information about all releases of Debian and Ubuntu.
  .
@@ -46,7 +44,7 @@
 Package: python-distro-info
 Architecture: all
 Section: python
-Depends: distro-info-data, ${misc:Depends}, ${python:Depends}
+Depends: distro-info-data (>= 0.46~), ${misc:Depends}, ${python:Depends}
 Breaks: distro-info (<< 0.3~)
 Replaces: distro-info (<< 0.3~)
 Description: information about distributions' releases (Python module)
@@ -59,7 +57,7 @@
 Package: python3-distro-info
 Architecture: all
 Section: python
-Depends: distro-info-data, ${misc:Depends}, ${python3:Depends}
+Depends: distro-info-data (>= 0.46~), ${misc:Depends}, ${python3:Depends}
 Description: information about distributions' releases (Python 3 module)
  Information about all releases of Debian and Ubuntu.
  .
diff -Nru distro-info-0.21/debian/copyright distro-info-1.0~deb10u1/debian/copyright
--- distro-info-0.21/debian/copyright	2018-02-04 15:42:42.000000000 -0400
+++ distro-info-1.0~deb10u1/debian/copyright	2021-04-22 11:54:50.000000000 -0400
@@ -4,7 +4,7 @@
 
 Files: *
 Copyright: 2009-2018, Benjamin Drung <bdrung@debian.org>
-           2010-2011, Stefano Rivera <stefanor@debian.org>
+           2010-2021, Stefano Rivera <stefanor@debian.org>
 License: ISC
 
 Files: shell/*-distro-info.in shell/distro-info-util.sh
diff -Nru distro-info-0.21/debian/tests/control distro-info-1.0~deb10u1/debian/tests/control
--- distro-info-0.21/debian/tests/control	2018-10-11 20:11:26.000000000 -0400
+++ distro-info-1.0~deb10u1/debian/tests/control	2021-04-22 11:54:50.000000000 -0400
@@ -7,11 +7,9 @@
 Features: test-name=test-ubuntu-distro-info
 
 Test-Command: cp -r python/distro_info_test python/*-distro-info python/setup.py "$AUTOPKGTEST_TMP"; for py in $(py3versions -r 2>/dev/null); do cd "$AUTOPKGTEST_TMP"; echo "Testing with $py:"; $py -m unittest discover -v; done
-Depends: pylint3, python3-all, python3-distro-info, python3-flake8
+Depends: pylint (>= 2.2.2-2~) | pylint3,
+         python3-all,
+         python3-distro-info,
+         python3-flake8
 Restrictions: allow-stderr
 Features: test-name=python3-unittest
-
-Test-Command: cp -r python/distro_info_test python/*-distro-info python/setup.py "$AUTOPKGTEST_TMP"; for py in $(pyversions -r 2>/dev/null); do cd "$AUTOPKGTEST_TMP"; echo "Testing with $py:"; $py -m unittest discover -v; done
-Depends: pylint, python-all, python-distro-info, python-flake8
-Restrictions: allow-stderr
-Features: test-name=python-unittest
diff -Nru distro-info-0.21/debian-distro-info.c distro-info-1.0~deb10u1/debian-distro-info.c
--- distro-info-0.21/debian-distro-info.c	2013-08-02 17:31:52.000000000 -0400
+++ distro-info-1.0~deb10u1/debian-distro-info.c	2021-04-22 11:54:50.000000000 -0400
@@ -16,7 +16,7 @@
 
 #define DEBIAN
 #define CSV_NAME "debian"
-#define CSV_HEADER "version,codename,series,created,release,eol"
+#define CSV_HEADER "version,codename,series,created,release,eol,eol-lts,eol-elts"
 #define DISTRO_NAME "Debian"
 #define NAME "debian-distro-info"
 
diff -Nru distro-info-0.21/distro-info-util.c distro-info-1.0~deb10u1/distro-info-util.c
--- distro-info-0.21/distro-info-util.c	2019-02-09 17:07:26.000000000 -0400
+++ distro-info-1.0~deb10u1/distro-info-util.c	2021-04-22 11:54:50.000000000 -0400
@@ -38,8 +38,13 @@
 static char *milestones[] = {"created"
                             ,"release"
                             ,"eol"
+#ifdef DEBIAN
+                            ,"eol-lts"
+                            ,"eol-elts"
+#endif
 #ifdef UBUNTU
                             ,"eol-server"
+                            ,"eol-esm"
 #endif
 };
 
@@ -193,6 +198,31 @@
     ;
 }
 
+#ifdef DEBIAN
+static inline bool eol_lts(const date_t *date, const distro_t *distro) {
+    return !distro->milestones[MILESTONE_EOL_LTS] ||
+           date_ge(date, distro->milestones[MILESTONE_EOL_LTS])
+    ;
+}
+
+static inline bool eol_elts(const date_t *date, const distro_t *distro) {
+    return !distro->milestones[MILESTONE_EOL_ELTS] ||
+           date_ge(date, distro->milestones[MILESTONE_EOL_ELTS])
+    ;
+}
+#endif
+
+#ifdef UBUNTU
+static inline bool eol_esm(const date_t *date, const distro_t *distro) {
+    return distro->milestones[MILESTONE_EOL] &&
+           date_ge(date, distro->milestones[MILESTONE_EOL])
+           && (!distro->milestones[MILESTONE_EOL_ESM] ||
+              (distro->milestones[MILESTONE_EOL_ESM] &&
+               date_ge(date, distro->milestones[MILESTONE_EOL_ESM])))
+    ;
+}
+#endif
+
 // Filter callbacks
 
 static bool filter_all(unused(const date_t *date),
@@ -208,6 +238,23 @@
     return created(date, distro) && !eol(date, distro);
 }
 
+#ifdef DEBIAN
+static bool filter_lts_supported(const date_t *date, const distro_t *distro) {
+    return created(date, distro) && eol(date, distro) && !eol_lts(date, distro);
+}
+
+static bool filter_elts_supported(const date_t *date, const distro_t *distro) {
+    return created(date, distro) && eol_lts(date, distro) && !eol_elts(date, distro);
+}
+#endif
+
+#ifdef UBUNTU
+static bool filter_esm_supported(const date_t *date, const distro_t *distro) {
+    return created(date, distro) && !eol_esm(date, distro) &&
+           strstr(distro->version, "LTS") != NULL;
+}
+#endif
+
 static bool filter_unsupported(const date_t *date, const distro_t *distro) {
     return created(date, distro) && eol(date, distro);
 }
@@ -372,8 +419,13 @@
         free(list->distro->milestones[MILESTONE_CREATED]);
         free(list->distro->milestones[MILESTONE_RELEASE]);
         free(list->distro->milestones[MILESTONE_EOL]);
+#ifdef DEBIAN
+        free(list->distro->milestones[MILESTONE_EOL_LTS]);
+        free(list->distro->milestones[MILESTONE_EOL_ELTS]);
+#endif
 #ifdef UBUNTU
         free(list->distro->milestones[MILESTONE_EOL_SERVER]);
+        free(list->distro->milestones[MILESTONE_EOL_ESM]);
 #endif
         free(list->distro);
         free(list);
@@ -397,9 +449,9 @@
     data = *content = read_full_file(filename);
     line = strsep(&data, "\n");
     lineno = 1;
-    if(unlikely(strcmp(CSV_HEADER, line) != 0)) {
-        fprintf(stderr, NAME ": Header `%s' in file `%s' does not match "
-                "exactly `" CSV_HEADER "'.\n", line, filename);
+    if(unlikely(strncmp(CSV_HEADER, line, strlen(CSV_HEADER)) != 0)) {
+        fprintf(stderr, NAME ": Header `%s' in file `%s' does not start with "
+                "`" CSV_HEADER "'.\n", line, filename);
         failures++;
     }
 
@@ -525,16 +577,23 @@
 #endif
            "  -a  --all              list all known versions\n"
            "  -d  --devel            latest development version\n"
+#ifdef DEBIAN
+           "  -t  --testing          current testing version\n"
+#endif
+           "  -s  --stable           latest stable version\n"
 #ifdef UBUNTU
            "      --lts              latest long term support (LTS) version\n"
 #endif
 #ifdef DEBIAN
            "  -o  --oldstable        latest oldstable version\n"
 #endif
-           "  -s  --stable           latest stable version\n"
            "      --supported        list of all supported stable versions\n"
 #ifdef DEBIAN
-           "  -t  --testing          current testing version\n"
+           "  -l  --lts              list of all LTS supported versions\n"
+           "  -e  --elts             list of all Extended LTS supported versions\n"
+#endif
+#ifdef UBUNTU
+           "      --supported-esm    list of all Ubuntu Advantage supported stable versions\n"
 #endif
            "      --unsupported      list of all unsupported stable versions\n"
            "  -c  --codename         print the codename (default)\n"
@@ -550,13 +609,20 @@
             "--alias, "
 #endif
             "--all, --devel, "
+#ifdef DEBIAN
+            "--elts, "
+#endif
 #ifdef UBUNTU
-            "--latest, --lts, "
+            "--latest, "
 #endif
+            "--lts, "
 #ifdef DEBIAN
             "--oldstable, "
 #endif
             "--stable, --supported, "
+#ifdef UBUNTU
+            "--supported-esm, "
+#endif
             "--series, "
 #ifdef DEBIAN
             "--testing, "
@@ -590,35 +656,40 @@
 #endif
 
     const struct option long_options[] = {
-        {"help",        no_argument,       NULL, 'h' },
-        {"date",        required_argument, NULL, 'D' },
-        {"series",      required_argument, NULL, 'R' },
-        {"all",         no_argument,       NULL, 'a' },
-        {"days",        optional_argument, NULL, 'y' },
-        {"devel",       no_argument,       NULL, 'd' },
-        {"stable",      no_argument,       NULL, 's' },
-        {"supported",   no_argument,       NULL, 'S' },
-        {"unsupported", no_argument,       NULL, 'U' },
-        {"codename",    no_argument,       NULL, 'c' },
-        {"fullname",    no_argument,       NULL, 'f' },
-        {"release",     no_argument,       NULL, 'r' },
-#ifdef DEBIAN
-        {"alias",       required_argument, NULL, 'A' },
-        {"oldstable",   no_argument,       NULL, 'o' },
-        {"testing",     no_argument,       NULL, 't' },
+        {"help",          no_argument,       NULL, 'h' },
+        {"date",          required_argument, NULL, 'D' },
+        {"series",        required_argument, NULL, 'R' },
+        {"all",           no_argument,       NULL, 'a' },
+        {"days",          optional_argument, NULL, 'y' },
+        {"devel",         no_argument,       NULL, 'd' },
+        {"stable",        no_argument,       NULL, 's' },
+        {"supported",     no_argument,       NULL, 'S' },
+#ifdef UBUNTU
+        {"supported-esm", no_argument,       NULL, 'e' },
+#endif
+        {"unsupported",   no_argument,       NULL, 'U' },
+        {"codename",      no_argument,       NULL, 'c' },
+        {"fullname",      no_argument,       NULL, 'f' },
+        {"release",       no_argument,       NULL, 'r' },
+#ifdef DEBIAN
+        {"alias",         required_argument, NULL, 'A' },
+        {"elts",          no_argument,       NULL, 'e' },
+        {"lts",           no_argument,       NULL, 'l' },
+        {"oldstable",     no_argument,       NULL, 'o' },
+        {"testing",       no_argument,       NULL, 't' },
 #endif
 #ifdef UBUNTU
-        {"latest",      no_argument,       NULL, 'l' },
-        {"lts",         no_argument,       NULL, 'L' },
+        {"latest",        no_argument,       NULL, 'l' },
+        {"lts",           no_argument,       NULL, 'L' },
 #endif
-        {NULL,          0,                 NULL, '\0' }
+        {NULL,            0,                 NULL, '\0' }
     };
 
 #ifdef UBUNTU
     const char *short_options = "hadscrfly::";
 #endif
 #ifdef DEBIAN
-    const char *short_options = "hadscrfoty::";
+    const char *short_options = "hadescrfloty::";
 #endif
 
     // Suppress error messages from getopt_long
@@ -728,6 +799,18 @@
 #endif
 
 #ifdef DEBIAN
+            case 'e':
+                selected_filters++;
+                filter_cb = filter_elts_supported;
+                select_cb = NULL;
+                break;
+
+            case 'l':
+                selected_filters++;
+                filter_cb = filter_lts_supported;
+                select_cb = NULL;
+                break;
+
             case 'o':
                 selected_filters++;
                 filter_cb = filter_oldstable;
@@ -753,6 +836,15 @@
                 select_cb = NULL;
                 break;
 
+#ifdef UBUNTU
+            case 'e':
+                // Only long option --supported-esm is used
+                selected_filters++;
+                filter_cb = filter_esm_supported;
+                select_cb = NULL;
+                break;
+
+#endif
 #ifdef DEBIAN
             case 't':
                 selected_filters++;
diff -Nru distro-info-0.21/distro-info-util.h distro-info-1.0~deb10u1/distro-info-util.h
--- distro-info-0.21/distro-info-util.h	2013-08-02 17:31:31.000000000 -0400
+++ distro-info-1.0~deb10u1/distro-info-util.h	2021-04-22 11:54:50.000000000 -0400
@@ -34,8 +34,13 @@
 enum MILESTONE {MILESTONE_CREATED
                ,MILESTONE_RELEASE
                ,MILESTONE_EOL
+#ifdef DEBIAN
+               ,MILESTONE_EOL_LTS
+               ,MILESTONE_EOL_ELTS
+#endif
 #ifdef UBUNTU
                ,MILESTONE_EOL_SERVER
+               ,MILESTONE_EOL_ESM
 #endif
                ,MILESTONE_COUNT
 };
@@ -70,6 +75,13 @@
 static inline bool created(const date_t *date, const distro_t *distro);
 static inline bool released(const date_t *date, const distro_t *distro);
 static inline bool eol(const date_t *date, const distro_t *distro);
+#ifdef DEBIAN
+static inline bool eol_lts(const date_t *date, const distro_t *distro);
+static inline bool eol_elts(const date_t *date, const distro_t *distro);
+#endif
+#ifdef UBUNTU
+static inline bool eol_esm(const date_t *date, const distro_t *distro);
+#endif
 static inline int milestone_to_index(const char *milestone);
 
 #endif // __DISTRO_INFO_UTIL_H__
diff -Nru distro-info-0.21/doc/ubuntu-distro-info.1 distro-info-1.0~deb10u1/doc/ubuntu-distro-info.1
--- distro-info-0.21/doc/ubuntu-distro-info.1	2014-05-10 14:53:03.000000000 -0400
+++ distro-info-1.0~deb10u1/doc/ubuntu-distro-info.1	2021-04-22 11:54:50.000000000 -0400
@@ -66,6 +66,9 @@
 \fB\-\-supported\fR
 list of all supported stable versions
 .TP
+\fB\-\-supported\-esm\fR
+list of all Ubuntu Advantage supported stable versions
+.TP
 \fB\-\-unsupported\fR
 list of all unsupported stable versions
 .TP
diff -Nru distro-info-0.21/haskell/DebianDistroInfo.hs distro-info-1.0~deb10u1/haskell/DebianDistroInfo.hs
--- distro-info-0.21/haskell/DebianDistroInfo.hs	2012-02-25 11:10:38.000000000 -0400
+++ distro-info-1.0~deb10u1/haskell/DebianDistroInfo.hs	2021-04-22 11:54:50.000000000 -0400
@@ -21,7 +21,6 @@
 import System.Environment
 import System.Exit
 import System.IO
-import System.Locale
 
 import Text.CSV
 
@@ -47,8 +46,8 @@
 
 onlyOneFilter :: a
 onlyOneFilter = error ("You have to select exactly one of --all, " ++
-                       "--devel, --oldstable, --stable, --supported, " ++
-                       "--testing, --unsupported.")
+                       "--devel, --elts, --lts, --oldstable, --stable, " ++
+                       "--supported, --testing, --unsupported.")
 
 options :: [OptDescr (Options -> IO Options)]
 options =
@@ -61,7 +60,7 @@
         then version
         else debSeries e
     readDate arg opt =
-      return opt { optDate = readTime defaultTimeLocale "%F" arg }
+      return opt { optDate = parseTimeOrError False defaultTimeLocale "%F" arg }
     printHelp _ =
       do
         prg <- getProgName
@@ -81,14 +80,18 @@
              "list all known versions"
     , Option "d" ["devel"] (NoArg (setFilter debianDevel))
              "latest development version"
-    , Option "o" ["oldstable"] (NoArg (setFilter debianOldstable))
-             "latest oldstable version"
+    , Option "t" ["testing"] (NoArg (setFilter debianTesting))
+             "current testing version"
     , Option "s" ["stable"] (NoArg (setFilter debianStable))
              "latest stable version"
+    , Option "o" ["oldstable"] (NoArg (setFilter debianOldstable))
+             "latest oldstable version"
     , Option "" ["supported"] (NoArg (setFilter debianSupported))
              "list of all supported stable versions"
-    , Option "t" ["testing"] (NoArg (setFilter debianTesting))
-             "current testing version"
+    , Option "l" ["lts"] (NoArg (setFilter debianSupportedLTS))
+             "list of all LTS supported versions"
+    , Option "e" ["elts"] (NoArg (setFilter debianSupportedELTS))
+             "list of all Extended LTS supported versions"
     , Option "" ["unsupported"] (NoArg (setFilter debianUnsupported))
              "list of all unsupported stable versions"
     , Option "c" ["codename"]
diff -Nru distro-info-0.21/haskell/DistroInfo.hs distro-info-1.0~deb10u1/haskell/DistroInfo.hs
--- distro-info-0.21/haskell/DistroInfo.hs	2011-10-11 10:16:17.000000000 -0400
+++ distro-info-1.0~deb10u1/haskell/DistroInfo.hs	2021-04-22 11:54:50.000000000 -0400
@@ -20,6 +20,8 @@
                    debianOldstable,
                    debianStable,
                    debianSupported,
+                   debianSupportedLTS,
+                   debianSupportedELTS,
                    debianTesting,
                    debianUnsupported,
                    UbuntuEntry, ubuVersion, ubuSeries, ubuFull,
@@ -29,6 +31,7 @@
                    ubuntuLTS,
                    ubuntuStable,
                    ubuntuSupported,
+                   ubuntuSupportedESM,
                    ubuntuUnsupported,
                   ) where
 
@@ -46,7 +49,9 @@
                                  debSeries :: String,
                                  debCreated :: Day,
                                  debRelease :: Maybe Day,
-                                 debEol :: Maybe Day
+                                 debEol :: Maybe Day,
+                                 debEolLTS :: Maybe Day,
+                                 debEolELTS :: Maybe Day
                                } deriving(Eq, Show)
 
 -- | Represents one Ubuntu release data set
@@ -57,7 +62,8 @@
                                  ubuCreated :: Day,
                                  ubuRelease :: Day,
                                  ubuEol :: Day,
-                                 ubuEolServer :: Maybe Day
+                                 ubuEolServer :: Maybe Day,
+                                 ubuEolESM :: Maybe Day
                                } deriving(Eq, Show)
 
 -- | Splits a string by a given character (similar to the Python split function)
@@ -104,6 +110,7 @@
                   (convertDate $ m ! "created") (convertDate $ m ! "release")
                   (convertDate $ m ! "eol")
                   (maybeDate $ Map.lookup "eol-server" m)
+                  (maybeDate $ Map.lookup "eol-esm" m)
 
 -- | Converts a given CSV data into a list of Debian entries
 debianEntry :: CSV -> [DebianEntry]
@@ -117,6 +124,8 @@
                   (convertDate $ m ! "created")
                   (maybeDate $ Map.lookup "release" m)
                   (maybeDate $ Map.lookup "eol" m)
+                  (maybeDate $ Map.lookup "eol-lts" m)
+                  (maybeDate $ Map.lookup "eol-elts" m)
 
 -------------------
 -- Debian Filter --
@@ -161,6 +170,22 @@
     isSupported DebianEntry { debCreated = created, debEol = eol } =
       date >= created && maybe True (date <=) eol
 
+-- | Get list of all LTS supported distributions based on the given date.
+debianSupportedLTS :: Day -> [DebianEntry] -> [DebianEntry]
+debianSupportedLTS date = filter isSupportedLTS
+  where
+    isSupportedLTS DebianEntry { debCreated = created, debEol = eol,
+                                 debEolLTS = eol_lts } =
+      date >= created && maybe False (date >) eol && maybe False (date <=) eol_lts
+
+-- | Get list of all ELTS supported distributions based on the given date.
+debianSupportedELTS :: Day -> [DebianEntry] -> [DebianEntry]
+debianSupportedELTS date = filter isSupportedELTS
+  where
+    isSupportedELTS DebianEntry { debCreated = created, debEolLTS = eol_lts,
+                                  debEolELTS = eol_elts } =
+      date >= created && maybe False (date >) eol_lts && maybe False (date <=) eol_elts
+
 -- | Get latest testing Debian distribution based on the given date.
 debianTesting :: Day -> [DebianEntry] -> [DebianEntry]
 debianTesting date = filter isUnreleased
@@ -225,6 +250,13 @@
                               ubuEolServer = eolServer } =
       date >= created && (date <= eol || maybe False (date <=) eolServer)
 
+-- | Get list of all ESM supported distributions based on the given date.
+ubuntuSupportedESM :: Day -> [UbuntuEntry] -> [UbuntuEntry]
+ubuntuSupportedESM date = filter isSupportedESM
+  where
+    isSupportedESM UbuntuEntry { ubuCreated = created, ubuEolESM = eolESM } =
+      date >= created && maybe False (date <=) eolESM
+
 -- | Get list of all unsupported distributions based on the given date.
 ubuntuUnsupported :: Day -> [UbuntuEntry] -> [UbuntuEntry]
 ubuntuUnsupported date = filter isUnsupported
diff -Nru distro-info-0.21/haskell/TestDistroInfo.hs distro-info-1.0~deb10u1/haskell/TestDistroInfo.hs
--- distro-info-0.21/haskell/TestDistroInfo.hs	2012-03-22 19:07:08.000000000 -0400
+++ distro-info-1.0~deb10u1/haskell/TestDistroInfo.hs	2021-04-22 11:54:50.000000000 -0400
@@ -26,6 +26,10 @@
 
 date1 :: Day
 date1 = fromGregorian 2011 01 10
+date2 :: Day
+date2 = fromGregorian 2016 02 28
+date3 :: Day
+date3 = fromGregorian 2020 06 29
 
 ------------------
 -- Debian tests --
@@ -62,6 +66,18 @@
     expected = ["lenny", "squeeze", "sid", "experimental"]
     result = map debSeries $ debianSupported date1 d
 
+testDebianSupportedLTS :: [DebianEntry] -> Test
+testDebianSupportedLTS d = TestCase (assertEqual "Debian LTS" expected result)
+  where
+    expected = ["squeeze"]
+    result = map debSeries $ debianSupportedLTS date2 d
+
+testDebianSupportedELTS :: [DebianEntry] -> Test
+testDebianSupportedELTS d = TestCase (assertEqual "Debian ELTS" expected result)
+  where
+    expected = ["wheezy"]
+    result = map debSeries $ debianSupportedELTS date3 d
+
 testDebianTesting :: [DebianEntry] -> Test
 testDebianTesting d = TestCase (assertEqual "Debian testing" expected result)
   where
@@ -111,6 +127,12 @@
     expected = ["dapper", "hardy", "karmic", "lucid", "maverick", "natty"]
     result = map ubuSeries $ ubuntuSupported date1 u
 
+testUbuntuSupportedESM :: [UbuntuEntry] -> Test
+testUbuntuSupportedESM u = TestCase (assertEqual "Ubuntu ESM" expected result)
+  where
+    expected = ["precise", "trusty", "xenial"]
+    result = map ubuSeries $ ubuntuSupportedESM date2 u
+
 testUbuntuUnsupported :: [UbuntuEntry] -> Test
 testUbuntuUnsupported u = TestCase (assertEqual "Ubuntu unsupported" expected result)
   where
@@ -126,6 +148,8 @@
 tests d u = TestList [
     testDebianAll d,
     testDebianDevel d,
+    testDebianSupportedLTS d,
+    testDebianSupportedELTS d,
     testDebianOldstable d,
     testDebianStable d,
     testDebianSupported d,
@@ -136,6 +160,7 @@
     testUbuntuLTS u,
     testUbuntuStable u,
     testUbuntuSupported u,
+    testUbuntuSupportedESM u,
     testUbuntuUnsupported u
   ]
 
diff -Nru distro-info-0.21/haskell/UbuntuDistroInfo.hs distro-info-1.0~deb10u1/haskell/UbuntuDistroInfo.hs
--- distro-info-0.21/haskell/UbuntuDistroInfo.hs	2012-02-25 11:10:20.000000000 -0400
+++ distro-info-1.0~deb10u1/haskell/UbuntuDistroInfo.hs	2021-04-22 11:54:50.000000000 -0400
@@ -21,7 +21,6 @@
 import System.Environment
 import System.Exit
 import System.IO
-import System.Locale
 
 import Text.CSV
 
@@ -47,13 +46,14 @@
 
 onlyOneFilter :: a
 onlyOneFilter = error ("You have to select exactly one of --all, --devel, " ++
-                       "--lts, --stable, --supported, --unsupported.")
+                       "--lts, --stable, --supported, --supported-esm, " ++
+                       "--unsupported.")
 
 options :: [OptDescr (Options -> IO Options)]
 options =
   let
     readDate arg opt =
-      return opt { optDate = readTime defaultTimeLocale "%F" arg }
+      return opt { optDate = parseTimeOrError False defaultTimeLocale "%F" arg }
     printHelp _ =
       do
         prg <- getProgName
@@ -73,12 +73,14 @@
              "list all known versions"
     , Option "d" ["devel"] (NoArg (setFilter ubuntuDevel))
              "latest development version"
-    , Option "" ["lts"] (NoArg (setFilter ubuntuLTS))
-             "latest long term support (LTS) version"
     , Option "s" ["stable"] (NoArg (setFilter ubuntuStable))
              "latest stable version"
+    , Option "" ["lts"] (NoArg (setFilter ubuntuLTS))
+             "latest long term support (LTS) version"
     , Option "" ["supported"] (NoArg (setFilter ubuntuSupported))
              "list of all supported stable versions"
+    , Option "" ["supported-esm"] (NoArg (setFilter ubuntuSupportedESM))
+             "list of all Ubuntu Advantage supported stable versions"
     , Option "" ["unsupported"] (NoArg (setFilter ubuntuUnsupported))
              "list of all unsupported stable versions"
     , Option "c" ["codename"]
diff -Nru distro-info-0.21/Makefile distro-info-1.0~deb10u1/Makefile
--- distro-info-0.21/Makefile	2018-10-11 20:11:26.000000000 -0400
+++ distro-info-1.0~deb10u1/Makefile	2021-04-22 11:54:50.000000000 -0400
@@ -37,7 +37,7 @@
 	cd perl && ./test.pl
 
 test-python:
-	$(foreach python,$(shell pyversions -r && py3versions -r),cd python && $(python) setup.py test$(\n))
+	$(foreach python,$(shell py3versions -r),cd python && $(python) setup.py test$(\n))
 
 clean:
 	rm -rf debian-distro-info ubuntu-distro-info python/build python/*.egg-info python/.pylint.d
diff -Nru distro-info-0.21/perl/Debian/DistroInfo.pm distro-info-1.0~deb10u1/perl/Debian/DistroInfo.pm
--- distro-info-0.21/perl/Debian/DistroInfo.pm	2019-02-09 17:15:09.000000000 -0400
+++ distro-info-1.0~deb10u1/perl/Debian/DistroInfo.pm	2021-04-22 11:54:50.000000000 -0400
@@ -77,7 +77,8 @@
             for my $col (@header) {
                 $row{$col} = shift(@raw_row) or undef;
             }
-            for my $col ('created', 'release', 'eol', 'eol-server') {
+            for my $col ('created', 'release', 'eol', 'eol-esm', 'eol-lts',
+                         'eol-elts', 'eol-server') {
                 if(defined($row{$col})) {
                     $row{$col} = Debian::DistroInfo::convert_date($row{$col});
                 }
@@ -249,6 +250,32 @@
         return @distros;
     }
 
+    sub supported_lts {
+        my ($self, $date) = @_;
+        $date = $self->{'date'} if (!defined($date));
+        my @distros;
+        for my $row ($self->_avail($date)) {
+            if (defined($row->{'eol'}) && $date > $row->{'eol'}
+                    && defined($row->{'eol-lts'}) && $date <= $row->{'eol-lts'}) {
+                push(@distros, $row->{'series'});
+            }
+        }
+        return @distros;
+    }
+
+    sub supported_elts {
+        my ($self, $date) = @_;
+        $date = $self->{'date'} if (!defined($date));
+        my @distros;
+        for my $row ($self->_avail($date)) {
+            if (defined($row->{'eol-lts'}) && $date > $row->{'eol-lts'}
+                    && defined($row->{'eol-elts'}) && $date <= $row->{'eol-elts'}) {
+                push(@distros, $row->{'series'});
+            }
+        }
+        return @distros;
+    }
+
     sub testing {
         my ($self, $date) = @_;
         $date = $self->{'date'} if (!defined($date));
@@ -327,6 +354,18 @@
                 push(@distros, $row->{'series'});
             }
         }
+        return @distros;
+    }
+
+    sub supported_esm {
+        my ($self, $date) = @_;
+        $date = $self->{'date'} if (!defined($date));
+        my @distros;
+        for my $row ($self->_avail($date)) {
+            if (defined($row->{'eol-esm'}) && $date <= $row->{'eol-esm'}) {
+                push(@distros, $row->{'series'});
+            }
+        }
         return @distros;
     }
 }
diff -Nru distro-info-0.21/perl/test.pl distro-info-1.0~deb10u1/perl/test.pl
--- distro-info-0.21/perl/test.pl	2019-02-09 17:15:09.000000000 -0400
+++ distro-info-1.0~deb10u1/perl/test.pl	2021-04-22 11:54:50.000000000 -0400
@@ -1,5 +1,5 @@
 #!/usr/bin/perl
-# Copyright (C) 2011-2012, Stefano Rivera <stefanor@debian.org>
+# Copyright (C) 2011-2019, Stefano Rivera <stefanor@debian.org>
 #
 # Permission to use, copy, modify, and/or distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -16,7 +16,7 @@
 use strict;
 use warnings;
 
-use Test::Simple tests => 32;
+use Test::Simple tests => 35;
 
 use lib '.';
 use Debian::DistroInfo;
@@ -55,35 +55,47 @@
 
 # Test DistroInfo:
 my @expected = ();
-my $date = Debian::DistroInfo::convert_date('2011-01-10');
+my $date1 = Debian::DistroInfo::convert_date('2011-01-10');
+my $date2 = Debian::DistroInfo::convert_date('2016-02-28');
+my $date3 = Debian::DistroInfo::convert_date('2020-06-29');
 
 my $deb = DebianDistroInfo->new();
 @all = ('buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', 'woody', 'sarge',
            'etch', 'lenny', 'squeeze', 'sid', 'experimental');
-@returned = $deb->all($date);
+@returned = $deb->all($date1);
 ok(unique(\@all, \@returned) == 0, 'Debian all');
 
-ok($deb->devel($date) eq 'sid', 'Debian devel');
-ok($deb->old($date) eq 'etch', 'Debian oldstable');
-ok($deb->stable($date) eq 'lenny', 'Debian stable');
-ok($deb->testing($date) eq 'squeeze', 'Debian testing');
+ok($deb->devel($date1) eq 'sid', 'Debian devel');
+ok($deb->old($date1) eq 'etch', 'Debian oldstable');
+ok($deb->stable($date1) eq 'lenny', 'Debian stable');
+ok($deb->testing($date1) eq 'squeeze', 'Debian testing');
 ok($deb->valid('sid'), 'Debian valid');
 ok($deb->valid('stable'), 'Debian valid');
 ok(!$deb->valid('foobar'), 'Debian invalid');
 
 @expected = ('lenny', 'squeeze', 'sid', 'experimental');
-@returned = $deb->supported($date);
+@returned = $deb->supported($date1);
 ok(symmetric_difference(\@expected, \@returned) == 0,
    'Debian supported');
 
+@expected = ('squeeze');
+@returned = $deb->supported_lts($date2);
+ok(symmetric_difference(\@expected, \@returned) == 0,
+   'Debian LTS');
+
+@expected = ('wheezy');
+@returned = $deb->supported_elts($date3);
+ok(symmetric_difference(\@expected, \@returned) == 0,
+   'Debian ELTS');
+
 @expected = ('buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', 'woody', 'sarge',
              'etch');
-@returned = $deb->unsupported($date);
+@returned = $deb->unsupported($date1);
 ok(symmetric_difference(\@expected, \@returned) == 0,
    'Debian unsupported');
 
 ok(!defined($deb->codename('foo')), 'Debian codename, invalid');
-ok($deb->codename('testing', $date) eq $deb->testing($date),
+ok($deb->codename('testing', $date1) eq $deb->testing($date1),
    'Debian codename');
 
 ok(!defined($deb->version('foo')), 'Debian version, invalid');
@@ -92,15 +104,15 @@
 my $ubu = UbuntuDistroInfo->new();
 @all = ('warty', 'hoary', 'breezy', 'dapper', 'edgy', 'feisty', 'gutsy',
         'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', 'maverick', 'natty');
-@returned = $ubu->all($date);
+@returned = $ubu->all($date1);
 ok(unique(\@all, \@returned) == 0, 'Ubuntu all');
 
 ok($ubu->version('Maverick Meerkat') eq '10.10', 'Ubuntu version');
 ok($ubu->version('lucid') eq '10.04 LTS', 'Ubuntu LTS version');
 
-ok($ubu->devel($date) eq 'natty', 'Ubuntu devel');
-ok($ubu->lts($date) eq 'lucid', 'Ubuntu LTS');
-ok($ubu->stable($date) eq 'maverick', 'Ubuntu stable');
+ok($ubu->devel($date1) eq 'natty', 'Ubuntu devel');
+ok($ubu->lts($date1) eq 'lucid', 'Ubuntu LTS');
+ok($ubu->stable($date1) eq 'maverick', 'Ubuntu stable');
 ok($ubu->valid('lucid'), 'Ubuntu valid');
 ok(!$ubu->valid(42), 'Ubuntu invalid');
 ok($ubu->is_lts('lucid'), 'Ubuntu is_lts');
@@ -108,13 +120,18 @@
 ok(!$ubu->is_lts('warty'), 'Ubuntu !is_lts');
 
 @expected = ('dapper', 'hardy', 'karmic', 'lucid', 'maverick', 'natty');
-@returned = $ubu->supported($date);
+@returned = $ubu->supported($date1);
 ok(symmetric_difference(\@expected, \@returned) == 0,
    'Ubuntu supported');
 
+@expected = ('precise', 'trusty', 'xenial');
+@returned = $ubu->supported_esm($date2);
+ok(symmetric_difference(\@expected, \@returned) == 0,
+   'Ubuntu ESM');
+
 @expected = ('warty', 'hoary', 'breezy', 'edgy', 'feisty', 'gutsy', 'intrepid',
              'jaunty');
-@returned = $ubu->unsupported($date);
+@returned = $ubu->unsupported($date1);
 ok(symmetric_difference(\@expected, \@returned) == 0,
    'Ubuntu unsupported');
 
diff -Nru distro-info-0.21/python/debian-distro-info distro-info-1.0~deb10u1/python/debian-distro-info
--- distro-info-0.21/python/debian-distro-info	2018-11-11 17:08:04.000000000 -0400
+++ distro-info-1.0~deb10u1/python/debian-distro-info	2021-04-22 11:54:50.000000000 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # Copyright (C) 2009-2011, Benjamin Drung <bdrung@debian.org>
 #
@@ -38,24 +38,29 @@
                         help="list all known versions")
     parser.add_argument("-d", "--devel", dest="devel", action="store_true",
                         help="latest development version")
-    parser.add_argument("-o", "--old", dest="old", action="store_true",
-                        help="latest old (stable) version")
+    parser.add_argument("-t", "--testing", dest="testing", action="store_true",
+                        help="current testing version")
     parser.add_argument("-s", "--stable", dest="stable", action="store_true",
                         help="latest stable version")
+    parser.add_argument("-o", "--old", dest="old", action="store_true",
+                        help="latest old (stable) version")
     parser.add_argument("--supported", dest="supported", action="store_true",
                         help="list of all supported stable versions")
-    parser.add_argument("-t", "--testing", dest="testing", action="store_true",
-                        help="current testing version")
+    parser.add_argument("-l", "--lts", dest="lts", action="store_true",
+                        help="list of all LTS supported stable versions")
+    parser.add_argument("-e", "--elts", dest="elts", action="store_true",
+                        help="list of all ELTS supported stable versions")
     parser.add_argument("--unsupported", dest="unsupported",
                         help="list of all unsupported stable versions")
 
     args = parser.parse_args()
 
-    versions = [args.all, args.devel, args.old, args.stable,
-                args.supported, args.testing, args.unsupported]
+    versions = [args.all, args.devel, args.lts, args.elts, args.old,
+                args.stable, args.supported, args.testing, args.unsupported]
     if len([x for x in versions if x]) != 1:
-        parser.error("You have to select exactly one of --all, --devel, --old, "
-                     "--stable, --supported, --testing, --unsupported.")
+        parser.error("You have to select exactly one of --all, --devel, "
+                     "--elts, --lts, --old, --stable, --supported, --testing, "
+                     "--unsupported.")
 
     if args.date is not None:
         try:
@@ -67,6 +72,7 @@
 
 
 def main():
+    # pylint: disable=too-many-branches
     args = parse_args()
     if args.all:
         for distro in DebianDistroInfo().all:
@@ -80,6 +86,12 @@
     elif args.supported:
         for distro in DebianDistroInfo().supported(args.date):
             sys.stdout.write(distro + "\n")
+    elif args.lts:
+        for distro in DebianDistroInfo().lts_supported(args.date):
+            sys.stdout.write(distro + "\n")
+    elif args.elts:
+        for distro in DebianDistroInfo().elts_supported(args.date):
+            sys.stdout.write(distro + "\n")
     elif args.testing:
         sys.stdout.write(DebianDistroInfo().testing(args.date) + "\n")
     elif args.unsupported:
diff -Nru distro-info-0.21/python/distro_info.py distro-info-1.0~deb10u1/python/distro_info.py
--- distro-info-0.21/python/distro_info.py	2019-02-09 17:18:08.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info.py	2021-04-22 11:54:50.000000000 -0400
@@ -48,18 +48,31 @@
     """Distribution data outdated."""
 
     def __init__(self):
-        super(DistroDataOutdated, self).__init__(
-            "Distribution data outdated. "
-            "Please check for an update for distro-info-data. See "
-            "/usr/share/doc/distro-info-data/README.Debian for details.")
+        super().__init__(
+            "Distribution data outdated. Please check for an update for distro-info-data. "
+            "See /usr/share/doc/distro-info-data/README.Debian for details."
+        )
 
 
 class DistroRelease(object):
     """Represents a distributions release"""
+
     # pylint: disable=too-few-public-methods
+    # pylint: disable=too-many-instance-attributes
 
-    def __init__(self, version, codename, series, created=None, release=None, eol=None,
-                 eol_server=None):
+    def __init__(
+            self,
+            version,
+            codename,
+            series,
+            created=None,
+            release=None,
+            eol=None,
+            eol_esm=None,
+            eol_lts=None,
+            eol_elts=None,
+            eol_server=None,
+    ):
         # pylint: disable=too-many-arguments
         self.version = version
         self.codename = codename
@@ -67,12 +80,18 @@
         self.created = created
         self.release = release
         self.eol = eol
+        self.eol_lts = eol_lts
+        self.eol_elts = eol_elts
+        self.eol_esm = eol_esm
         self.eol_server = eol_server
 
     def is_supported(self, date):
         """Check whether this release is supported on the given date."""
-        return date >= self.created and (self.eol is None or date <= self.eol or (
-            self.eol_server is not None and date <= self.eol_server))
+        return date >= self.created and (
+            self.eol is None
+            or date <= self.eol
+            or (self.eol_server is not None and date <= self.eol_server)
+        )
 
 
 def _get_date(row, column):
@@ -91,9 +110,18 @@
         csv_reader = csv.DictReader(csvfile)
         self._releases = []
         for row in csv_reader:
-            release = DistroRelease(row['version'], row['codename'], row['series'],
-                                    _get_date(row, 'created'), _get_date(row, 'release'),
-                                    _get_date(row, 'eol'), _get_date(row, 'eol-server'))
+            release = DistroRelease(
+                row["version"],
+                row["codename"],
+                row["series"],
+                _get_date(row, "created"),
+                _get_date(row, "release"),
+                _get_date(row, "eol"),
+                _get_date(row, "eol-esm"),
+                _get_date(row, "eol-lts"),
+                _get_date(row, "eol-elts"),
+                _get_date(row, "eol-server"),
+            )
             self._releases.append(release)
         csvfile.close()
         self._date = datetime.date.today()
@@ -127,8 +155,11 @@
         """Get latest development distribution based on the given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._avail(date) if x.release is None or
-                   (date < x.release and (x.eol is None or date <= x.eol))]
+        distros = [
+            x
+            for x in self._avail(date)
+            if x.release is None or (date < x.release and (x.eol is None or date <= x.eol))
+        ]
         if not distros:
             raise DistroDataOutdated()
         return self._format(result, distros[-1])
@@ -144,15 +175,20 @@
         if format_string == "release":
             return release.version
 
-        raise ValueError("Only codename, fullname, object, and release are allowed "
-                         "result values, but not '" + format_string + "'.")
+        raise ValueError(
+            "Only codename, fullname, object, and release are allowed "
+            "result values, but not '" + format_string + "'."
+        )
 
     def stable(self, date=None, result="codename"):
         """Get latest stable distribution based on the given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._avail(date) if x.release is not None and
-                   date >= x.release and (x.eol is None or date <= x.eol)]
+        distros = [
+            x
+            for x in self._avail(date)
+            if x.release is not None and date >= x.release and (x.eol is None or date <= x.eol)
+        ]
         if not distros:
             raise DistroDataOutdated()
         return self._format(result, distros[-1])
@@ -170,8 +206,7 @@
         if date is None:
             date = self._date
         supported = self.supported(date)
-        distros = [self._format(result, x) for x in self._avail(date)
-                   if x.series not in supported]
+        distros = [self._format(result, x) for x in self._avail(date) if x.series not in supported]
         return distros
 
 
@@ -179,7 +214,7 @@
     """provides information about Debian's distributions"""
 
     def __init__(self):
-        super(DebianDistroInfo, self).__init__("Debian")
+        super().__init__("Debian")
 
     def codename(self, release, date=None, default=None):
         """Map 'unstable', 'testing', etc. to their codenames."""
@@ -199,8 +234,11 @@
         """Get latest development distribution based on the given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._avail(date) if x.release is None or
-                   (date < x.release and (x.eol is None or date <= x.eol))]
+        distros = [
+            x
+            for x in self._avail(date)
+            if x.release is None or (date < x.release and (x.eol is None or date <= x.eol))
+        ]
         if len(distros) < 2:
             raise DistroDataOutdated()
         return self._format(result, distros[-2])
@@ -209,51 +247,85 @@
         """Get old (stable) Debian distribution based on the given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._avail(date)
-                   if x.release is not None and date >= x.release]
+        distros = [x for x in self._avail(date) if x.release is not None and date >= x.release]
         if len(distros) < 2:
             raise DistroDataOutdated()
         return self._format(result, distros[-2])
 
     def supported(self, date=None, result="codename"):
         """Get list of all supported Debian distributions based on the given
-           date."""
+        date."""
         if date is None:
             date = self._date
-        distros = [self._format(result, x) for x in self._avail(date)
-                   if x.eol is None or date <= x.eol]
+        distros = [
+            self._format(result, x) for x in self._avail(date) if x.eol is None or date <= x.eol
+        ]
+        return distros
+
+    def lts_supported(self, date=None, result="codename"):
+        """Get list of all LTS supported Debian distributions based on the given
+        date."""
+        if date is None:
+            date = self._date
+        distros = [
+            self._format(result, x)
+            for x in self._avail(date)
+            if (x.eol is not None and date > x.eol)
+            and (x.eol_lts is not None and date <= x.eol_lts)
+        ]
+        return distros
+
+    def elts_supported(self, date=None, result="codename"):
+        """Get list of all Extended LTS supported Debian distributions based on
+        the given date."""
+        if date is None:
+            date = self._date
+        distros = [
+            self._format(result, x)
+            for x in self._avail(date)
+            if (x.eol_lts is not None and date > x.eol_lts)
+            and (x.eol_elts is not None and date <= x.eol_elts)
+        ]
         return distros
 
     def testing(self, date=None, result="codename"):
         """Get latest testing Debian distribution based on the given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._avail(date) if (x.release is None and x.version) or
-                   (x.release is not None and date < x.release and
-                    (x.eol is None or date <= x.eol))]
+        distros = [
+            x
+            for x in self._avail(date)
+            if (x.release is None and x.version)
+            or (x.release is not None and date < x.release and (x.eol is None or date <= x.eol))
+        ]
         if not distros:
             raise DistroDataOutdated()
         return self._format(result, distros[-1])
 
     def valid(self, codename):
         """Check if the given codename is known."""
-        return (DistroInfo.valid(self, codename) or
-                codename in ["unstable", "testing", "stable", "oldstable"])
+        return DistroInfo.valid(self, codename) or codename in [
+            "unstable",
+            "testing",
+            "stable",
+            "oldstable",
+        ]
 
 
 class UbuntuDistroInfo(DistroInfo):
     """provides information about Ubuntu's distributions"""
 
     def __init__(self):
-        super(UbuntuDistroInfo, self).__init__("Ubuntu")
+        super().__init__("Ubuntu")
 
     def lts(self, date=None, result="codename"):
         """Get latest long term support (LTS) Ubuntu distribution based on the
-           given date."""
+        given date."""
         if date is None:
             date = self._date
-        distros = [x for x in self._releases if x.version.find("LTS") >= 0 and
-                   x.release <= date <= x.eol]
+        distros = [
+            x for x in self._releases if x.version.find("LTS") >= 0 and x.release <= date <= x.eol
+        ]
         if not distros:
             raise DistroDataOutdated()
         return self._format(result, distros[-1])
@@ -267,10 +339,24 @@
 
     def supported(self, date=None, result="codename"):
         """Get list of all supported Ubuntu distributions based on the given
-           date."""
+        date."""
+        if date is None:
+            date = self._date
+        distros = [
+            self._format(result, x)
+            for x in self._avail(date)
+            if date <= x.eol or (x.eol_server is not None and date <= x.eol_server)
+        ]
+        return distros
+
+    def supported_esm(self, date=None, result="codename"):
+        """Get list of all ESM supported Ubuntu distributions based on the
+        given date."""
         if date is None:
             date = self._date
-        distros = [self._format(result, x) for x in self._avail(date)
-                   if date <= x.eol or
-                   (x.eol_server is not None and date <= x.eol_server)]
+        distros = [
+            self._format(result, x)
+            for x in self._avail(date)
+            if x.eol_esm is not None and date <= x.eol_esm
+        ]
         return distros
diff -Nru distro-info-0.21/python/distro_info_test/__init__.py distro-info-1.0~deb10u1/python/distro_info_test/__init__.py
--- distro-info-0.21/python/distro_info_test/__init__.py	2018-11-11 17:03:58.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info_test/__init__.py	2021-04-22 11:54:50.000000000 -0400
@@ -24,7 +24,7 @@
 def get_source_files():
     """Return a list of sources files/directories (to check with flake8/pylint)"""
     scripts = ["debian-distro-info", "ubuntu-distro-info"]
-    modules = ["distro_info_test"]
+    modules = []
     py_files = ["distro_info.py", "setup.py"]
 
     files = []
@@ -41,8 +41,9 @@
         if is_script:
             with open(code_file, "rb") as script_file:
                 shebang = script_file.readline().decode("utf-8")
-            if ((sys.version_info[0] == 3 and "python3" in shebang)
-                    or ("python" in shebang and "python3" not in shebang)):
+            if (sys.version_info[0] == 3 and "python3" in shebang) or (
+                "python" in shebang and "python3" not in shebang
+            ):
                 files.append(code_file)
         else:
             files.append(code_file)
diff -Nru distro-info-0.21/python/distro_info_test/test_distro_info.py distro-info-1.0~deb10u1/python/distro_info_test/test_distro_info.py
--- distro-info-0.21/python/distro_info_test/test_distro_info.py	2019-02-09 17:15:09.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info_test/test_distro_info.py	2021-04-22 11:54:50.000000000 -0400
@@ -31,9 +31,21 @@
 
     def test_all(self):
         """Test: List all known Debian distributions."""
-        all_distros = set(["buzz", "rex", "bo", "hamm", "slink", "potato",
-                           "woody", "sarge", "etch", "lenny", "squeeze", "sid",
-                           "experimental"])
+        all_distros = {
+            "buzz",
+            "rex",
+            "bo",
+            "hamm",
+            "slink",
+            "potato",
+            "woody",
+            "sarge",
+            "etch",
+            "lenny",
+            "squeeze",
+            "sid",
+            "experimental",
+        }
         self.assertEqual(all_distros - set(self._distro_info.all), set())
 
     def test_devel(self):
@@ -50,8 +62,19 @@
 
     def test_supported(self):
         """Test: List all supported Debian distribution."""
-        self.assertEqual(self._distro_info.supported(self._date),
-                         ["lenny", "squeeze", "sid", "experimental"])
+        self.assertEqual(
+            self._distro_info.supported(self._date), ["lenny", "squeeze", "sid", "experimental"]
+        )
+
+    def test_lts_supported(self):
+        """Test: List all LTS supported Debian distribution."""
+        date = datetime.date(2016, 2, 28)
+        self.assertEqual(self._distro_info.lts_supported(date), ["squeeze"])
+
+    def test_elts_supported(self):
+        """Test: List all ELTS supported Debian distribution."""
+        date = datetime.date(2020, 6, 29)
+        self.assertEqual(self._distro_info.elts_supported(date), ["wheezy"])
 
     def test_testing(self):
         """Test: Get latest testing Debian distribution."""
@@ -65,41 +88,38 @@
 
     def test_unsupported(self):
         """Test: List all unsupported Debian distribution."""
-        unsupported = ["buzz", "rex", "bo", "hamm", "slink", "potato", "woody",
-                       "sarge", "etch"]
+        unsupported = ["buzz", "rex", "bo", "hamm", "slink", "potato", "woody", "sarge", "etch"]
         self.assertEqual(self._distro_info.unsupported(self._date), unsupported)
 
     def test_codename(self):
         """Test: Codename decoding"""
-        self.assertIsNone(self._distro_info.codename('foobar'))
-        self.assertEqual(self._distro_info.codename('testing', self._date),
-                         self._distro_info.testing(self._date))
+        self.assertIsNone(self._distro_info.codename("foobar"))
+        self.assertEqual(
+            self._distro_info.codename("testing", self._date),
+            self._distro_info.testing(self._date),
+        )
 
     def test_version(self):
         """Test: Version decoding"""
-        self.assertIsNone(self._distro_info.version('foobar'))
-        self.assertEqual(self._distro_info.version('lenny'), '5.0')
+        self.assertIsNone(self._distro_info.version("foobar"))
+        self.assertEqual(self._distro_info.version("lenny"), "5.0")
 
     def test_codename_result(self):
         """Test: Check result set to codename."""
         self.assertEqual(self._distro_info.old(self._date, "codename"), "etch")
-        self.assertEqual(self._distro_info.devel(self._date, result="codename"),
-                         "sid")
+        self.assertEqual(self._distro_info.devel(self._date, result="codename"), "sid")
 
     def test_fullname(self):
         """Test: Check result set to fullname."""
-        self.assertEqual(self._distro_info.stable(self._date, "fullname"),
-                         'Debian 5.0 "Lenny"')
+        self.assertEqual(self._distro_info.stable(self._date, "fullname"), 'Debian 5.0 "Lenny"')
         result = self._distro_info.testing(self._date, result="fullname")
         self.assertEqual(result, 'Debian 6.0 "Squeeze"')
 
     def test_release(self):
         """Test: Check result set to release."""
         self.assertEqual(self._distro_info.devel(self._date, "release"), "")
-        self.assertEqual(self._distro_info.testing(self._date, "release"),
-                         "6.0")
-        self.assertEqual(self._distro_info.stable(self._date, result="release"),
-                         "5.0")
+        self.assertEqual(self._distro_info.testing(self._date, "release"), "6.0")
+        self.assertEqual(self._distro_info.stable(self._date, result="release"), "5.0")
 
 
 class UbuntuDistroInfoTestCase(unittest.TestCase):  # pylint: disable=too-many-public-methods
@@ -111,9 +131,22 @@
 
     def test_all(self):
         """Test: List all known Ubuntu distributions."""
-        all_distros = set(["warty", "hoary", "breezy", "dapper", "edgy",
-                           "feisty", "gutsy", "hardy", "intrepid", "jaunty",
-                           "karmic", "lucid", "maverick", "natty"])
+        all_distros = {
+            "warty",
+            "hoary",
+            "breezy",
+            "dapper",
+            "edgy",
+            "feisty",
+            "gutsy",
+            "hardy",
+            "intrepid",
+            "jaunty",
+            "karmic",
+            "lucid",
+            "maverick",
+            "natty",
+        }
         self.assertEqual(all_distros - set(self._distro_info.all), set())
 
     def test_devel(self):
@@ -135,16 +168,13 @@
 
     def test_unsupported(self):
         """Test: List all unsupported Ubuntu distributions."""
-        unsupported = ["warty", "hoary", "breezy", "edgy", "feisty", "gutsy",
-                       "intrepid", "jaunty"]
+        unsupported = ["warty", "hoary", "breezy", "edgy", "feisty", "gutsy", "intrepid", "jaunty"]
         self.assertEqual(self._distro_info.unsupported(self._date), unsupported)
 
     def test_current_unsupported(self):
         """Test: List all unsupported Ubuntu distributions today."""
-        unsupported = set(["warty", "hoary", "breezy", "edgy", "feisty",
-                           "gutsy", "intrepid", "jaunty"])
-        self.assertEqual(unsupported -
-                         set(self._distro_info.unsupported()), set())
+        unsupported = {"warty", "hoary", "breezy", "edgy", "feisty", "gutsy", "intrepid", "jaunty"}
+        self.assertEqual(unsupported - set(self._distro_info.unsupported()), set())
 
     def test_valid(self):
         """Test: Check for valid Ubuntu distribution."""
@@ -160,24 +190,23 @@
     def test_codename(self):
         """Test: Check result set to codename."""
         self.assertEqual(self._distro_info.lts(self._date, "codename"), "lucid")
-        self.assertEqual(self._distro_info.devel(self._date, result="codename"),
-                         "natty")
+        self.assertEqual(self._distro_info.devel(self._date, result="codename"), "natty")
 
     def test_version(self):
         """Test: Check result set to version."""
-        self.assertEqual(self._distro_info.version("lucid"), '10.04 LTS')
-        self.assertEqual(self._distro_info.version("Maverick Meerkat"), '10.10')
+        self.assertEqual(self._distro_info.version("lucid"), "10.04 LTS")
+        self.assertEqual(self._distro_info.version("Maverick Meerkat"), "10.10")
 
     def test_fullname(self):
         """Test: Check result set to fullname."""
-        self.assertEqual(self._distro_info.stable(self._date, "fullname"),
-                         'Ubuntu 10.10 "Maverick Meerkat"')
-        self.assertEqual(self._distro_info.lts(self._date, result="fullname"),
-                         'Ubuntu 10.04 LTS "Lucid Lynx"')
+        self.assertEqual(
+            self._distro_info.stable(self._date, "fullname"), 'Ubuntu 10.10 "Maverick Meerkat"'
+        )
+        self.assertEqual(
+            self._distro_info.lts(self._date, result="fullname"), 'Ubuntu 10.04 LTS "Lucid Lynx"'
+        )
 
     def test_release(self):
         """Test: Check result set to release."""
-        self.assertEqual(self._distro_info.devel(self._date, "release"),
-                         "11.04")
-        self.assertEqual(self._distro_info.lts(self._date, result="release"),
-                         "10.04 LTS")
+        self.assertEqual(self._distro_info.devel(self._date, "release"), "11.04")
+        self.assertEqual(self._distro_info.lts(self._date, result="release"), "10.04 LTS")
diff -Nru distro-info-0.21/python/distro_info_test/test_flake8.py distro-info-1.0~deb10u1/python/distro_info_test/test_flake8.py
--- distro-info-0.21/python/distro_info_test/test_flake8.py	2018-11-11 17:02:27.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info_test/test_flake8.py	2021-04-22 11:54:50.000000000 -0400
@@ -31,21 +31,35 @@
 
     def test_flake8(self):
         """Test: Run flake8 on Python source code"""
-        cmd = [sys.executable, "-m", "flake8", "--max-line-length=99"] + get_source_files()
+        cmd = [
+            sys.executable,
+            "-m",
+            "flake8",
+            "--ignore",
+            "H301,H403,H405,W504,W503",
+            "--max-line-length=99",
+        ] + get_source_files()
         if unittest_verbosity() >= 2:
             sys.stderr.write("Running following command:\n{}\n".format(" ".join(cmd)))
-        process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
-                                   stderr=subprocess.PIPE, close_fds=True)
+        process = subprocess.Popen(
+            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True
+        )
 
         out, err = process.communicate()
         if process.returncode != 0:  # pragma: no cover
             msgs = []
             if err:
-                msgs.append("flake8 exited with code {} and has unexpected output on stderr:\n{}"
-                            .format(process.returncode, err.decode().rstrip()))
+                msgs.append(
+                    "flake8 exited with code {} and has unexpected output on stderr:\n{}".format(
+                        process.returncode, err.decode().rstrip()
+                    )
+                )
             if out:
                 msgs.append("flake8 found issues:\n{}".format(out.decode().rstrip()))
             if not msgs:
-                msgs.append("flake8 exited with code {} and has no output on stdout or stderr."
-                            .format(process.returncode))
+                msgs.append(
+                    "flake8 exited with code {} and has no output on stdout or stderr.".format(
+                        process.returncode
+                    )
+                )
             self.fail("\n".join(msgs))
diff -Nru distro-info-0.21/python/distro_info_test/test_help.py distro-info-1.0~deb10u1/python/distro_info_test/test_help.py
--- distro-info-0.21/python/distro_info_test/test_help.py	2017-04-30 15:43:03.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info_test/test_help.py	2021-04-22 11:54:50.000000000 -0400
@@ -31,23 +31,29 @@
     @classmethod
     def populate(cls):
         for script in setup.SCRIPTS:
-            setattr(cls, 'test_' + script, cls.make_help_tester(script))
+            setattr(cls, "test_" + script, cls.make_help_tester(script))
 
     @classmethod
     def make_help_tester(cls, script):
         def tester(self):
-            null = open('/dev/null', 'r')
-            process = subprocess.Popen(['./' + script, '--help'],
-                                       close_fds=True, stdin=null,
-                                       stdout=subprocess.PIPE,
-                                       stderr=subprocess.PIPE)
+            null = open("/dev/null", "r")
+            process = subprocess.Popen(
+                ["./" + script, "--help"],
+                close_fds=True,
+                stdin=null,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE,
+            )
             started = time.time()
             out = []
 
             fds = [process.stdout.fileno(), process.stderr.fileno()]
             for file_descriptor in fds:
-                fcntl.fcntl(file_descriptor, fcntl.F_SETFL,
-                            fcntl.fcntl(file_descriptor, fcntl.F_GETFL) | os.O_NONBLOCK)
+                fcntl.fcntl(
+                    file_descriptor,
+                    fcntl.F_SETFL,
+                    fcntl.fcntl(file_descriptor, fcntl.F_GETFL) | os.O_NONBLOCK,
+                )
 
             while time.time() - started < TIMEOUT:
                 for file_descriptor in select.select(fds, [], fds, TIMEOUT)[0]:
@@ -62,10 +68,13 @@
                     os.kill(process.pid, signal.SIGKILL)
             null.close()
 
-            self.assertEqual(process.poll(), 0,
-                             "%s failed to return usage within %i seconds.\n"
-                             "Output:\n%s"
-                             % (script, TIMEOUT, ''.encode('ascii').join(out)))
+            self.assertEqual(
+                process.poll(),
+                0,
+                "%s failed to return usage within %i seconds.\n"
+                "Output:\n%s" % (script, TIMEOUT, "".encode("ascii").join(out)),
+            )
             process.stdout.close()
             process.stderr.close()
+
         return tester
diff -Nru distro-info-0.21/python/distro_info_test/test_pylint.py distro-info-1.0~deb10u1/python/distro_info_test/test_pylint.py
--- distro-info-0.21/python/distro_info_test/test_pylint.py	2018-11-11 17:02:27.000000000 -0400
+++ distro-info-1.0~deb10u1/python/distro_info_test/test_pylint.py	2021-04-22 11:54:50.000000000 -0400
@@ -40,8 +40,9 @@
         cmd = [sys.executable, "-m", "pylint", "--rcfile=" + CONFIG, "--"] + get_source_files()
         if unittest_verbosity() >= 2:
             sys.stderr.write("Running following command:\n{}\n".format(" ".join(cmd)))
-        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                                   close_fds=True)
+        process = subprocess.Popen(
+            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True
+        )
         out, err = process.communicate()
 
         if process.returncode != 0:  # pragma: no cover
@@ -50,19 +51,26 @@
             # ------------------------------------
             # Your code has been rated at 10.00/10
             #
-            out = re.sub("^(-+|Your code has been rated at .*)$", "", out.decode(),
-                         flags=re.MULTILINE).rstrip()
+            out = re.sub(
+                "^(-+|Your code has been rated at .*)$", "", out.decode(), flags=re.MULTILINE
+            ).rstrip()
 
             # Strip logging of used config file (introduced in pylint 1.8)
             err = re.sub("^Using config file .*\n", "", err.decode()).rstrip()
 
             msgs = []
             if err:
-                msgs.append("pylint exited with code {} and has unexpected output on stderr:\n{}"
-                            .format(process.returncode, err))
+                msgs.append(
+                    "pylint exited with code {} and has unexpected output on stderr:\n{}".format(
+                        process.returncode, err
+                    )
+                )
             if out:
                 msgs.append("pylint found issues:\n{}".format(out))
             if not msgs:
-                msgs.append("pylint exited with code {} and has no output on stdout or stderr."
-                            .format(process.returncode))
+                msgs.append(
+                    "pylint exited with code {} and has no output on stdout or stderr.".format(
+                        process.returncode
+                    )
+                )
             self.fail("\n".join(msgs))
diff -Nru distro-info-0.21/python/setup.py distro-info-1.0~deb10u1/python/setup.py
--- distro-info-0.21/python/setup.py	2018-11-11 17:01:13.000000000 -0400
+++ distro-info-1.0~deb10u1/python/setup.py	2021-04-22 11:54:50.000000000 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import os
 import re
@@ -7,11 +7,8 @@
 
 
 PACKAGES = []
-PY_MODULES = ['distro_info']
-SCRIPTS = [
-    'debian-distro-info',
-    'ubuntu-distro-info',
-]
+PY_MODULES = ["distro_info"]
+SCRIPTS = ["debian-distro-info", "ubuntu-distro-info"]
 
 
 def get_debian_version():
@@ -26,9 +23,9 @@
     return version
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     setup(
-        name='distro-info',
+        name="distro-info",
         version=get_debian_version(),
         py_modules=PY_MODULES,
         packages=PACKAGES,
diff -Nru distro-info-0.21/python/ubuntu-distro-info distro-info-1.0~deb10u1/python/ubuntu-distro-info
--- distro-info-0.21/python/ubuntu-distro-info	2018-11-11 17:07:21.000000000 -0400
+++ distro-info-1.0~deb10u1/python/ubuntu-distro-info	2021-04-22 11:54:50.000000000 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # Copyright (C) 2009-2011, Benjamin Drung <bdrung@debian.org>
 #
@@ -38,10 +38,10 @@
                         help="list all known versions")
     parser.add_argument("-d", "--devel", dest="devel", action="store_true",
                         help="latest development version")
-    parser.add_argument("--lts", dest="lts", action="store_true",
-                        help="latest long term support (LTS) version")
     parser.add_argument("-s", "--stable", dest="stable", action="store_true",
                         help="latest stable version")
+    parser.add_argument("--lts", dest="lts", action="store_true",
+                        help="latest long term support (LTS) version")
     parser.add_argument("--supported", dest="supported", action="store_true",
                         help="list of all supported stable versions")
     parser.add_argument("--unsupported", dest="unsupported", action="store_true",
diff -Nru distro-info-0.21/shell/debian-distro-info.in distro-info-1.0~deb10u1/shell/debian-distro-info.in
--- distro-info-0.21/shell/debian-distro-info.in	2012-03-27 06:20:02.000000000 -0400
+++ distro-info-1.0~deb10u1/shell/debian-distro-info.in	2021-04-22 11:54:50.000000000 -0400
@@ -17,7 +17,7 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 DISTRO_INFO_NAME="Debian"
-DISTRO_INFO_ARGS="--all --devel --oldstable --stable --supported
+DISTRO_INFO_ARGS="--all --devel --elts --lts --oldstable --stable --supported
                   --testing --unsupported"
 DISTRO_INFO_DATA="/usr/share/distro-info/debian.csv"
 
@@ -32,10 +32,12 @@
       --date=DATE    date for calculating the version (default: today)
   -a  --all          list all known versions
   -d  --devel        latest development version
-  -o  --oldstable    latest oldstable version
+  -t  --testing      current testing version
   -s  --stable       latest stable version
+  -o  --oldstable    latest oldstable version
       --supported    list of all supported stable versions
-  -t  --testing      current testing version
+  -l  --lts          list of all LTS versions
+  -e  --elts         list of all Extended LTS versions
       --unsupported  list of all unsupported stable versions
   -c  --codename     print the codename (default)
   -r  --release      print the release version
@@ -59,6 +61,15 @@
 		store
 	return 1;
 }
+cb_supported() {
+	date_ge "$eol" "$CMP_DATE" && created
+}
+cb_lts() {
+	date_ge "$eollts" "$CMP_DATE" && ! date_ge "$eol" "$CMP_DATE" && created
+}
+cb_elts() {
+	date_ge "$eolelts" "$CMP_DATE" && ! date_ge "$eollts" "$CMP_DATE" && created
+}
 
 main "$@"
 
diff -Nru distro-info-0.21/shell/distro-info-util.sh distro-info-1.0~deb10u1/shell/distro-info-util.sh
--- distro-info-0.21/shell/distro-info-util.sh	2012-05-28 19:24:55.000000000 -0400
+++ distro-info-1.0~deb10u1/shell/distro-info-util.sh	2021-04-22 11:54:50.000000000 -0400
@@ -25,7 +25,14 @@
 	s_created=$created;
 	s_release=$release;
 	s_eol=$eol;
+#BEGIN debian#
+	s_eollts=$eollts;
+	s_eolelts=$eolelts;
+#END debian#
+#BEGIN ubuntu#
 	s_eols=$eols;
+	s_eolesm=$eolesm;
+#END ubuntu#
 }
 restore() {
 	# restore data previously stored with store
@@ -35,7 +42,14 @@
 	created=$s_created;
 	release=$s_release;
 	eol=$s_eol;
+#BEGIN debian#
+	eollts=$s_eollts;
+	eolelts=$s_eolelts;
+#END debian#
+#BEGIN ubuntu#
 	eols=$s_eols;
+	eolesm=$s_eolesm;
+#END ubuntu#
 }
 
 created() {
@@ -60,7 +74,13 @@
 next_is() {
 	# call a function as if you were calling it for next
 	local version=$n_version codename=$n_codename series=$n_series
-	local created=$n_created release=$n_release eol=$n_eol eols=$n_eols
+	local created=$n_created release=$n_release eol=$n_eol
+#BEGIN debian#
+	local eollts=$n_eollts eolelts=$in_eolelts
+#END debian#
+#BEGIN ubuntu#
+	local eols=$n_eols eolesm=$n_eolesm
+#END ubuntu#
 	"$@"
 }
 
@@ -75,9 +95,6 @@
 	released && [ -n "$n_version" ] && ! next_is released && store
 	return 1;
 }
-cb_supported() {
-	date_ge "$eols" "$CMP_DATE" && created
-}
 cb_unsupported() {
 	created && ! cb_supported
 }
@@ -97,20 +114,40 @@
 	local callback="$1" fmt="$2" found=0
 	shift 2;
 	IFS=","
-	local version codename series created release eol eols
-	local n_version n_codename n_series n_created n_release n_eol n_eols
+	local version codename series created release eol
+	local n_version n_codename n_series n_created n_release n_eol
+#BEGIN debian#
+	local eollts n_eollts eolelts n_eolelts
+#END debian#
+#BEGIN ubuntu#
+	local eols n_eols eolesm n_eolesm
+#END ubuntu#
 	{
 	read tmpvar # header of file
 	read version codename series created release eol eols
 	[ -n "$eol" ] || eol="9999-99-99"
 	[ -n "$eols" ] || eols=$eol
-	while read n_version n_codename n_series n_created n_release n_eol n_eols; do
+	while read n_version n_codename n_series n_created n_release n_eol \
+#BEGIN debian#
+		n_eollts n_eolelts
+#END debian#
+#BEGIN ubuntu#
+		n_eols n_eolesm
+#END ubuntu#
+	do
 		[ -n "$n_eol" ] || n_eol="9999-99-99"
+#BEGIN ubuntu#
 		[ -n "$n_eols" ] || n_eols=$n_eol
+#END ubuntu#
 		"$callback" && found=$(($found+1)) && "$fmt"
 		version=$n_version; codename=$n_codename; series=$n_series
 		created=$n_created; release=$n_release;   eol=$n_eol;
-		eols=$n_eols
+#BEGIN debian#
+		eollts=$n_eollts; eolelts=$n_eolelts;
+#END debian#
+#BEGIN ubuntu#
+		eols=$n_eols; eolesm=$n_eolesm;
+#END ubuntu#
 	done
 	} < "$DISTRO_INFO_DATA"
 
@@ -160,11 +197,11 @@
 			-a|--all)
 				[ -z "$callback" ] || { not_exactly_one; return 1; }
 				callback="all";;
-		   	--date=*)
+			--date=*)
 				date=${1#*=};
 				[ -n "$date" ] || { date_requires_arg; return 1; }
 				;;
-		   	--date)
+			--date)
 				date="$2";
 				[ -n "$2" ] || { date_requires_arg; return 1; }
 				shift;;
@@ -181,11 +218,20 @@
 			-r|--release)  fmt="print_release";;
 			-f|--fullname) fmt="print_fullname";;
 #BEGIN ubuntu#
-		   	--lts)
+			--lts)
 				[ -z "$callback" ] || { not_exactly_one; return 1; }
 				callback="lts";;
+			--supported-esm)
+				[ -z "$callback" ] || { not_exactly_one; return 1; }
+				callback="supported_esm";;
 #END ubuntu#
 #BEGIN debian#
+			-e|--elts)
+				[ -z "$callback" ] || { not_exactly_one; return 1; }
+				callback="elts";;
+			-l|--lts)
+				[ -z "$callback" ] || { not_exactly_one; return 1; }
+				callback="lts";;
 			-o|--oldstable|--old)
 				[ -z "$callback" ] || { not_exactly_one; return 1; }
 				callback="oldstable";;
diff -Nru distro-info-0.21/shell/Makefile distro-info-1.0~deb10u1/shell/Makefile
--- distro-info-0.21/shell/Makefile	2012-04-02 09:47:45.000000000 -0400
+++ distro-info-1.0~deb10u1/shell/Makefile	2021-04-22 11:54:50.000000000 -0400
@@ -3,10 +3,10 @@
 
 build: debian-distro-info ubuntu-distro-info
 
-%-distro-info: debian-distro-info.in distro-info-util.sh
+%-distro-info: %-distro-info.in distro-info-util.sh
 	sed -e '/^\. .*distro-info-util.sh\"$$/r distro-info-util.sh' $< | \
 		sed -e '/^##/d;/^\. .*distro-info-util.sh\"$$/d' | \
-		python -c 'import re,sys;print re.sub("(?<=\n)#BEGIN \w*#\n(.|\n)*?\n#END \w*#\n", "", re.sub("(?<=\n)#(BEGIN|END) $*#\n", "", sys.stdin.read())),' > $@
+		python3 -c 'import re,sys;print(re.sub("(?<=\n)#BEGIN \w*#\n(.|\n)*?\n#END \w*#\n", "", re.sub("(?<=\n)#(BEGIN|END) $*#\n", "", sys.stdin.read())), end="")' > $@
 	chmod +x $@
 
 install: debian-distro-info ubuntu-distro-info
diff -Nru distro-info-0.21/shell/ubuntu-distro-info.in distro-info-1.0~deb10u1/shell/ubuntu-distro-info.in
--- distro-info-0.21/shell/ubuntu-distro-info.in	2012-03-27 06:20:06.000000000 -0400
+++ distro-info-1.0~deb10u1/shell/ubuntu-distro-info.in	2021-04-22 11:54:50.000000000 -0400
@@ -17,27 +17,29 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 DISTRO_INFO_NAME="Ubuntu"
-DISTRO_INFO_ARGS="--all --devel --lts --stable --supported --unsupported"
+DISTRO_INFO_ARGS="--all --devel --lts --stable --supported --supported-esm
+                  --unsupported"
 DISTRO_INFO_DATA="/usr/share/distro-info/ubuntu.csv"
 
 . "${0%/*}/distro-info-util.sh"
 
 Usage() {
 	cat <<EOF
-Usage: ${0##*/} [options]
+Usage: ubuntu-distro-info [options]
 
 Options:
-  -h  --help         show this help message and exit
-      --date=DATE    date for calculating the version (default: today)
-  -a  --all          list all known versions
-  -d  --devel        latest development version
-      --lts          latest long term support (LTS) version
-  -s  --stable       latest stable version
-      --supported    list of all supported stable versions
-      --unsupported  list of all unsupported stable versions
-  -c  --codename     print the codename (default)
-  -r  --release      print the release version
-  -f  --fullname     print the full name
+  -h  --help          show this help message and exit
+      --date=DATE     date for calculating the version (default: today)
+  -a  --all           list all known versions
+  -d  --devel         latest development version
+  -s  --stable        latest stable version
+      --lts           latest long term support (LTS) version
+      --supported     list of all supported stable versions
+      --supported-esm list of all supported stable versions
+      --unsupported   list of all unsupported stable versions
+  -c  --codename      print the codename (default)
+  -r  --release       print the release version
+  -f  --fullname      print the full name
 
 See ubuntu-distro-info(1) for more info.
 EOF
@@ -47,6 +49,12 @@
 	devel && store
 	return 1
 }
+cb_supported() {
+	date_ge "$eols" "$CMP_DATE" && created
+}
+cb_supported_esm() {
+	date_ge "$eolesm" "$CMP_DATE" && created
+}
 cb_lts() {
 	[ "${version#*LTS}" != "${version}" ] && released && store
 	return 1;
diff -Nru distro-info-0.21/test-debian-distro-info distro-info-1.0~deb10u1/test-debian-distro-info
--- distro-info-0.21/test-debian-distro-info	2018-10-11 20:11:26.000000000 -0400
+++ distro-info-1.0~deb10u1/test-debian-distro-info	2021-04-22 11:54:50.000000000 -0400
@@ -69,6 +69,14 @@
     success "--date=2011-01-10 --supported" "$result"
 }
 
+testLTS() {
+    success "--date=2016-02-28 --lts" "squeeze"
+}
+
+testELTS() {
+    success "--date=2018-09-01 --elts" "wheezy"
+}
+
 testUnsupported() {
     local result="buzz
 rex
@@ -160,15 +168,17 @@
       --date=DATE        date for calculating the version (default: today)
       --series=SERIES    series to calculate the version for
   -y[MILESTONE]          additionally, display days until milestone
-      --days=[MILESTONE] (created, release, eol)
+      --days=[MILESTONE] (created, release, eol, eol-lts, eol-elts)
       --alias=DIST       print the alias (oldstable, stable, testing, unstable)
                          relative to the given distribution codename
   -a  --all              list all known versions
   -d  --devel            latest development version
-  -o  --oldstable        latest oldstable version
+  -t  --testing          current testing version
   -s  --stable           latest stable version
+  -o  --oldstable        latest oldstable version
       --supported        list of all supported stable versions
-  -t  --testing          current testing version
+  -l  --lts              list of all LTS supported versions
+  -e  --elts             list of all Extended LTS supported versions
       --unsupported      list of all unsupported stable versions
   -c  --codename         print the codename (default)
   -f  --fullname         print the full name
@@ -180,7 +190,7 @@
 }
 
 testExactlyOne() {
-    local result='debian-distro-info: You have to select exactly one of --alias, --all, --devel, --oldstable, --stable, --supported, --series, --testing, --unsupported.'
+    local result='debian-distro-info: You have to select exactly one of --alias, --all, --devel, --elts, --lts, --oldstable, --stable, --supported, --series, --testing, --unsupported.'
     failure "" "$result"
     failure "-ad" "$result"
     failure "--alias foo -a" "$result"
@@ -189,7 +199,7 @@
 testUnrecognizedOption() {
     failure "--foo" "debian-distro-info: unrecognized option \`--foo'"
     failure "-x" "debian-distro-info: unrecognized option \`-x'"
-    failure "--lts" "debian-distro-info: unrecognized option \`--lts'"
+    failure "--supported-esm" "debian-distro-info: unrecognized option \`--supported-esm'"
 }
 
 testUnrecognizedArguments() {
@@ -315,6 +325,41 @@
     success "--testing --date=$date --days=eol -c" "etch 1045"
     success "--testing --date=$date --days=eol -f" "Debian 4.0 \"Etch\" 1045"
     success "--testing --date=$date --days=eol -r" "4.0 1045"
+
+    # day before wheezy was released
+    date=2013-05-03
+
+    success "--testing --date=$date" "wheezy"
+
+    success "--testing --date=$date --days=created" "-817"
+    success "--testing --date=$date --days=created -c" "wheezy -817"
+    success "--testing --date=$date --days=created -f" "Debian 7 \"Wheezy\" -817"
+    success "--testing --date=$date --days=created -r" "7 -817"
+
+    success "--testing --date=$date --days" "1"
+    success "--testing --date=$date --days -c" "wheezy 1"
+    success "--testing --date=$date --days -f" "Debian 7 \"Wheezy\" 1"
+    success "--testing --date=$date --days -r" "7 1"
+
+    success "--testing --date=$date --days=release" "1"
+    success "--testing --date=$date --days=release -c" "wheezy 1"
+    success "--testing --date=$date --days=release -f" "Debian 7 \"Wheezy\" 1"
+    success "--testing --date=$date --days=release -r" "7 1"
+
+    success "--testing --date=$date --days=eol" "1089"
+    success "--testing --date=$date --days=eol -c" "wheezy 1089"
+    success "--testing --date=$date --days=eol -f" "Debian 7 \"Wheezy\" 1089"
+    success "--testing --date=$date --days=eol -r" "7 1089"
+
+    success "--testing --date=$date --days=eol-lts" "1854"
+    success "--testing --date=$date --days=eol-lts -c" "wheezy 1854"
+    success "--testing --date=$date --days=eol-lts -f" "Debian 7 \"Wheezy\" 1854"
+    success "--testing --date=$date --days=eol-lts -r" "7 1854"
+
+    success "--testing --date=$date --days=eol-elts" "2615"
+    success "--testing --date=$date --days=eol-elts -c" "wheezy 2615"
+    success "--testing --date=$date --days=eol-elts -f" "Debian 7 \"Wheezy\" 2615"
+    success "--testing --date=$date --days=eol-elts -r" "7 2615"
 }
 
 . shunit2
diff -Nru distro-info-0.21/test-ubuntu-distro-info distro-info-1.0~deb10u1/test-ubuntu-distro-info
--- distro-info-0.21/test-ubuntu-distro-info	2018-10-11 20:11:26.000000000 -0400
+++ distro-info-1.0~deb10u1/test-ubuntu-distro-info	2021-04-22 11:54:50.000000000 -0400
@@ -117,9 +117,9 @@
     success "--date=2011-01-10 --fullname --lts --days=eol" \
         'Ubuntu 10.04 LTS "Lucid Lynx" 850'
     success "--date=2011-01-10 --fullname --lts -yeol-server" \
-        'Ubuntu 10.04 LTS "Lucid Lynx" 1570'
+        'Ubuntu 10.04 LTS "Lucid Lynx" 1571'
     success "--date=2011-01-10 --fullname --lts --days=eol-server" \
-        'Ubuntu 10.04 LTS "Lucid Lynx" 1570'
+        'Ubuntu 10.04 LTS "Lucid Lynx" 1571'
 }
 
 testRelease() {
@@ -141,9 +141,9 @@
     success "--date=2011-01-10 --lts --release -yeol" \
         "10.04 LTS 850"
     success "--date=2011-01-10 --lts --release --days=eol-server" \
-        "10.04 LTS 1570"
+        "10.04 LTS 1571"
     success "--date=2011-01-10 --lts --release -yeol-server" \
-        "10.04 LTS 1570"
+        "10.04 LTS 1571"
 
     success "--date=2011-01-10 -r --stable" "10.10"
 }
@@ -171,12 +171,13 @@
       --date=DATE        date for calculating the version (default: today)
       --series=SERIES    series to calculate the version for
   -y[MILESTONE]          additionally, display days until milestone
-      --days=[MILESTONE] (created, release, eol, eol-server)
+      --days=[MILESTONE] (created, release, eol, eol-server, eol-esm)
   -a  --all              list all known versions
   -d  --devel            latest development version
-      --lts              latest long term support (LTS) version
   -s  --stable           latest stable version
+      --lts              latest long term support (LTS) version
       --supported        list of all supported stable versions
+      --supported-esm    list of all Ubuntu Advantage supported stable versions
       --unsupported      list of all unsupported stable versions
   -c  --codename         print the codename (default)
   -f  --fullname         print the full name
@@ -188,7 +189,7 @@
 }
 
 testExactlyOne() {
-    local result='ubuntu-distro-info: You have to select exactly one of --all, --devel, --latest, --lts, --stable, --supported, --series, --unsupported.'
+    local result='ubuntu-distro-info: You have to select exactly one of --all, --devel, --latest, --lts, --stable, --supported, --supported-esm, --series, --unsupported.'
     failure "" "$result"
     failure "--date=2009-01-10 -sad" "$result"
 }
@@ -271,10 +272,10 @@
     success "--date=$date --lts --days=eol -f" "Ubuntu 10.04 LTS \"Lucid Lynx\" 1105"
     success "--date=$date --lts --days=eol -r" "10.04 LTS 1105"
 
-    success "--date=$date --lts --days=eol-server" "1825"
-    success "--date=$date --lts --days=eol-server -c" "lucid 1825"
-    success "--date=$date --lts --days=eol-server -f" "Ubuntu 10.04 LTS \"Lucid Lynx\" 1825"
-    success "--date=$date --lts --days=eol-server -r" "10.04 LTS 1825"
+    success "--date=$date --lts --days=eol-server" "1826"
+    success "--date=$date --lts --days=eol-server -c" "lucid 1826"
+    success "--date=$date --lts --days=eol-server -f" "Ubuntu 10.04 LTS \"Lucid Lynx\" 1826"
+    success "--date=$date --lts --days=eol-server -r" "10.04 LTS 1826"
 
     # date precise released
     date=2012-04-26
@@ -296,15 +297,15 @@
     success "--date=$date --lts --days -f" "Ubuntu 12.04 LTS \"Precise Pangolin\" 0"
     success "--date=$date --lts --days -r" "12.04 LTS 0"
 
-    success "--date=$date --lts --days=eol" "1826"
-    success "--date=$date --lts --days=eol -c" "precise 1826"
-    success "--date=$date --lts --days=eol -f" "Ubuntu 12.04 LTS \"Precise Pangolin\" 1826"
-    success "--date=$date --lts --days=eol -r" "12.04 LTS 1826"
-
-    success "--date=$date --lts --days=eol-server" "(unknown)"
-    success "--date=$date --lts --days=eol-server -c" "precise (unknown)"
-    success "--date=$date --lts --days=eol-server -f" "Ubuntu 12.04 LTS \"Precise Pangolin\" (unknown)"
-    success "--date=$date --lts --days=eol-server -r" "12.04 LTS (unknown)"
+    success "--date=$date --lts --days=eol" "1828"
+    success "--date=$date --lts --days=eol -c" "precise 1828"
+    success "--date=$date --lts --days=eol -f" "Ubuntu 12.04 LTS \"Precise Pangolin\" 1828"
+    success "--date=$date --lts --days=eol -r" "12.04 LTS 1828"
+
+    success "--date=$date --lts --days=eol-server" "1828"
+    success "--date=$date --lts --days=eol-server -c" "precise 1828"
+    success "--date=$date --lts --days=eol-server -f" "Ubuntu 12.04 LTS \"Precise Pangolin\" 1828"
+    success "--date=$date --lts --days=eol-server -r" "12.04 LTS 1828"
 
     # day before raring was released
     date=2013-04-24
diff -Nru distro-info-0.21/ubuntu-distro-info.c distro-info-1.0~deb10u1/ubuntu-distro-info.c
--- distro-info-0.21/ubuntu-distro-info.c	2014-05-10 13:00:26.000000000 -0400
+++ distro-info-1.0~deb10u1/ubuntu-distro-info.c	2021-04-22 11:54:50.000000000 -0400
@@ -16,7 +16,7 @@
 
 #define UBUNTU
 #define CSV_NAME "ubuntu"
-#define CSV_HEADER "version,codename,series,created,release,eol,eol-server"
+#define CSV_HEADER "version,codename,series,created,release,eol,eol-server,eol-esm"
 #define DISTRO_NAME "Ubuntu"
 #define NAME "ubuntu-distro-info"
 
diff -Nru distro-info-data-0.41+deb10u3/debian/changelog distro-info-data-0.47~deb10u1/debian/changelog
--- distro-info-data-0.41+deb10u3/debian/changelog	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/changelog	2021-04-22 11:46:22.000000000 -0400
@@ -1,3 +1,80 @@
+distro-info-data (0.47~deb10u1) buster; urgency=medium
+
+  * Backport 0.47 to buster. Highlights:
+    - Add "eol-esm" for Ubuntu Extended Security Maintenance support.
+    - Add "eol-lts" for Debian LTS (Closes: #782685)
+    - Add "eol-elts" for Debian ELTS.
+    - Add estimated dates for Buster EOL and Buster LTS EOL.
+    - Add Debian 13 "Trixie", with a rough date.
+    - Correct the EOL date for Debian Jessie.
+    - Tweak eol and eol-esm dates, by a couple of days, for Ubuntu 6.10, 9.10,
+      10.04, 12.04, 15.04, 15.10, 19.04 to match announced EOL dates.
+    - Add Ubuntu 21.04, Impish Indri.
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:46:22 -0400
+
+distro-info-data (0.47) unstable; urgency=medium
+
+  * Add Ubuntu 21.04, Impish Indri.
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 10:30:18 -0400
+
+distro-info-data (0.46) unstable; urgency=medium
+
+  * Add "eol-server" dates matching "eol", for LTS releases, as there hasn't
+    been a distinction between the two, for a while.
+    (Closes: #922090, LP: #1814976).
+  * Add "eol-esm" column: EOL for Ubuntu Extended Security Maintenance support.
+    (LP: #1808038)
+  * Drop ancient Replaces: distro-info (<< 0.3~). No longer needed.
+  * Add "eol-lts" for Debian LTS (Closes: #782685)
+  * Add estimated dates for Buster EOL and Buster LTS EOL.
+  * Publish the data to GitLab pages. (Closes: #973904)
+  * Bump Standards-Version to 4.5.1, no changes needed.
+  * Bump copyright years.
+  * Correct the EOL date for Debian Jessie.
+  * Add Debian 13 "Trixie", with a rough date.
+  * Add "up-to-date" testing tool.
+  * Add an autopkgtest, running the validation and up-to-date tests.
+  * "black" Python.
+  * Add "eol-elts" for Debian ELTS.
+  * Tweak eol and eol-esm dates, by a couple of days, for Ubuntu 6.10, 9.10,
+    10.04, 12.04, 15.04, 15.10, 19.04 to match announced EOL dates.
+
+ -- Stefano Rivera <stefanor@debian.org>  Fri, 29 Jan 2021 13:41:20 -0700
+
+distro-info-data (0.45) unstable; urgency=medium
+
+  * Add Ubuntu 21.04, Hirsute Hippo.
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 29 Oct 2020 13:21:12 -0700
+
+distro-info-data (0.44) unstable; urgency=medium
+
+  * Add Ubuntu 20.10, Groovy Gorilla.
+  * Add a guessed EOL date for Debian Stretch.
+  * Bump Standards-Version to 4.5.0, no changes needed.
+
+ -- Stefano Rivera <stefanor@debian.org>  Fri, 24 Apr 2020 08:29:10 -0700
+
+distro-info-data (0.43) unstable; urgency=medium
+
+  * Add Ubuntu 20.04 LTS, Focal Fossa.
+  * Bump Standards-Version to 4.4.1, no changes needed.
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 17 Oct 2019 13:10:30 -0700
+
+distro-info-data (0.42) unstable; urgency=medium
+
+  * validate-csv-data:
+    - Switch to Python 3
+    - Switch from optparse to argparse
+    - Fix pylint issues
+  * Bump Standards-Version to 4.4.0
+  * Switch to debhelper 12
+
+ -- Benjamin Drung <bdrung@debian.org>  Tue, 23 Jul 2019 12:29:47 +0200
+
 distro-info-data (0.41+deb10u3) buster; urgency=medium
 
   * Update data to 0.45:
diff -Nru distro-info-data-0.41+deb10u3/debian/compat distro-info-data-0.47~deb10u1/debian/compat
--- distro-info-data-0.41+deb10u3/debian/compat	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/compat	1969-12-31 20:00:00.000000000 -0400
@@ -1 +0,0 @@
-9
diff -Nru distro-info-data-0.41+deb10u3/debian/control distro-info-data-0.47~deb10u1/debian/control
--- distro-info-data-0.41+deb10u3/debian/control	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/control	2021-04-22 11:46:22.000000000 -0400
@@ -3,8 +3,8 @@
 Priority: optional
 Maintainer: Benjamin Drung <bdrung@debian.org>
 Uploaders: Stefano Rivera <stefanor@debian.org>
-Build-Depends: debhelper (>= 9), python
-Standards-Version: 4.3.0
+Build-Depends: debhelper-compat (= 12), python3
+Standards-Version: 4.5.1
 Vcs-Git: https://salsa.debian.org/debian/distro-info-data.git
 Vcs-Browser: https://salsa.debian.org/debian/distro-info-data
 Rules-Requires-Root: no
@@ -13,8 +13,7 @@
 Architecture: all
 Multi-Arch: foreign
 Depends: ${misc:Depends}
-Breaks: distro-info (<< 0.3~)
-Replaces: distro-info (<< 0.3~)
+Breaks: distro-info (<< 1.0~)
 Description: information about the distributions' releases (data files)
  Information about all releases of Debian and Ubuntu. The distro-info script
  will give you the codename for e.g. the latest stable release of your
diff -Nru distro-info-data-0.41+deb10u3/debian/copyright distro-info-data-0.47~deb10u1/debian/copyright
--- distro-info-data-0.41+deb10u3/debian/copyright	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/copyright	2021-04-22 11:46:22.000000000 -0400
@@ -4,7 +4,7 @@
 
 Files: *
 Copyright: 2009-2018, Benjamin Drung <bdrung@debian.org>
-           2009-2018, Stefano Rivera <stefanor@debian.org>
+           2009-2021, Stefano Rivera <stefanor@debian.org>
 License: ISC
  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
diff -Nru distro-info-data-0.41+deb10u3/debian/README.Debian distro-info-data-0.47~deb10u1/debian/README.Debian
--- distro-info-data-0.41+deb10u3/debian/README.Debian	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/README.Debian	2021-04-22 11:46:22.000000000 -0400
@@ -23,3 +23,8 @@
 
 If there isn't an update available yet, you should be able to install the
 latest version from Debian/unstable.
+
+Or pull it from the Internet at:
+
+* https://debian.pages.debian.net/distro-info-data/debian.csv
+* https://debian.pages.debian.net/distro-info-data/ubuntu.csv
diff -Nru distro-info-data-0.41+deb10u3/debian/tests/control distro-info-data-0.47~deb10u1/debian/tests/control
--- distro-info-data-0.41+deb10u3/debian/tests/control	1969-12-31 20:00:00.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian/tests/control	2021-04-22 11:46:22.000000000 -0400
@@ -0,0 +1,2 @@
+Depends: @builddeps@
+Test-Command: make up-to-date
diff -Nru distro-info-data-0.41+deb10u3/debian.csv distro-info-data-0.47~deb10u1/debian.csv
--- distro-info-data-0.41+deb10u3/debian.csv	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/debian.csv	2021-04-22 11:46:22.000000000 -0400
@@ -1,4 +1,4 @@
-version,codename,series,created,release,eol
+version,codename,series,created,release,eol,eol-lts,eol-elts
 1.1,Buzz,buzz,1993-08-16,1996-06-17,1997-06-05
 1.2,Rex,rex,1996-06-17,1996-12-12,1998-06-05
 1.3,Bo,bo,1996-12-12,1997-06-05,1999-03-09
@@ -9,12 +9,13 @@
 3.1,Sarge,sarge,2002-07-19,2005-06-06,2008-03-30
 4.0,Etch,etch,2005-06-06,2007-04-08,2010-02-15
 5.0,Lenny,lenny,2007-04-08,2009-02-14,2012-02-06
-6.0,Squeeze,squeeze,2009-02-14,2011-02-06,2014-05-31
-7,Wheezy,wheezy,2011-02-06,2013-05-04,2016-04-26
-8,Jessie,jessie,2013-05-04,2015-04-25,2018-06-06
-9,Stretch,stretch,2015-04-25,2017-06-17,2020-07-06
-10,Buster,buster,2017-06-17,2019-07-06
+6.0,Squeeze,squeeze,2009-02-14,2011-02-06,2014-05-31,2016-02-29
+7,Wheezy,wheezy,2011-02-06,2013-05-04,2016-04-26,2018-05-31,2020-06-30
+8,Jessie,jessie,2013-05-04,2015-04-25,2018-06-17,2020-06-30,2022-06-30
+9,Stretch,stretch,2015-04-25,2017-06-17,2020-07-06,2022-06-30
+10,Buster,buster,2017-06-17,2019-07-06,2022-07-06,2024-06-30
 11,Bullseye,bullseye,2019-07-06
 12,Bookworm,bookworm,2021-08-01
+13,Trixie,trixie,2023-08-01
 ,Sid,sid,1993-08-16
 ,Experimental,experimental,1993-08-16
diff -Nru distro-info-data-0.41+deb10u3/.gitlab-ci.yml distro-info-data-0.47~deb10u1/.gitlab-ci.yml
--- distro-info-data-0.41+deb10u3/.gitlab-ci.yml	1969-12-31 20:00:00.000000000 -0400
+++ distro-info-data-0.47~deb10u1/.gitlab-ci.yml	2021-04-22 11:46:22.000000000 -0400
@@ -0,0 +1,10 @@
+---
+image: debian:stable
+
+pages:
+  script:
+    - mkdir public
+    - cp ubuntu.csv debian.csv public/
+  artifacts:
+    paths:
+      - public
diff -Nru distro-info-data-0.41+deb10u3/lib/tools.py distro-info-data-0.47~deb10u1/lib/tools.py
--- distro-info-data-0.41+deb10u3/lib/tools.py	1969-12-31 20:00:00.000000000 -0400
+++ distro-info-data-0.47~deb10u1/lib/tools.py	2021-04-22 11:46:22.000000000 -0400
@@ -0,0 +1,70 @@
+# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Common parsing and utility functions"""
+
+import argparse
+import datetime
+import os
+import sys
+
+
+def convert_date(string):
+    """Convert a date string in ISO 8601 into a datetime object."""
+    if not string:
+        date = None
+    else:
+        parts = [int(x) for x in string.split("-")]
+        if len(parts) == 3:
+            (year, month, day) = parts
+            date = datetime.date(year, month, day)
+        else:
+            raise ValueError("Date not in ISO 8601 format.")
+    return date
+
+
+def main(validation_function):
+    """Main function with command line parameter parsing."""
+    script_name = os.path.basename(sys.argv[0])
+    usage = "%s [-h] -d|-u csv-file" % (script_name)
+    parser = argparse.ArgumentParser(usage=usage)
+
+    parser.add_argument(
+        "-d",
+        "--debian",
+        dest="debian",
+        action="store_true",
+        default=False,
+        help="validate a Debian CSV file",
+    )
+    parser.add_argument(
+        "-u",
+        "--ubuntu",
+        dest="ubuntu",
+        action="store_true",
+        default=False,
+        help="validate an Ubuntu CSV file",
+    )
+    parser.add_argument("csv_file", metavar="csv-file", help="CSV file to validate")
+
+    args = parser.parse_args()
+    if len([x for x in [args.debian, args.ubuntu] if x]) != 1:
+        parser.error("You have to select exactly one of --debian, --ubuntu.")
+
+    if args.debian:
+        distro = "debian"
+    else:
+        distro = "ubuntu"
+
+    return int(not validation_function(args.csv_file, distro))
diff -Nru distro-info-data-0.41+deb10u3/Makefile distro-info-data-0.47~deb10u1/Makefile
--- distro-info-data-0.41+deb10u3/Makefile	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/Makefile	2021-04-22 11:46:22.000000000 -0400
@@ -1,4 +1,5 @@
 PREFIX ?= /usr
+PYTHON_SOURCES=lib up-to-date validate-csv-data
 
 build:
 
@@ -10,4 +11,14 @@
 	./validate-csv-data -d debian.csv
 	./validate-csv-data -u ubuntu.csv
 
-.PHONY: build install test
+up-to-date:
+	./up-to-date -d debian.csv
+	./up-to-date -u ubuntu.csv
+
+black:
+	black $(PYTHON_SOURCES)
+
+pylint:
+	pylint $(PYTHON_SOURCES)
+
+.PHONY: black build install pylint test up-to-date
diff -Nru distro-info-data-0.41+deb10u3/README.md distro-info-data-0.47~deb10u1/README.md
--- distro-info-data-0.41+deb10u3/README.md	1969-12-31 20:00:00.000000000 -0400
+++ distro-info-data-0.47~deb10u1/README.md	2021-04-22 11:46:22.000000000 -0400
@@ -0,0 +1,54 @@
+# distro-info-data
+
+The `distro-info` package provides centralized lists of code-names and
+release history for the supported distributions (Currently: Debian and
+Ubuntu).
+
+The `distro-info` data (in the `distro-info-data` package) can be
+updated once, and all the packages using it will have the latest
+data. This avoids having to hard-code current development release names
+(and other such volatile data) into packages.
+
+## Outdated Data Errors
+
+If you get an error that the package data is out of date, look for a newer
+distro-info-data package in your distribution's updates.
+
+On Debian, this is:
+deb http://ftp.debian.org/debian stable-updates main
+
+On Ubuntu, it is:
+deb http://archive.ubuntu.com/ubuntu $RELEASE-updates main
+where $RELEASE is the name of your release.
+
+If there isn't an update available yet, you should be able to install the
+latest version from Debian/unstable.
+
+## Online data
+
+Please don't scrape the git interface directly.
+
+This data is available publicly at:
+
+* https://debian.pages.debian.net/distro-info-data/debian.csv
+* https://debian.pages.debian.net/distro-info-data/ubuntu.csv
+
+## Data format
+
+The data is in CSV format. They are parsed by code specific to the
+distribution, so columns use and meaning vary.
+Each row is a release in the distribution's history.
+
+* `version`: Numeric (decimal) release version. Suffixed `LTS` for
+  Ubuntu LTS releases.
+* `codename`: Full human-readable name of the release.
+* `series`: The machine-readable series name (suite).
+* `created`: Date that the release started development. Normally the
+  release date for the previous release.
+* `release`: Official (stable) release date. Not defined when unknown
+   and for suites that will never release (e.g. Debian unstable &
+   experimental).
+* `eol`: The primary End of Life date for the release. Excluding Debian
+   LTS and Ubuntu ESM.
+* `eol-server`: End of Life for use on servers. (Specific to early
+   Ubuntu LTSs).
diff -Nru distro-info-data-0.41+deb10u3/ubuntu.csv distro-info-data-0.47~deb10u1/ubuntu.csv
--- distro-info-data-0.41+deb10u3/ubuntu.csv	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/ubuntu.csv	2021-04-22 11:46:22.000000000 -0400
@@ -1,35 +1,36 @@
-version,codename,series,created,release,eol,eol-server
+version,codename,series,created,release,eol,eol-server,eol-esm
 4.10,Warty Warthog,warty,2004-03-05,2004-10-20,2006-04-30
 5.04,Hoary Hedgehog,hoary,2004-10-20,2005-04-08,2006-10-31
 5.10,Breezy Badger,breezy,2005-04-08,2005-10-12,2007-04-13
 6.06 LTS,Dapper Drake,dapper,2005-10-12,2006-06-01,2009-07-14,2011-06-01
-6.10,Edgy Eft,edgy,2006-06-01,2006-10-26,2008-04-25
+6.10,Edgy Eft,edgy,2006-06-01,2006-10-26,2008-04-26
 7.04,Feisty Fawn,feisty,2006-10-26,2007-04-19,2008-10-19
 7.10,Gutsy Gibbon,gutsy,2007-04-19,2007-10-18,2009-04-18
 8.04 LTS,Hardy Heron,hardy,2007-10-18,2008-04-24,2011-05-12,2013-05-09
 8.10,Intrepid Ibex,intrepid,2008-04-24,2008-10-30,2010-04-30
 9.04,Jaunty Jackalope,jaunty,2008-10-30,2009-04-23,2010-10-23
-9.10,Karmic Koala,karmic,2009-04-23,2009-10-29,2011-04-29
-10.04 LTS,Lucid Lynx,lucid,2009-10-29,2010-04-29,2013-05-09,2015-04-29
+9.10,Karmic Koala,karmic,2009-04-23,2009-10-29,2011-04-30
+10.04 LTS,Lucid Lynx,lucid,2009-10-29,2010-04-29,2013-05-09,2015-04-30
 10.10,Maverick Meerkat,maverick,2010-04-29,2010-10-10,2012-04-10
 11.04,Natty Narwhal,natty,2010-10-10,2011-04-28,2012-10-28
 11.10,Oneiric Ocelot,oneiric,2011-04-28,2011-10-13,2013-05-09
-12.04 LTS,Precise Pangolin,precise,2011-10-13,2012-04-26,2017-04-26
+12.04 LTS,Precise Pangolin,precise,2011-10-13,2012-04-26,2017-04-28,2017-04-28,2019-04-28
 12.10,Quantal Quetzal,quantal,2012-04-26,2012-10-18,2014-05-16
 13.04,Raring Ringtail,raring,2012-10-18,2013-04-25,2014-01-27
 13.10,Saucy Salamander,saucy,2013-04-25,2013-10-17,2014-07-17
-14.04 LTS,Trusty Tahr,trusty,2013-10-17,2014-04-17,2019-04-25
+14.04 LTS,Trusty Tahr,trusty,2013-10-17,2014-04-17,2019-04-25,2019-04-25,2022-04-25
 14.10,Utopic Unicorn,utopic,2014-04-17,2014-10-23,2015-07-23
-15.04,Vivid Vervet,vivid,2014-10-23,2015-04-23,2016-01-23
-15.10,Wily Werewolf,wily,2015-04-23,2015-10-22,2016-07-22
-16.04 LTS,Xenial Xerus,xenial,2015-10-22,2016-04-21,2021-04-21
+15.04,Vivid Vervet,vivid,2014-10-23,2015-04-23,2016-02-04
+15.10,Wily Werewolf,wily,2015-04-23,2015-10-22,2016-07-28
+16.04 LTS,Xenial Xerus,xenial,2015-10-22,2016-04-21,2021-04-21,2021-04-21,2024-04-21
 16.10,Yakkety Yak,yakkety,2016-04-21,2016-10-13,2017-07-20
 17.04,Zesty Zapus,zesty,2016-10-13,2017-04-13,2018-01-13
 17.10,Artful Aardvark,artful,2017-04-13,2017-10-19,2018-07-19
-18.04 LTS,Bionic Beaver,bionic,2017-10-19,2018-04-26,2023-04-26
+18.04 LTS,Bionic Beaver,bionic,2017-10-19,2018-04-26,2023-04-26,2023-04-26,2028-04-26
 18.10,Cosmic Cuttlefish,cosmic,2018-04-26,2018-10-18,2019-07-18
-19.04,Disco Dingo,disco,2018-10-18,2019-04-18,2020-01-18
+19.04,Disco Dingo,disco,2018-10-18,2019-04-18,2020-01-23
 19.10,Eoan Ermine,eoan,2019-04-18,2019-10-17,2020-07-17
-20.04 LTS,Focal Fossa,focal,2019-10-17,2020-04-23,2025-04-23
+20.04 LTS,Focal Fossa,focal,2019-10-17,2020-04-23,2025-04-23,2025-04-23,2030-04-23
 20.10,Groovy Gorilla,groovy,2020-04-23,2020-10-22,2021-07-22
 21.04,Hirsute Hippo,hirsute,2020-10-22,2021-04-22,2022-01-22
+21.10,Impish Indri,impish,2021-04-22,2021-10-14,2022-07-14
diff -Nru distro-info-data-0.41+deb10u3/up-to-date distro-info-data-0.47~deb10u1/up-to-date
--- distro-info-data-0.41+deb10u3/up-to-date	1969-12-31 20:00:00.000000000 -0400
+++ distro-info-data-0.47~deb10u1/up-to-date	2021-04-22 11:46:22.000000000 -0400
@@ -0,0 +1,81 @@
+#!/usr/bin/python3
+
+# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org>
+#               2018, Stefano Rivera <stefanor@debian.org>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Validates that the data is up-to-date."""
+
+import csv
+import datetime
+import sys
+
+from lib.tools import convert_date, main
+
+ROLLING_FOREVER = {
+    "debian": ("sid", "experimental"),
+    "ubuntu": (),
+}
+
+
+def validate(filename, distro):
+    """Validates that the given CSV file is current.
+
+    Returns True if the given CSV file is current and otherwise False.
+    """
+    content = open(filename).readlines()
+    # Remove comments
+    for no, line in enumerate(content):
+        if line.startswith("#"):
+            content[no] = "\n"
+    csvreader = csv.DictReader(content)
+    today = datetime.datetime.utcnow().date()
+
+    last_release = None
+    dev_releases = []
+    for row in csvreader:
+        created = False
+        released = False
+        if row["series"] in ROLLING_FOREVER[distro]:
+            continue
+        if row["created"]:
+            created = today >= convert_date(row["created"])
+        if row["release"]:
+            released = today >= convert_date(row["release"])
+        if created:
+            if not released:
+                dev_releases.append(row["codename"])
+            else:
+                last_release = row["codename"]
+
+    if len(dev_releases) == 1:
+        return True
+
+    if len(dev_releases) > 1:
+        print(
+            "Multiple current development %s releases: %s" % (distro, dev_releases),
+            file=sys.stderr,
+        )
+    else:
+        print(
+            "No current development %s release. %s is now released."
+            % (distro, last_release),
+            file=sys.stderr,
+        )
+
+    return False
+
+
+if __name__ == "__main__":
+    sys.exit(main(validate))
diff -Nru distro-info-data-0.41+deb10u3/validate-csv-data distro-info-data-0.47~deb10u1/validate-csv-data
--- distro-info-data-0.41+deb10u3/validate-csv-data	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.47~deb10u1/validate-csv-data	2021-04-22 11:46:22.000000000 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # Copyright (C) 2012, Benjamin Drung <bdrung@debian.org>
 #
@@ -14,46 +14,58 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+# pylint: disable=invalid-name
+# pylint: enable=invalid-name
+
 """Validates a given Debian or Ubuntu distro-info CSV file."""
 
 import csv
-import datetime
-import optparse
-import os
 import sys
 
+from lib.tools import convert_date, main
+
+
 _COLUMNS = {
-    "debian": ("version", "codename", "series", "created", "release", "eol"),
-    "ubuntu": ("version", "codename", "series", "created", "release", "eol",
-               "eol-server"),
+    "debian": (
+        "version",
+        "codename",
+        "series",
+        "created",
+        "release",
+        "eol",
+        "eol-lts",
+        "eol-elts",
+    ),
+    "ubuntu": (
+        "version",
+        "codename",
+        "series",
+        "created",
+        "release",
+        "eol",
+        "eol-server",
+        "eol-esm",
+    ),
 }
-_DATES = ("created", "release", "eol", "eol-server")
+_DATES = ("created", "release", "eol", "eol-server", "eol-esm", "eol-lts", "eol-elts")
 _EARLIER_DATES = (
     ("created", "release"),
     ("release", "eol"),
     ("eol", "eol-server"),
+    ("eol", "eol-esm"),
+    ("eol", "eol-lts"),
+    ("eol-lts", "eol-elts"),
 )
 _STRINGS = {
     "debian": ("codename", "series"),
     "ubuntu": ("version", "codename", "series"),
 }
 
-def convert_date(string):
-    """Convert a date string in ISO 8601 into a datetime object."""
-    if not string:
-        date = None
-    else:
-        parts = [int(x) for x in string.split("-")]
-        if len(parts) == 3:
-            (year, month, day) = parts
-            date = datetime.date(year, month, day)
-        else:
-            raise ValueError("Date not in ISO 8601 format.")
-    return date
 
 def error(filename, line, message, *args):
     """Prints an error message"""
-    print >> sys.stderr, "%s:%i: %s." % (filename, line, message % args)
+    print("%s:%i: %s." % (filename, line, message % args), file=sys.stderr)
+
 
 def validate(filename, distro):
     """Validates a given CSV file.
@@ -63,9 +75,9 @@
     failures = 0
     content = open(filename).readlines()
     # Remove comments
-    for line in xrange(len(content)):
-        if content[line].startswith("#"):
-            content[line] = "\n"
+    for counter, line in enumerate(content):
+        if line.startswith("#"):
+            content[counter] = "\n"
     csvreader = csv.DictReader(content)
     for row in csvreader:
         # Check for missing columns
@@ -93,8 +105,7 @@
                     row[column] = convert_date(row[column])
                 except ValueError:
                     msg = "Invalid date `%s' in column `%s'"
-                    error(filename, csvreader.line_num, msg, row[column],
-                           column)
+                    error(filename, csvreader.line_num, msg, row[column], column)
                     failures += 1
                     row[column] = None
         # Check required date columns
@@ -108,51 +119,32 @@
             if date2 in row and row[date2]:
                 if date1 in row and row[date1]:
                     # date1 needs to be earlier than date2
-                    if row[date1] >= row[date2]:
-                        msg = ("Date %s of column `%s' needs to be later "
-                               "than %s of column `%s'")
-                        error(filename, csvreader.line_num, msg,
-                              row[date2].isoformat(), date2,
-                              row[date1].isoformat(), date1)
+                    if row[date1] > row[date2]:
+                        msg = (
+                            "Date %s of column `%s' needs to be >= "
+                            "than %s of column `%s'"
+                        )
+                        error(
+                            filename,
+                            csvreader.line_num,
+                            msg,
+                            row[date2].isoformat(),
+                            date2,
+                            row[date1].isoformat(),
+                            date1,
+                        )
                         failures += 1
                 else:
                     # date1 needs to be specified if date1 is specified
-                    msg = ("A date needs to be specified in column `%s' due "
-                           "to the given date in column `%s'")
+                    msg = (
+                        "A date needs to be specified in column `%s' due "
+                        "to the given date in column `%s'"
+                    )
                     error(filename, csvreader.line_num, msg, date1, date2)
                     failures += 1
 
     return failures == 0
 
-def main():
-    """Main function with command line parameter parsing."""
-    script_name = os.path.basename(sys.argv[0])
-    usage = "%s -d|-u csv-file" % (script_name)
-    parser = optparse.OptionParser(usage=usage)
-
-    parser.add_option("-d", "--debian", dest="debian", action="store_true",
-                      default=False, help="validate a Debian CSV file")
-    parser.add_option("-u", "--ubuntu", dest="ubuntu", action="store_true",
-                      default=False, help="validate an Ubuntu CSV file")
-
-    (options, args) = parser.parse_args()
-
-    if len(args) == 0:
-        parser.error("No CSV file specified.")
-    elif len(args) > 1:
-        parser.error("Multiple CSV files specified: %s" % (", ".join(args)))
-
-    if len([x for x in [options.debian, options.ubuntu] if x]) != 1:
-        parser.error("You have to select exactly one of --debian, --ubuntu.")
-    if options.debian:
-        distro = "debian"
-    else:
-        distro = "ubuntu"
-
-    if validate(args[0], distro):
-        return 0
-    else:
-        return 1
 
 if __name__ == "__main__":
-    sys.exit(main())
+    sys.exit(main(validate))
diff -Nru distro-info-data-0.41+deb10u3/debian/changelog distro-info-data-0.41+deb10u4/debian/changelog
--- distro-info-data-0.41+deb10u3/debian/changelog	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.41+deb10u4/debian/changelog	2021-04-22 11:07:13.000000000 -0400
@@ -1,3 +1,13 @@
+distro-info-data (0.41+deb10u4) buster; urgency=medium
+
+  * Update data to 0.46, without new columns:
+    - Add estimated date for Buster EOL.
+    - Correct the EOL date for Debian Jessie.
+    - Add Debian 13 "Trixie", with a rough date.
+    - Add Ubuntu 21.04, Impish Indri.
+
+ -- Stefano Rivera <stefanor@debian.org>  Thu, 22 Apr 2021 11:07:13 -0400
+
 distro-info-data (0.41+deb10u3) buster; urgency=medium
 
   * Update data to 0.45:
diff -Nru distro-info-data-0.41+deb10u3/debian.csv distro-info-data-0.41+deb10u4/debian.csv
--- distro-info-data-0.41+deb10u3/debian.csv	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.41+deb10u4/debian.csv	2021-04-22 11:07:13.000000000 -0400
@@ -11,10 +11,11 @@
 5.0,Lenny,lenny,2007-04-08,2009-02-14,2012-02-06
 6.0,Squeeze,squeeze,2009-02-14,2011-02-06,2014-05-31
 7,Wheezy,wheezy,2011-02-06,2013-05-04,2016-04-26
-8,Jessie,jessie,2013-05-04,2015-04-25,2018-06-06
+8,Jessie,jessie,2013-05-04,2015-04-25,2018-06-17
 9,Stretch,stretch,2015-04-25,2017-06-17,2020-07-06
-10,Buster,buster,2017-06-17,2019-07-06
+10,Buster,buster,2017-06-17,2019-07-06,2022-07-06
 11,Bullseye,bullseye,2019-07-06
 12,Bookworm,bookworm,2021-08-01
+13,Trixie,trixie,2023-08-01
 ,Sid,sid,1993-08-16
 ,Experimental,experimental,1993-08-16
diff -Nru distro-info-data-0.41+deb10u3/ubuntu.csv distro-info-data-0.41+deb10u4/ubuntu.csv
--- distro-info-data-0.41+deb10u3/ubuntu.csv	2020-11-02 16:44:14.000000000 -0400
+++ distro-info-data-0.41+deb10u4/ubuntu.csv	2021-04-22 11:07:13.000000000 -0400
@@ -33,3 +33,4 @@
 20.04 LTS,Focal Fossa,focal,2019-10-17,2020-04-23,2025-04-23
 20.10,Groovy Gorilla,groovy,2020-04-23,2020-10-22,2021-07-22
 21.04,Hirsute Hippo,hirsute,2020-10-22,2021-04-22,2022-01-22
+21.10,Impish Indri,impish,2021-04-22,2021-10-14,2022-07-14

--- End Message ---
--- Begin Message ---
Package: release.debian.org
Version: 10.11

Hi,

The updates relating to these bugs were included in this morning's
10.11 point release for buster.

Regards,

Adam

--- End Message ---

Reply to: