示例#1
0
    def test_unpack_dsc_with_vendor(self):
        # Some source packages unpack differently depending on dpkg's idea
        # of the "vendor", and in extreme cases may even fail with some
        # vendors.  gina always sets the vendor to the target distribution
        # name to ensure that it unpacks packages as if unpacking on that
        # distribution.
        archive_root = self.useTempDir()
        pool_dir = os.path.join(archive_root, "pool/main/f/foo")
        os.makedirs(pool_dir)

        # Synthesise a package that can be unpacked with DEB_VENDOR=debian
        # but not with DEB_VENDOR=ubuntu.
        with open(os.path.join(pool_dir, "foo_1.0.orig.tar.gz"),
                  "wb+") as buffer:
            orig_tar = LaunchpadWriteTarFile(buffer)
            orig_tar.add_directory("foo-1.0")
            orig_tar.close()
            buffer.seek(0)
            orig_tar_contents = buffer.read()
        with open(os.path.join(pool_dir, "foo_1.0-1.debian.tar.gz"),
                  "wb+") as buffer:
            debian_tar = LaunchpadWriteTarFile(buffer)
            debian_tar.add_file("debian/source/format", "3.0 (quilt)\n")
            debian_tar.add_file("debian/patches/ubuntu.series",
                                "--- corrupt patch\n")
            debian_tar.add_file("debian/rules", "")
            debian_tar.close()
            buffer.seek(0)
            debian_tar_contents = buffer.read()
        dsc_path = os.path.join(pool_dir, "foo_1.0-1.dsc")
        with open(dsc_path, "w") as dsc:
            dsc.write(
                dedent("""\
                Format: 3.0 (quilt)
                Source: foo
                Binary: foo
                Architecture: all
                Version: 1.0-1
                Maintainer: Foo Bar <*****@*****.**>
                Files:
                 %s %s foo_1.0.orig.tar.gz
                 %s %s foo_1.0-1.debian.tar.gz
                """ % (hashlib.md5(orig_tar_contents).hexdigest(),
                       len(orig_tar_contents),
                       hashlib.md5(debian_tar_contents).hexdigest(),
                       len(debian_tar_contents))))

        dsc_contents = parse_tagfile(dsc_path)
        dsc_contents["Directory"] = pool_dir
        dsc_contents["Package"] = "foo"
        dsc_contents["Component"] = "main"
        dsc_contents["Section"] = "misc"

        sp_data = SourcePackageData(**dsc_contents)
        # Unpacking this in an Ubuntu context fails.
        self.assertRaises(ExecutionError, sp_data.do_package, "ubuntu",
                          archive_root)
        # But all is well in a Debian context.
        sp_data.do_package("debian", archive_root)
示例#2
0
    def test_process_package_cleans_up_after_unpack_failure(self):
        archive_root = self.useTempDir()
        pool_dir = os.path.join(archive_root, "pool/main/f/foo")
        os.makedirs(pool_dir)

        with open(os.path.join(
            pool_dir, "foo_1.0.orig.tar.gz"), "wb+") as buffer:
            orig_tar = LaunchpadWriteTarFile(buffer)
            orig_tar.add_directory("foo-1.0")
            orig_tar.close()
            buffer.seek(0)
            orig_tar_contents = buffer.read()
        with open(os.path.join(
            pool_dir, "foo_1.0-1.debian.tar.gz"), "wb+") as buffer:
            debian_tar = LaunchpadWriteTarFile(buffer)
            debian_tar.add_file("debian/source/format", "3.0 (quilt)\n")
            debian_tar.add_file("debian/patches/series", "--- corrupt patch\n")
            debian_tar.add_file("debian/rules", "")
            debian_tar.close()
            buffer.seek(0)
            debian_tar_contents = buffer.read()
        dsc_path = os.path.join(pool_dir, "foo_1.0-1.dsc")
        with open(dsc_path, "w") as dsc:
            dsc.write(dedent("""\
                Format: 3.0 (quilt)
                Source: foo
                Binary: foo
                Architecture: all
                Version: 1.0-1
                Maintainer: Foo Bar <*****@*****.**>
                Files:
                 %s %s foo_1.0.orig.tar.gz
                 %s %s foo_1.0-1.debian.tar.gz
                """ % (
                    hashlib.md5(orig_tar_contents).hexdigest(),
                    len(orig_tar_contents),
                    hashlib.md5(debian_tar_contents).hexdigest(),
                    len(debian_tar_contents))))

        dsc_contents = parse_tagfile(dsc_path)
        dsc_contents["Directory"] = pool_dir
        dsc_contents["Package"] = "foo"
        dsc_contents["Component"] = "main"
        dsc_contents["Section"] = "misc"

        sp_data = SourcePackageData(**dsc_contents)
        unpack_tmpdir = self.makeTemporaryDirectory()
        with EnvironmentVariableFixture("TMPDIR", unpack_tmpdir):
            # Force tempfile to recheck TMPDIR.
            tempfile.tempdir = None
            try:
                self.assertRaises(
                    ExecutionError,
                    sp_data.process_package, "ubuntu", archive_root)
            finally:
                # Force tempfile to recheck TMPDIR for future tests.
                tempfile.tempdir = None
        self.assertEqual([], os.listdir(unpack_tmpdir))
