~xubuntu-dev/ubuntu-cdimage/xubuntu-base

« back to all changes in this revision

Viewing changes to lib/cdimage/tree.py

  • Committer: Sean Davis
  • Date: 2018-03-28 10:32:07 UTC
  • mfrom: (1559.1.156 ubuntu-cdimage)
  • Revision ID: smd.seandavis@gmail.com-20180328103207-o6s9d6h0hxxh8eqc
Merge lp:ubuntu-cdimage rev 1715

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
from optparse import OptionParser
25
25
import os
26
26
import re
 
27
try:
 
28
    from shlex import quote as shell_quote
 
29
except ImportError:
 
30
    from pipes import quote as shell_quote
27
31
import shutil
28
32
import socket
29
33
import stat
65
69
    "kubuntu-netbook",
66
70
    "kubuntu-plasma5",
67
71
    "lubuntu",
 
72
    "lubuntu-next",
68
73
    "mythbuntu",
69
74
    "ubuntu",
70
75
    "ubuntu-desktop-next",
71
76
    "ubuntu-gnome",
 
77
    "ubuntu-budgie",
72
78
    "ubuntu-mate",
73
79
    "ubuntu-headless",
74
80
    "ubuntu-netbook",
189
195
    def manifest_file_allowed(self, path):
190
196
        """Return true if a given file is allowed in the manifest."""
191
197
        if (path.endswith(".iso") or path.endswith(".img") or
192
 
                path.endswith(".img.gz") or path.endswith(".tar.gz") or
193
 
                path.endswith(".tar.xz")):
 
198
                path.endswith(".img.gz") or path.endswith(".img.xz") or
 
199
                path.endswith(".tar.gz") or path.endswith(".tar.xz")):
194
200
            try:
195
201
                if stat.S_ISREG(os.stat(path).st_mode):
196
202
                    return True
379
385
                return "preinstalled-headless"
380
386
            elif self.project == "ubuntu-server":
381
387
                return "preinstalled-server"
382
 
            elif self.project == "ubuntu-touch":
 
388
            elif self.project in ("ubuntu-touch", "ubuntu-touch-custom"):
383
389
                return "preinstalled-touch"
384
 
            elif self.project == "ubuntu-pd":
385
 
                return "preinstalled-pd"
386
390
            elif self.project == "ubuntu-core":
387
391
                return "preinstalled-core"
388
392
            elif self.project == "ubuntu-desktop-next":
402
406
            elif self.project in ("ubuntu-netbook", "kubuntu-netbook"):
403
407
                return "netbook"
404
408
            elif self.project == "ubuntu-server":
405
 
                return "live"
 
409
                return "live-server"
 
410
            elif self.project == "ubuntu-core":
 
411
                return "live-core"
406
412
            elif self.project == "xubuntu-base":
407
413
                return "base"
408
414
            else:
427
433
                    return "server"
428
434
            elif self.project == "jeos":
429
435
                return "jeos"
430
 
            elif self.project == "ubuntu-core":
431
 
                return "core"
 
436
            elif self.project == "ubuntu-base":
 
437
                return "base"
432
438
            else:
433
439
                if self.config["DIST"] <= "breezy":
434
440
                    return "install"
441
447
        if publish_type.startswith("preinstalled-"):
442
448
            return "daily-preinstalled"
443
449
        elif publish_type in (
444
 
                "desktop", "live", "mid", "moblin-remix", "netbook"):
 
450
                "desktop", "live", "mid", "moblin-remix", "netbook",
 
451
                "live-core", "live-server"):
445
452
            return "daily-live"
446
453
        elif publish_type == "base" and self.project == "xubuntu-base":
447
454
            return "daily-live"
448
455
        elif publish_type == "dvd":
449
456
            return "dvd"
450
457
        elif publish_type in (
451
 
                "addon", "alternate", "core", "install", "jeos", "server"):
 
458
                "addon", "alternate", "base", "install", "jeos", "server"):
452
459
            return "daily"
453
460
        else:
454
461
            return None
476
483
            return ["http://releases.ubuntu.com/include/kubuntu.css"]
477
484
        if self.project == "kubuntu-plasma5":
478
485
            return ["http://releases.ubuntu.com/include/kubuntu-plasma5.css"]
 