示例#3
0
    def test_unpack_dsc_with_vendor(self):
        # Some source packages unpack differently depending on dpkg's idea
        # of the "vendor", and in extreme cases may even fail with some
        # vendors.  gina always sets the vendor to the target distribution
        # name to ensure that it unpacks packages as if unpacking on that
        # distribution.
        archive_root = self.useTempDir()
        pool_dir = os.path.join(archive_root, "pool/main/f/foo")
        os.makedirs(pool_dir)

        # Synthesise a package that can be unpacked with DEB_VENDOR=debian
        # but not with DEB_VENDOR=ubuntu.
        with open(os.path.join(pool_dir, "foo_1.0.orig.tar.gz"), "wb+") as buffer:
            orig_tar = LaunchpadWriteTarFile(buffer)
            orig_tar.add_directory("foo-1.0")
            orig_tar.close()
            buffer.seek(0)
            orig_tar_contents = buffer.read()
        with open(os.path.join(pool_dir, "foo_1.0-1.debian.tar.gz"), "wb+") as buffer:
            debian_tar = LaunchpadWriteTarFile(buffer)
            debian_tar.add_file("debian/source/format", "3.0 (quilt)\n")
            debian_tar.add_file("debian/patches/ubuntu.series", "--- corrupt patch\n")
            debian_tar.add_file("debian/rules", "")
            debian_tar.close()
            buffer.seek(0)
            debian_tar_contents = buffer.read()
        dsc_path = os.path.join(pool_dir, "foo_1.0-1.dsc")
        with open(dsc_path, "w") as dsc:
            dsc.write(
                dedent(
                    """\
                Format: 3.0 (quilt)
                Source: foo
                Binary: foo
                Architecture: all
                Version: 1.0-1
                Maintainer: Foo Bar <*****@*****.**>
                Files:
                 %s %s foo_1.0.orig.tar.gz
                 %s %s foo_1.0-1.debian.tar.gz
                """
                    % (
                        hashlib.md5(orig_tar_contents).hexdigest(),
                        len(orig_tar_contents),
                        hashlib.md5(debian_tar_contents).hexdigest(),
                        len(debian_tar_contents),
                    )
                )
            )

        dsc_contents = parse_tagfile(dsc_path)
        dsc_contents["Directory"] = pool_dir
        dsc_contents["Package"] = "foo"
        dsc_contents["Component"] = "main"
        dsc_contents["Section"] = "misc"

        sp_data = SourcePackageData(**dsc_contents)
        # Unpacking this in an Ubuntu context fails.
        self.assertRaises(ExecutionError, sp_data.do_package, "ubuntu", archive_root)
        # But all is well in a Debian context.
        sp_data.do_package("debian", archive_root)