486
        if self.project in ("lubuntu", "lubuntu-next"):
 
487
            return ["http://cdimage.ubuntu.com/include/lubuntu/style.css"]
479
488
        else:
480
489
            return ["http://releases.ubuntu.com/include/style.css"]
481
490
 
495
504
 
496
505
        if publish_type == "live":
497
506
            return "live %s" % cd
 
507
        elif publish_type == "live-core":
 
508
            return "Ubuntu Core %s" % cd
498
509
        elif publish_type == "desktop":
499
510
            return "desktop %s" % cd
500
511
        elif publish_type == "base":
503
514
            return "install %s" % cd
504
515
        elif publish_type == "alternate":
505
516
            return "alternate install %s" % cd
506
 
        elif publish_type == "server":
 
517
        elif publish_type == "server" or publish_type == "live-server":
507
518
            if self.project == "edubuntu":
508
519
                return "classroom server %s" % cd
509
520
            else:
669
680
                "This live %s is optimized for netbooks with screens up to "
670
681
                "10\"." % cd)
671
682
            sentences.append(desktop_req)
672
 
        elif publish_type == "server":
 
683
        elif publish_type == "server" or publish_type == "live-server":
673
684
            if self.project == "edubuntu":
674
685
                sentences.append(
675
686
                    "The classroom server %s allows you to install %s "
851
862
            if arch == "amd64+mac":
852
863
                sentences.append(
853
864
                    "This image is adjusted to work properly on Mac systems.")
 
865
            else:
 
866
                sentences.append("Choose this if you are at all unsure.")
854
867
        elif arch == "arm64":
855
868
            sentences.append("For 64-bit ARMv8 processors and above.")
856
869
        elif arch == "armel":
899
912
                "processors and almost all computers that run Microsoft "
900
913
                "Windows, as well as newer Apple Macintosh systems based on "
901
914
                "Intel processors.")
902
 
            sentences.append("Choose this if you are at all unsure.")
903
915
        elif arch == "ia64":
904
916
            sentences.append("For Intel Itanium and Itanium 2 computers.")
905
917
        elif arch == "lpia":
958
970
            sentences.append(
959
971
                "However, you may still test it using a larger USB drive or a "
960
972
                "virtual machine.")
 
973
        elif (self.project in ("ubuntu-gnome",
 
974
                               "kubuntu",
 
975
                               "ubuntu-mate",
 
976
                               "ubuntu-budgie") and series >= "xenial"):
 
977
            sentences.append(
 
978
                "Warning: This image is oversized (which is a bug) and will "
 
979
                "not fit onto a 2GB USB stick.")
 
980
            sentences.append(
 
981
                "However, you may still test it using a DVD, a larger USB "
 
982
                "drive, or a virtual machine.")
961
983
        elif (self.project in usb_projects or
962
984
                (self.project == "xubuntu" and series >= "raring") or
963
 
                (self.project == "ubuntu-gnome" and series >= "saucy")):
 
985
                (self.project == "ubuntu-gnome" and series >= "saucy" and
 
986
                 series << "xenial")):
964
987
            sentences.append(
965
988
                "Warning: This image is oversized (which is a bug) and will "
966
989
                "not fit onto a 1GB USB stick.")
1003
1026
            return "contents of desktop part of live filesystem"
1004
1027
        elif extension == "manifest-remove":
1005
1028
            return "packages to remove from live filesystem on installation"
 
1029
        elif extension == "manifest-minimal-remove":
 
1030
            return "packages to remove from live filesystem on " + \
 
1031
                   " installation when performing a minimal install"
1006
1032
        elif extension == "template":
1007
1033
            return "%s template" % Link("http://atterer.org/jigdo", "jigdo")
1008
1034
        elif extension.endswith(".zsync"):
1086
1112
        images = []
1087
1113
        prefix_type = "%s-%s" % (prefix, publish_type)
1088
1114
        for entry in os.listdir(directory):
1089
 
            if entry == ("%s.img" % prefix_type):
 
1115
            if entry in ("%s.img" % prefix_type, "%s.img.xz" % prefix_type):
1090
1116
                images.append(entry)
1091
1117
            elif publish_type == "wubi" and entry.endswith(".tar.xz"):
1092
1118
                # Wubi images are just "ARCH.tar.xz", with no prefix.