示例#4
0
class TestDdtpTarball(TestCaseWithFactory):

    layer = ZopelessDatabaseLayer

    def setUp(self):
        super(TestDdtpTarball, self).setUp()
        self.temp_dir = self.makeTemporaryDirectory()
        self.distro = self.factory.makeDistribution()
        db_pubconf = getUtility(IPublisherConfigSet).getByDistribution(
            self.distro)
        db_pubconf.root_dir = unicode(self.temp_dir)
        self.archive = self.factory.makeArchive(distribution=self.distro,
                                                purpose=ArchivePurpose.PRIMARY)
        self.suite = "distroseries"
        # CustomUpload.installFiles requires a umask of 0o022.
        old_umask = os.umask(0o022)
        self.addCleanup(os.umask, old_umask)

    def openArchive(self, version):
        self.path = os.path.join(self.temp_dir,
                                 "translations_main_%s.tar.gz" % version)
        self.buffer = open(self.path, "wb")
        self.tarfile = LaunchpadWriteTarFile(self.buffer)

    def process(self):
        self.tarfile.close()
        self.buffer.close()
        DdtpTarballUpload().process(self.archive, self.path, self.suite)

    def getTranslationsPath(self, filename):
        pubconf = getPubConfig(self.archive)
        return os.path.join(pubconf.archiveroot, "dists", self.suite, "main",
                            "i18n", filename)

    def test_basic(self):
        # Processing a simple correct tar file works.
        self.openArchive("20060728")
        self.tarfile.add_file("i18n/Translation-de", b"")
        self.process()
        self.assertTrue(
            os.path.exists(self.getTranslationsPath("Translation-de")))

    def test_ignores_empty_directories(self):
        # Empty directories in the tarball are not extracted.
        self.openArchive("20060728")
        self.tarfile.add_file("i18n/Translation-de", b"")
        self.tarfile.add_directory("i18n/foo")
        self.process()
        self.assertTrue(
            os.path.exists(self.getTranslationsPath("Translation-de")))
        self.assertFalse(os.path.exists(self.getTranslationsPath("foo")))

    def test_partial_update(self):
        # If a DDTP tarball only contains a subset of published translation
        # files, these are updated and the rest are left untouched.
        self.openArchive("20060728")
        self.tarfile.add_file("i18n/Translation-bn", b"bn")
        self.tarfile.add_file("i18n/Translation-ca", b"ca")
        self.process()
        with open(self.getTranslationsPath("Translation-bn")) as bn_file:
            self.assertEqual("bn", bn_file.read())
        with open(self.getTranslationsPath("Translation-ca")) as ca_file:
            self.assertEqual("ca", ca_file.read())
        self.openArchive("20060817")
        self.tarfile.add_file("i18n/Translation-bn", b"new bn")
        self.process()
        with open(self.getTranslationsPath("Translation-bn")) as bn_file:
            self.assertEqual("new bn", bn_file.read())
        with open(self.getTranslationsPath("Translation-ca")) as ca_file:
            self.assertEqual("ca", ca_file.read())

    def test_breaks_hard_links(self):
        # Our archive uses dsync to replace identical files with hard links
        # in order to save some space.  tarfile.extract overwrites
        # pre-existing files rather than creating new files and moving them
        # into place, so making this work requires special care.  Test that
        # that care has been taken.
        self.openArchive("20060728")
        self.tarfile.add_file("i18n/Translation-ca", b"")
        self.process()
        ca = self.getTranslationsPath("Translation-ca")
        bn = self.getTranslationsPath("Translation-bn")
        os.link(ca, bn)
        self.assertTrue(os.path.exists(bn))
        self.assertEqual(2, os.stat(bn).st_nlink)
        self.assertEqual(2, os.stat(ca).st_nlink)
        self.openArchive("20060817")
        self.tarfile.add_file("i18n/Translation-bn", b"break hard link")
        self.process()
        with open(bn) as bn_file:
            self.assertEqual("break hard link", bn_file.read())
        with open(ca) as ca_file:
            self.assertEqual("", ca_file.read())
        self.assertEqual(1, os.stat(bn).st_nlink)
        self.assertEqual(1, os.stat(ca).st_nlink)

    def test_parsePath_handles_underscore_in_directory(self):
        # parsePath is not misled by an underscore in the directory name.
        self.assertEqual(
            # XXX cjwatson 2012-07-03: .tar.gz is not stripped off the end
            # of the version due to something of an ambiguity in the design;
            # how should translations_main_1.0.1.tar.gz be parsed?  In
            # practice this doesn't matter because DdtpTarballUpload never
            # uses the version for anything.
            ("translations", "main", "1.tar.gz"),
            DdtpTarballUpload.parsePath(
                "/dir_with_underscores/translations_main_1.tar.gz"))

    def test_getSeriesKey_extracts_component(self):
        # getSeriesKey extracts the component from an upload's filename.
        self.openArchive("20060728")
        self.assertEqual("main", DdtpTarballUpload.getSeriesKey(self.path))

    def test_getSeriesKey_returns_None_on_mismatch(self):
        # getSeriesKey returns None if the filename does not match the
        # expected pattern.
        self.assertIsNone(DdtpTarballUpload.getSeriesKey("argh_1.0.jpg"))

    def test_getSeriesKey_refuses_names_with_wrong_number_of_fields(self):
        # getSeriesKey requires exactly three fields.
        self.assertIsNone(DdtpTarballUpload.getSeriesKey("package_1.0.tar.gz"))
        self.assertIsNone(
            DdtpTarballUpload.getSeriesKey("one_two_three_four_5.tar.gz"))
class TestDdtpTarball(TestCase):

    def setUp(self):
        super(TestDdtpTarball, self).setUp()
        self.temp_dir = self.makeTemporaryDirectory()
        self.pubconf = FakeConfig(self.temp_dir)
        self.suite = "distroseries"
        # CustomUpload.installFiles requires a umask of 022.
        old_umask = os.umask(022)
        self.addCleanup(os.umask, old_umask)

    def openArchive(self, version):
        self.path = os.path.join(
            self.temp_dir, "translations_main_%s.tar.gz" % version)
        self.buffer = open(self.path, "wb")
        self.archive = LaunchpadWriteTarFile(self.buffer)

    def process(self):
        self.archive.close()
        self.buffer.close()
        process_ddtp_tarball(self.pubconf, self.path, self.suite)

    def getTranslationsPath(self, filename):
        return os.path.join(
            self.temp_dir, "dists", self.suite, "main", "i18n", filename)

    def test_basic(self):
        # Processing a simple correct tar file works.
        self.openArchive("20060728")
        self.archive.add_file("i18n/Translation-de", "")
        self.process()
        self.assertTrue(os.path.exists(
            self.getTranslationsPath("Translation-de")))

    def test_ignores_empty_directories(self):
        # Empty directories in the tarball are not extracted.
        self.openArchive("20060728")
        self.archive.add_file("i18n/Translation-de", "")
        self.archive.add_directory("i18n/foo")
        self.process()
        self.assertTrue(os.path.exists(
            self.getTranslationsPath("Translation-de")))
        self.assertFalse(os.path.exists(self.getTranslationsPath("foo")))

    def test_partial_update(self):
        # If a DDTP tarball only contains a subset of published translation
        # files, these are updated and the rest are left untouched.
        self.openArchive("20060728")
        self.archive.add_file("i18n/Translation-bn", "bn")
        self.archive.add_file("i18n/Translation-ca", "ca")
        self.process()
        with open(self.getTranslationsPath("Translation-bn")) as bn_file:
            self.assertEqual("bn", bn_file.read())
        with open(self.getTranslationsPath("Translation-ca")) as ca_file:
            self.assertEqual("ca", ca_file.read())
        self.openArchive("20060817")
        self.archive.add_file("i18n/Translation-bn", "new bn")
        self.process()
        with open(self.getTranslationsPath("Translation-bn")) as bn_file:
            self.assertEqual("new bn", bn_file.read())
        with open(self.getTranslationsPath("Translation-ca")) as ca_file:
            self.assertEqual("ca", ca_file.read())

    def test_breaks_hard_links(self):
        # Our archive uses dsync to replace identical files with hard links
        # in order to save some space.  tarfile.extract overwrites
        # pre-existing files rather than creating new files and moving them
        # into place, so making this work requires special care.  Test that
        # that care has been taken.
        self.openArchive("20060728")
        self.archive.add_file("i18n/Translation-ca", "")
        self.process()
        ca = self.getTranslationsPath("Translation-ca")
        bn = self.getTranslationsPath("Translation-bn")
        os.link(ca, bn)
        self.assertTrue(os.path.exists(bn))
        self.assertEqual(2, os.stat(bn).st_nlink)
        self.assertEqual(2, os.stat(ca).st_nlink)
        self.openArchive("20060817")
        self.archive.add_file("i18n/Translation-bn", "break hard link")
        self.process()
        with open(bn) as bn_file:
            self.assertEqual("break hard link", bn_file.read())
        with open(ca) as ca_file:
            self.assertEqual("", ca_file.read())
        self.assertEqual(1, os.stat(bn).st_nlink)
        self.assertEqual(1, os.stat(ca).st_nlink)

    def test_parsePath_handles_underscore_in_directory(self):
        # parsePath is not misled by an underscore in the directory name.
        self.assertEqual(
            # XXX cjwatson 2012-07-03: .tar.gz is not stripped off the end
            # of the version due to something of an ambiguity in the design;
            # how should translations_main_1.0.1.tar.gz be parsed?  In
            # practice this doesn't matter because DdtpTarballUpload never
            # uses the version for anything.
            ("translations", "main", "1.tar.gz"),
            DdtpTarballUpload.parsePath(
                "/dir_with_underscores/translations_main_1.tar.gz"))

    def test_getSeriesKey_extracts_component(self):
        # getSeriesKey extracts the component from an upload's filename.
        self.openArchive("20060728")
        self.assertEqual("main", DdtpTarballUpload.getSeriesKey(self.path))

    def test_getSeriesKey_returns_None_on_mismatch(self):
        # getSeriesKey returns None if the filename does not match the
        # expected pattern.
        self.assertIsNone(DdtpTarballUpload.getSeriesKey("argh_1.0.jpg"))

    def test_getSeriesKey_refuses_names_with_wrong_number_of_fields(self):
        # getSeriesKey requires exactly three fields.
        self.assertIsNone(DdtpTarballUpload.getSeriesKey("package_1.0.tar.gz"))
        self.assertIsNone(DdtpTarballUpload.getSeriesKey(
            "one_two_three_four_5.tar.gz"))