1122
1148
        all_publish_types = (
1123
1149
            "live", "desktop",
1124
1150
            "base",
 
1151
            "live-server",
1125
1152
            "server", "install", "alternate",
1126
1153
            "serveraddon", "addon",
1127
1154
            "dvd",
1132
1159
            "preinstalled-mobile", "preinstalled-active",
1133
1160
            "preinstalled-headless", "preinstalled-server",
1134
1161
            "preinstalled-touch", "preinstalled-core", "wubi",
1135
 
            "preinstalled-desktop-next",
 
1162
            "preinstalled-desktop-next", "live-core",
1136
1163
        )
1137
1164
 
1138
1165
        all_arches = (
1139
1166
            "amd64", "amd64+mac",
1140
1167
            "i386",
1141
 
            "armel+dove", "armel+imx51", "armel+omap", "armel+omap4",
 
1168
            "armel", "armel+dove", "armel+imx51", "armel+omap", "armel+omap4",
1142
1169
            "armel+ac100", "armel+mx5",
1143
 
            "armhf+omap", "armhf+omap4", "armhf+ac100", "armhf+mx5",
1144
 
            "armhf+nexus7", "armhf", "armel", "arm64",
 
1170
            "armhf", "armhf+omap", "armhf+omap4", "armhf+ac100", "armhf+mx5",
 
1171
            "armhf+nexus7", "armhf+raspi2",
 
1172
            "arm64",
1145
1173
            "powerpc",
1146
1174
            "powerpc+ps3",
1147
1175
            "ppc64el",
1183
1211
                    "<link "
1184
1212
                    "href='http://fonts.googleapis.com/css?family=Ubuntu' "
1185
1213
                    "rel='stylesheet' type='text/css'>", file=header)
1186
 
                print(
1187
 
                    "<link rel=\"icon\" type=\"image/png\" "
1188
 
                    "href=\"http://www.kubuntu.org/themes/kubuntu10.04/"
1189
 
                    "favicon.ico\">", file=header)
1190
1214
            if self.project == "kubuntu-plasma5":
1191
1215
                print(
1192
1216
                    "<link "
1197
1221
                    "<link rel=\"icon\" type=\"image/png\" "
1198
1222
                    "href=\"http://www.kubuntu.org/themes/kubuntu10.04/"
1199
1223
                    "favicon.ico\">", file=header)
 
1224
            if self.project in ("lubuntu", "lubuntu-next"):
 
1225
                print(
 
1226
                    "<link rel=\"icon\" type=\"image/png\" "
 
1227
                    "href=\"http://cdimage.ubuntu.com/include/lubuntu/"
 
1228
                    "favicon.png\" />", file=header)
 
1229
                header_href = 'https://lubuntu.me/'
 
1230
            else:
 
1231
                header_href = 'http://www.ubuntu.com/'
 
1232
 
1200
1233
            print(dedent("""\
1201
1234
                </head>
1202
1235
                <body><div id="pageWrapper">
1203
1236
 
1204
 
                <div id="header"><a href="http://www.ubuntu.com/"></a></div>
 
1237
                <div id="header"><a href="%s"></a></div>
1205
1238
 
1206
1239
                <h1>%s</h1>
1207
1240
 
1208
1241
                <div id="main">
1209
 
                """) % heading, file=header)
 
1242
                """) % (header_href, heading), file=header)
1210
1243
 
1211
1244
            mirrors_url = "http://www.ubuntu.com/getubuntu/downloadmirrors"
1212
1245
            reldir = os.path.realpath(directory)
1274
1307
                        arches = all_arches
1275
1308
 
1276
1309
                    for image_format in (
1277
 
                        "iso", "img", "img.gz", "img.tar.gz", "tar.gz",
1278
 
                        "tar.xz", "custom.tar.gz",
 
1310
                        "iso", "img", "img.gz", "img.xz", "img.tar.gz",
 
1311
                        "tar.gz", "tar.xz", "custom.tar.gz",
1279
1312
                    ):
1280
1313
                        paths = []
1281
 
                        if image_format == "img":
 
1314
                        if image_format == "img" or image_format == "img.xz":
1282
1315
                            path = os.path.join(
1283
1316
                                directory,
1284
1317
                                "%s-%s.%s" % (
1389
1422
                            else:
1390
1423
                                htaccess_extensions = (
1391
1424
                                    "img.gz.torrent", "img.gz.zsync", "img.gz",
1392
 
                                    "img.tar.gz", "img.torrent", "img.zsync",
1393
 
                                    "img", "iso.torrent", "iso.zsync", "iso",
1394
 
                                    "jigdo", "list", "manifest",
1395
 
                                    "manifest-desktop", "manifest-remove",
 
1425
                                    "img.xz", "img.tar.gz", "img.torrent",
 
1426
                                    "img.zsync", "img", "iso.torrent",
 
1427
                                    "iso.zsync", "iso", "jigdo", "list",
 
1428
                                    "manifest", "manifest-desktop",
 
1429
                                    "manifest-remove",
 
1430
                                    "manifest-minimal-remove",
1396
1431
                                    "template", "tar.gz", "tar.gz.zsync",
1397
1432
                                    "bootimg", "tar.xz", "custom.tar.gz",
1398
1433
                                )
1541
1576
            if got_iso or got_img:
1542
1577
                print(file=header)
1543
1578
 
1544
 
            if self.config.project in ("ubuntu-touch", "ubuntu-pd"):
 
1579
            if self.config.project in ("ubuntu-touch", "ubuntu-touch-custom"):
1545
1580
                for tag in self.ubuntu_touch_legal_notice():
1546
1581
                    print(tag, file=header)
1547
1582
                print(file=header)
1575
1610
            for icon, patterns in (
1576
1611
                ("folder.png", "^^DIRECTORY^^"),
1577
1612
                ("iso.png", ".iso"),
1578
 
                ("img.png", ".img .tar.gz .tar.xz"),
 
1613
                ("img.png", ".img .img.xz .tar.gz .tar.xz"),
1579
1614
                ("jigdo.png", ".jigdo .template"),
1580
1615
                ("list.png", (
1581
1616
                    ".list .manifest .html .zsync "
1591
1626
            for extension in (
1592
1627
                "img.gz.torrent", "img.gz", "img.torrent", "img",
1593
1628
                "iso.torrent", "iso", "jigdo", "list", "manifest",
1594
 
                "manifest-desktop", "manifest-remove", "template",
 
1629
                "manifest-desktop", "manifest-remove",
 
1630
                "manifest-minimal-remove", "template",
1595
1631
            ):
1596
1632
                mimetype = self.mimetypestr(extension)
1597
1633
                if (mimetype and
1600
1636
                        "AddType %s .%s" % (mimetype, extension),
1601
1637
                        file=htaccess)
1602
1638
 
1603
 
    def make_metalink(self, directory, version):
 
1639
    def make_metalink(self, directory, version, dry_run=False):
1604
1640
        """Create and publish metalink files."""
1605
1641
        osextras.unlink_force(os.path.join(directory, "MD5SUMS-metalink"))
1606
1642
        osextras.unlink_force(os.path.join(directory, "MD5SUMS-metalink.gpg"))
1612
1648
            metalink_builder, self.tree.directory, version, reldir,
1613
1649
            self.tree.site_name,
1614
1650
        ]
1615
 
        try:
1616
 
            if subprocess.call(command) == 0:
1617
 
                metalink_checksum_directory(self.config, directory)
1618
 
                return
1619
 
        except OSError as e:
1620
 
            if e.errno != errno.ENOENT:
1621
 
                raise
 
1651
        if dry_run:
 
1652
            logger.info(" ".join(shell_quote(arg) for arg in command))
 
1653
        else:
 
1654
            try:
 
1655
                if subprocess.call(command) == 0:
 
1656
                    metalink_checksum_directory(self.config, directory)
 
1657
                    return
 
1658
            except OSError as e:
 
1659
                if e.errno != errno.ENOENT:
 
1660
                    raise
1622
1661
 
1623
 
        # Metalink creation failed.  Remove any stale .metalink files.
1624
 
        for name in os.listdir(directory):
1625
 
            if name.endswith(".metalink"):
1626
 
                osextras.unlink_force(os.path.join(directory, name))
 
1662
        if not dry_run:
 
1663
            # Metalink creation failed.  Remove any stale .metalink files.
 
1664
            for name in os.listdir(directory):
 
1665
                if name.endswith(".metalink"):
 
1666
                    osextras.unlink_force(os.path.join(directory, name))
1627
1667
 
1628
1668
 
1629
1669
class DailyTree(Tree):
1694
1734
 
1695
1735
    @property
1696
1736
    def image_type_dir(self):
 
1737
        if (self.config.project == "ubuntu-core" and
 
1738
                self.image_type == 'daily-live'):
 
1739
            channel = self.config.get("CHANNEL", "edge")
 
1740
            return os.path.join(self.config.core_series, channel)
1697
1741
        image_type_dir = self.image_type.replace("_", "/")
1698
1742
        if (self.config.distribution != "ubuntu" or
1699
1743
                not self.config["DIST"].is_latest):
1719
1763
        elif self.project in (
1720
1764
                "kubuntu", "kubuntu-active", "kubuntu-plasma5",
1721
1765
                ):
 
1766
            if self.config["DIST"] >= "xenial":
 
1767
                # Per https://lists.ubuntu.com/archives/
 
1768
                # ... ubuntu-release/2016-May/003749.html
 
1769
                return 2 * 1000 * 1000 * 1000
1722
1770
            # 1.2GB arbitrary limit, set jriddell 2014-08-21
1723
1771
            return (1024 * 1024 * 1024) + (1024 * 1024 * 200)
1724
 
        elif (self.project == "ubuntu" and self.publish_type != "dvd" and
 
1772
        elif (self.project in ("ubuntu", "ubuntukylin") and
 
1773
              self.publish_type != "dvd" and
1725
1774
              self.config["DIST"] >= "quantal"):
1726
1775
            # Ubuntu quantal onward has a succession of arbitrary limits.
1727
1776
            if self.config["DIST"] == "quantal":
1733
1782
                    return 835000000
1734
1783
            elif self.config["DIST"] == "saucy":
1735
1784
                return 950000000
 
1785
            elif self.config["DIST"] in ("trusty", "utopic", "vivid", "wily"):
 
1786
                return 1.2 * 1000 * 1000 * 1000
1736
1787
            else:
1737
 
                return 1024 * 1024 * 1024
 
1788
                # next relevant size limit is a 2GB (not 2GiB) USB stick
 
1789
                return 2 * 1000 * 1000 * 1000
1738
1790
        elif self.project == "ubuntu-gnome" and self.config["DIST"] >= "saucy":
 
1791
            # Per https://lists.ubuntu.com/archives/
 
1792
            # ... ubuntu-release/2016-May/003740.html
 
1793
            if self.config["DIST"] >= "xenial":
 
1794
                return 2 * 1000 * 1000 * 1000
1739
1795
            # Requested by darkxst in #ubuntu-release on 2013/06/28 03:29 UTC
1740
1796
            return 1024 * 1024 * 1024
 
1797
        elif (self.project in ("ubuntu-budgie", "mythbuntu") and
 
1798
              self.config["DIST"] >= "xenial"):
 
1799
            # mythbuntu project has disbanded per
 
1800
            # https://bugs.launchpad.net/bugs/1639445, xenial images were
 
1801
            # oversized; executive decision by vorlon to raise the limit
 
1802
            # and suppress the warnings
 
1803
            return 2 * 1000 * 1000 * 1000
 
1804
        elif self.project == "xubuntu" and self.config["DIST"] >= "xenial":
 
1805
            # http://irclogs.ubuntu.com/2016/03/09/
 
1806
            #   %23ubuntu-release.html#t12:11
 
1807
            return 1460000000
1741
1808
        elif self.project == "xubuntu" and self.config["DIST"] >= "raring":
1742
1809
            # http://irclogs.ubuntu.com/2013/02/11/%23xubuntu-devel.html#t21:48
1743
1810
            return 1024 * 1024 * 1024
1744
1811
        elif self.project == "ubuntu-mate":
1745
 
            return 1024 * 1024 * 1024
 
1812
            if self.config["DIST"] >= "xenial":
 
1813
                # https://lists.ubuntu.com/archives/ubuntu-release/2016-May/003744.html
 
1814
                return 2 * 1000 * 1000 * 1000
 
1815
            return 1024 * 1024 * 1024
 
1816
        elif (self.project in ("lubuntu", "lubuntu-next") and
 
1817
              self.config["DIST"] >= "artful"):
 
1818
            # https://irclogs.ubuntu.com/2017/07/27/%23ubuntu-release.html#t23:05
 
1819
            return int(1.5 * 1000 * 1000 * 1000)
 
1820
        elif self.project == "lubuntu" and self.config["DIST"] >= "trusty":
 
1821
            # provisional;
 
1822
            # https://irclogs.ubuntu.com/2016/10/01/%23ubuntu-release.html#t19:06
 
1823
            return 1024 * 1024 * 1024
 
1824
        elif self.project == "ubuntu-server":
 
1825
            if self.config["DIST"] == "xenial":
 
1826
                return 1024 * 1024 * 1024
 
1827
            elif self.config["DIST"] >= "zesty" and arch == "ppc64el":
 
1828
                return 1024 * 1024 * 1024
 
1829
            else:
 
1830
                return 736665600
1746
1831
        else:
1747
1832
            if self.publish_type == "dvd":
1748
1833
                # http://en.wikipedia.org/wiki/DVD_plus_RW
1799
1884
            return "iso"
1800
1885
        elif output.startswith("x86 boot sector"):
1801
1886
            return "img"
1802
 
        elif output.startswith("gzip compressed data"):
 
1887
        elif output.startswith(("gzip compressed data", "XZ compressed data")):
 
1888
            if output.startswith("gzip compressed data"):
 
1889
                compressed_extension = "gz"
 
1890
            if output.startswith("XZ compressed data"):
 
1891
                compressed_extension = "xz"
1803
1892
            with open("%s.type" % source_prefix) as compressed_type:
1804
1893
                real_output = compressed_type.readline().rstrip("\n")
1805
1894
            if real_output.startswith("ISO 9660 CD-ROM filesystem data "):
1806
 
                return "iso.gz"
 
1895
                return "iso.%s" % compressed_extension
1807
1896
            elif real_output.startswith("x86 boot sector"):
1808
 
                return "img.gz"
 
1897
                return "img.%s" % compressed_extension
1809
1898
            elif real_output.startswith("tar archive"):
1810
 
                return "tar.gz"
 
1899
                return "tar.%s" % compressed_extension
1811
1900
            else:
1812
1901
                logger.warning(
1813
 
                    "Unknown compressed file type '%s'; assuming .img.gz" %
1814
 
                    real_output)
1815
 
                return "img.gz"
 
1902
                    "Unknown compressed file type '%s'; assuming .img.%s" %
 
1903
                    (real_output, compressed_extension))
 
1904
                return "img.%s" % compressed_extension
1816
1905
        else:
1817
1906
            logger.warning("Unknown file type '%s'; assuming .iso" % output)
1818
1907
            return "iso"
1846
1935
 
1847
1936
    def publish_binary(self, publish_type, arch, date):
1848
1937
        in_prefix = "%s-%s-%s" % (self.config.series, publish_type, arch)
1849
 
        out_prefix = "%s-%s-%s" % (self.config.series, publish_type, arch)
 
1938
        if publish_type == "live-core":
 
1939
            out_prefix = "ubuntu-core-%s-%s" % (self.config.core_series, arch)
 
1940
        else:
 
1941
            out_prefix = "%s-%s-%s" % (self.config.series, publish_type, arch)
1850
1942
        source_dir = self.image_output(arch)
1851
1943
        source_prefix = os.path.join(source_dir, in_prefix)
1852
1944
        target_dir = os.path.join(self.publish_base, date)
1949
2041
                        "%s.%s.device.tar.gz" % (source_prefix, devarch),
1950
2042
                        "%s.%s.device.tar.gz" % (target_prefix, devarch))
1951
2043
 
 
2044
        # os snap packages
 
2045
        if os.path.exists("%s.os.snap" % source_prefix):
 
2046
            logger.info("Publishing %s os snap package ..." % arch)
 
2047
            shutil.move(
 
2048
                "%s.os.snap" % source_prefix,
 
2049
                "%s.os.snap" % target_prefix)
 
2050
 
 
2051
        # kernel snap packages
 
2052
        if os.path.exists("%s.kernel.snap" % source_prefix):
 
2053
            logger.info("Publishing %s kernel snap package ..." % arch)
 
2054
            shutil.move(
 
2055
                "%s.kernel.snap" % source_prefix,
 
2056
                "%s.kernel.snap" % target_prefix)
 
2057
 
 
2058
            for devarch in ("dragonboard", "raspi2"):
 
2059
                if os.path.exists("%s.%s.kernel.snap" % (source_prefix,
 
2060
                                                         devarch)):
 
2061
                    logger.info("Publishing %s %s kernel snap package ..." %
 
2062
                                (arch, devarch))
 
2063
                    shutil.move(
 
2064
                        "%s.%s.kernel.snap" % (source_prefix, devarch),
 
2065
                        "%s.%s.kernel.snap" % (target_prefix, devarch))
 
2066
 
 
2067
        # snappy model assertions
 
2068
        if os.path.exists("%s.model-assertion" % source_prefix):
 
2069
            logger.info("Publishing %s model assertion ..." % arch)
 
2070
            shutil.move(
 
2071
                "%s.model-assertion" % source_prefix,
 
2072
                "%s.model-assertion" % target_prefix)
 
2073
 
1952
2074
        # zsync metafiles
1953
2075
        if osextras.find_on_path("zsyncmake"):
1954
2076
            logger.info("Making %s zsync metafile ..." % arch)
2003
2125
            shutil.copy2(
2004
2126
                "%s.manifest-remove" % source_prefix,
2005
2127
                "%s.manifest-remove" % target_prefix)
 
2128
        if os.path.exists("%s.manifest-minimal-remove" % source_prefix):
 
2129
            shutil.copy2(
 
2130
                "%s.manifest-minimal-remove" % source_prefix,
 
2131
                "%s.manifest-minimal-remove" % target_prefix)
2006
2132
        elif os.path.exists("%s.manifest-desktop" % source_prefix):
2007
2133
            shutil.copy2(
2008
2134
                "%s.manifest-desktop" % source_prefix,
2117
2243
                continue
2118
2244
            if (entry.startswith("%s-" % self.config.series) or
2119
2245
                (self.config.subproject == "wubi" and
2120
 
                 entry.endswith(".tar.xz"))):
 
2246
                 entry.endswith(".tar.xz")) or
 
2247
                (self.config.project == "ubuntu-core" and
 
2248
                 self.image_type == "daily-live" and
 
2249
                 entry.endswith(".img.xz"))):
2121
2250
                images.add(entry)
2122
2251
        return images
2123
2252
 
2153
2282
            for arch in arches:
2154
2283
                if image_base.endswith("-%s" % arch):
2155
2284
                    matches = True
2156
 
                elif (self.config.project in ("ubuntu-touch", "ubuntu-pd") and
 
2285
                elif (self.config.project in ("ubuntu-touch",
 
2286
                                              "ubuntu-touch-custom") and
2157
2287
                      arch == "armhf" and
2158
2288
                      ("-armel+" in image_base or "-armhf+" in image_base)):
2159
2289
                    matches = True
2160
 
                elif (self.config.project in ("ubuntu-touch", "ubuntu-pd") and
 
2290
                elif (self.config.project in ("ubuntu-touch",
 
2291
                                              "ubuntu-touch-custom") and
2161
2292
                      arch == "i386" and "-i386+" in image_base):
2162
2293
                    matches = True
 
2294
                elif (self.config.project in ("ubuntu-touch",
 
2295
                                              "ubuntu-touch-custom") and
 
2296
                      arch == "arm64" and "-arm64+" in image_base):
 
2297
                    matches = True
2163
2298
                elif self.config.subproject == "wubi" and image_base == arch:
2164
2299
                    matches = True
2165
2300
                else:
2236
2371
                    continue
2237
2372
                if self.image_type != image_type:
2238
2373
                    continue
2239
 
                if self.config.full_series != series:
 
2374
                if not self.config.match_series(series):
2240
2375
                    continue
2241
2376
                if arch in arches:
2242
2377
                    return True
2790
2925
            path,
2791
2926
        ])
2792
2927
        if self.dry_run:
2793
 
            logger.info(
2794
 
                " ".join(osextras.shell_escape(arg) for arg in command))
 
2928
            logger.info(" ".join(shell_quote(arg) for arg in command))
2795
2929
        else:
2796
2930
            with open("/dev/null", "w") as devnull:
2797
2931
                subprocess.check_call(command, stdout=devnull)
2922
3056
            "uec", "server-uec", "core", "wubi",
2923
3057
        ):
2924
3058
            return True
 
3059
        elif publish_type.startswith("preinstalled") and os.path.exists(path):
 
3060
            return True
2925
3061
        elif publish_type == "dvd" and os.path.exists(path):
2926
3062
            # DVDs are allowed to not have .manifest files, but may have
2927
3063
            # them depending on configuration.
2979
3115
                return os.path.join(
2980
3116
                    torrent_dir, "%s%s%s" % (base_plain, sep, ext))
2981
3117
 
2982
 
        for ext in "iso", "img", "img.gz", "tar.gz", "img.tar.gz", "tar.xz":
 
3118
        for ext in ("iso", "img", "img.gz", "img.xz", "tar.gz", "img.tar.gz",
 
3119
                    "tar.xz"):
2983
3120
            if os.path.exists(daily(ext)):
2984
3121
                break
2985
3122
        else:
2986
3123
            return
2987
3124
 
2988
3125
        # Copy, to make sure we have a canonical version of this.
2989
 
        artifacts = ["iso", "list", "img", "img.gz", "tar.gz", "img.tar.gz",
2990
 
                     "tar.xz", "bootimg", "custom.tar.gz", "device.tar.gz",
2991
 
                     "azure.device.tar.gz"]
 
3126
        artifacts = ["iso", "list", "img", "img.gz", "img.xz", "tar.gz",
 
3127
                     "img.tar.gz", "tar.xz", "bootimg", "custom.tar.gz",
 
3128
                     "device.tar.gz", "azure.device.tar.gz"]
2992
3129
        for ext in artifacts:
2993
3130
            if not os.path.exists(daily(ext)):
2994
3131
                continue
3053
3190
            if self.want_full:
3054
3191
                self.copy(daily("manifest"), full("manifest"))
3055
3192
 
3056
 
        for ext in "iso", "img", "img.gz", "tar.gz":
 
3193
        for ext in "iso", "img", "img.gz", "img.xz", "tar.gz":
3057
3194
            zsyncext = "%s.zsync" % ext
3058
3195
            if not os.path.exists(daily(zsyncext)):
3059
3196
                continue
3108
3245
            if source == "ubuntu-server/daily":
3109
3246
                source = os.path.join(
3110
3247
                    "ubuntu-server", series.full_name, "daily")
 
3248
            elif source == "ubuntu-server/daily-preinstalled":
 
3249
                source = os.path.join(
 
3250
                    "ubuntu-server", series.full_name, "daily-preinstalled")
3111
3251
            else:
3112
3252
                source = os.path.join(series.full_name, source)
3113
3253
 
3136
3276
        if publish_type not in ("netbook", "mid", "src"):
3137
3277
            for arch in arches:
3138
3278
                paths = []
3139
 
                for ext in "iso", "img", "img.gz", "img.tar.gz", "tar.gz":
 
3279
                for ext in ("iso", "img", "img.gz", "img.xz", "img.tar.gz",
 
3280
                            "tar.gz"):
3140
3281
                    paths.append(os.path.join(
3141
3282
                        daily_dir,
3142
3283
                        "%s-%s-%s.%s" % (series, publish_type, arch, ext)))
3248
3389
                logger.info(
3249
3390
                    "Creating and publishing metalink files for the simple "
3250
3391
                    "tree (%s) ..." % series)
3251
 
                self.make_metalink(target_dir, self.metalink_version)
 
3392
                self.make_metalink(
 
3393
                    target_dir, self.metalink_version, dry_run=self.dry_run)
3252
3394
        if self.want_full:
3253
3395
            logger.info("Checksumming full tree ...")
3254
3396
            self.checksum_directory(
3264
3406
                        self.full_version, self.status)
3265
3407
                else:
3266
3408
                    metalink_target_dir = target_dir
3267
 
                self.make_metalink(metalink_target_dir, self.version)
 
3409
                self.make_metalink(
 
3410
                    metalink_target_dir, self.version, dry_run=self.dry_run)
3268
3411
 
3269
3412
        if self.want_dist or self.want_pool:
3270
3413
            if self.dry_run: