Merge ~cjwatson/launchpad:fix-ftparchive-avoid-empty-overrides into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: c4cee494af3a5c9c19ee0d892666cf99fb2c169f
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:fix-ftparchive-avoid-empty-overrides
Merge into: launchpad:master
Diff against target: 189 lines (+79/-12)
2 files modified
lib/lp/archivepublisher/model/ftparchive.py (+23/-8)
lib/lp/archivepublisher/tests/test_ftparchive.py (+56/-4)
Reviewer Review Type Date Requested Status
Tom Wardill (community) Approve
Review via email: mp+399985@code.launchpad.net

Commit message

Generate empty override and file list files where necessary

Description of the change

Commit 25ce0c1d87 stopped `FTPArchive.createEmptyPocketRequests` from writing empty override and file list files for all suites/components, instead merely making sure that they exist. However, this broke in the case where a suite/component (or suite/component/architecture) was non-empty and then became empty, because the previous non-empty overrides and file lists were left in place.

To avoid this, ensure that `FTPArchive.publishOverrides` writes override files for all relevant components, and that `FTPArchive.publishFileLists` writes file list files for all relevant components/architectures; these may be empty if there are no publications in the corresponding contexts. This doesn't suffer from the problem that the aforementioned commit was fixing, because these files are put in place atomically.

It's possible that this comes close to making `FTPArchive.createEmptyPocketRequests` entirely unnecessary, but I haven't yet tried to remove it.

To post a comment you must log in.
Revision history for this message
Tom Wardill (twom) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/archivepublisher/model/ftparchive.py b/lib/lp/archivepublisher/model/ftparchive.py
index a13269e..624aebf 100644
--- a/lib/lp/archivepublisher/model/ftparchive.py
+++ b/lib/lp/archivepublisher/model/ftparchive.py
@@ -382,10 +382,9 @@ class FTPArchiveHandler:
382382
383 spphs = self.getSourcesForOverrides(distroseries, pocket)383 spphs = self.getSourcesForOverrides(distroseries, pocket)
384 bpphs = self.getBinariesForOverrides(distroseries, pocket)384 bpphs = self.getBinariesForOverrides(distroseries, pocket)
385 self.publishOverrides(385 self.publishOverrides(distroseries, pocket, spphs, bpphs)
386 distroseries.getSuite(pocket), spphs, bpphs)
387386
388 def publishOverrides(self, suite,387 def publishOverrides(self, distroseries, pocket,
389 source_publications, binary_publications):388 source_publications, binary_publications):
390 """Output a set of override files for use in apt-ftparchive.389 """Output a set of override files for use in apt-ftparchive.
391390
@@ -408,8 +407,15 @@ class FTPArchiveHandler:
408 # test_ftparchive.407 # test_ftparchive.
409 from lp.archivepublisher.publishing import FORMAT_TO_SUBCOMPONENT408 from lp.archivepublisher.publishing import FORMAT_TO_SUBCOMPONENT
410409
410 suite = distroseries.getSuite(pocket)
411
411 # overrides[component][src/bin] = sets of tuples412 # overrides[component][src/bin] = sets of tuples
412 overrides = defaultdict(lambda: defaultdict(set))413 overrides = defaultdict(lambda: defaultdict(set))
414 # Ensure that we generate overrides for all the expected components,
415 # even if they're currently empty.
416 for component in self.publisher.archive.getComponentsForSeries(
417 distroseries):
418 overrides[component.name]
413419
414 def updateOverride(packagename, component, section, archtag=None,420 def updateOverride(packagename, component, section, archtag=None,
415 priority=None, binpackageformat=None,421 priority=None, binpackageformat=None,
@@ -666,16 +672,25 @@ class FTPArchiveHandler:
666 continue672 continue
667 spps = self.getSourceFiles(distroseries, pocket)673 spps = self.getSourceFiles(distroseries, pocket)
668 pps = self.getBinaryFiles(distroseries, pocket)674 pps = self.getBinaryFiles(distroseries, pocket)
669 self.publishFileLists(distroseries.getSuite(pocket), spps, pps)675 self.publishFileLists(distroseries, pocket, spps, pps)
670676
671 def publishFileLists(self, suite, sourcefiles, binaryfiles):677 def publishFileLists(self, distroseries, pocket, sourcefiles, binaryfiles):
672 """Collate the set of source files and binary files provided and678 """Collate the set of source files and binary files provided and
673 write out all the file list files for them.679 write out all the file list files for them.
674680
675 listroot/distroseries_component_source681 listroot/distroseries_component_source
676 listroot/distroseries_component_binary-archname682 listroot/distroseries_component_binary-archname
677 """683 """
684 suite = distroseries.getSuite(pocket)
685
678 filelist = defaultdict(lambda: defaultdict(list))686 filelist = defaultdict(lambda: defaultdict(list))
687 # Ensure that we generate file lists for all the expected components
688 # and architectures, even if they're currently empty.
689 for component in self.publisher.archive.getComponentsForSeries(
690 distroseries):
691 filelist[component.name]["source"]
692 for das in distroseries.enabled_architectures:
693 filelist[component.name]["binary-%s" % das.architecturetag]
679694
680 def updateFileList(sourcepackagename, filename, component,695 def updateFileList(sourcepackagename, filename, component,
681 architecturetag=None):696 architecturetag=None):
@@ -698,7 +713,6 @@ class FTPArchiveHandler:
698 updateFileList(*file_details)713 updateFileList(*file_details)
699714
700 self.log.debug("Writing file lists for %s" % suite)715 self.log.debug("Writing file lists for %s" % suite)
701 series, pocket = self.distro.getDistroSeriesAndPocket(suite)
702 for component, architectures in six.iteritems(filelist):716 for component, architectures in six.iteritems(filelist):
703 for architecture, file_names in six.iteritems(architectures):717 for architecture, file_names in six.iteritems(architectures):
704 # XXX wgrant 2010-10-06: There must be a better place to do718 # XXX wgrant 2010-10-06: There must be a better place to do
@@ -708,7 +722,7 @@ class FTPArchiveHandler:
708 else:722 else:
709 # The "[7:]" strips the "binary-" prefix off the723 # The "[7:]" strips the "binary-" prefix off the
710 # architecture names we get here.724 # architecture names we get here.
711 das = series.getDistroArchSeries(architecture[7:])725 das = distroseries.getDistroArchSeries(architecture[7:])
712 enabled = das.enabled726 enabled = das.enabled
713 if enabled:727 if enabled:
714 self.writeFileList(728 self.writeFileList(
@@ -740,7 +754,8 @@ class FTPArchiveHandler:
740 with open(new_path, 'w') as f:754 with open(new_path, 'w') as f:
741 files[subcomp].sort(key=package_name)755 files[subcomp].sort(key=package_name)
742 f.write("\n".join(files[subcomp]))756 f.write("\n".join(files[subcomp]))
743 f.write("\n")757 if files[subcomp]:
758 f.write("\n")
744 os.rename(new_path, final_path)759 os.rename(new_path, final_path)
745760
746 #761 #
diff --git a/lib/lp/archivepublisher/tests/test_ftparchive.py b/lib/lp/archivepublisher/tests/test_ftparchive.py
index 3a9665a..94b68fc 100755
--- a/lib/lp/archivepublisher/tests/test_ftparchive.py
+++ b/lib/lp/archivepublisher/tests/test_ftparchive.py
@@ -186,13 +186,17 @@ class TestFTPArchive(TestCaseWithFactory):
186 'tiny', component, section, 'i386',186 'tiny', component, section, 'i386',
187 PackagePublishingPriority.EXTRA, binpackageformat,187 PackagePublishingPriority.EXTRA, binpackageformat,
188 phased_update_percentage)])188 phased_update_percentage)])
189 fa.publishOverrides('hoary-test', source_overrides, binary_overrides)189 fa.publishOverrides(
190 self._distribution['hoary-test'], PackagePublishingPocket.RELEASE,
191 source_overrides, binary_overrides)
190192
191 def _publishDefaultFileLists(self, fa, component):193 def _publishDefaultFileLists(self, fa, component):
192 source_files = FakeSelectResult([('tiny', 'tiny_0.1.dsc', component)])194 source_files = FakeSelectResult([('tiny', 'tiny_0.1.dsc', component)])
193 binary_files = FakeSelectResult(195 binary_files = FakeSelectResult(
194 [('tiny', 'tiny_0.1_i386.deb', component, 'binary-i386')])196 [('tiny', 'tiny_0.1_i386.deb', component, 'binary-i386')])
195 fa.publishFileLists('hoary-test', source_files, binary_files)197 fa.publishFileLists(
198 self._distribution['hoary-test'], PackagePublishingPocket.RELEASE,
199 source_files, binary_files)
196200
197 def test_createEmptyPocketRequests_preserves_existing(self):201 def test_createEmptyPocketRequests_preserves_existing(self):
198 # createEmptyPocketRequests leaves existing override and file list202 # createEmptyPocketRequests leaves existing override and file list
@@ -362,6 +366,29 @@ class TestFTPArchive(TestCaseWithFactory):
362 self.assertEqual(366 self.assertEqual(
363 ["tiny\textra\tdevel"], result_file.read().splitlines())367 ["tiny\textra\tdevel"], result_file.read().splitlines())
364368
369 def test_publishOverrides_empties_missing_components(self):
370 # publishOverrides writes empty overrides files for components that
371 # have no publications.
372 fa = self._setUpFTPArchiveHandler()
373 empty_overrides = []
374 for component in ("restricted", "universe", "multiverse"):
375 empty_overrides.extend([
376 "override.hoary-test.%s" % component,
377 "override.hoary-test.%s.src" % component,
378 "override.hoary-test.extra.%s" % component,
379 ])
380 for override in empty_overrides:
381 write_file(
382 os.path.join(self._overdir, override), b"previous contents\n")
383
384 self._publishDefaultOverrides(fa, "main")
385
386 self._verifyFile("override.hoary-test.main", self._overdir)
387 self._verifyFile("override.hoary-test.main.src", self._overdir)
388 self._verifyFile("override.hoary-test.extra.main", self._overdir)
389 for override in empty_overrides:
390 self._verifyEmpty(os.path.join(self._overdir, override))
391
365 def test_generateOverrides(self):392 def test_generateOverrides(self):
366 # generateOverrides generates all the overrides from start to finish.393 # generateOverrides generates all the overrides from start to finish.
367 self._distribution = getUtility(IDistributionSet).getByName('ubuntu')394 self._distribution = getUtility(IDistributionSet).getByName('ubuntu')
@@ -459,6 +486,27 @@ class TestFTPArchive(TestCaseWithFactory):
459 self._verifyFile("hoary-test_main_source", self._listdir)486 self._verifyFile("hoary-test_main_source", self._listdir)
460 self._verifyFile("hoary-test_main_binary-i386", self._listdir)487 self._verifyFile("hoary-test_main_binary-i386", self._listdir)
461488
489 def test_publishFileLists_empties_missing_components(self):
490 # publishFileLists writes empty file list files for components that
491 # have no publications.
492 fa = self._setUpFTPArchiveHandler()
493 empty_filelists = []
494 for component in ("restricted", "universe", "multiverse"):
495 empty_filelists.extend([
496 "hoary-test_%s_source" % component,
497 "hoary-test_%s_binary-i386" % component,
498 ])
499 for filelist in empty_filelists:
500 write_file(
501 os.path.join(self._listdir, filelist), b"previous contents\n")
502
503 self._publishDefaultFileLists(fa, "main")
504
505 self._verifyFile("hoary-test_main_source", self._listdir)
506 self._verifyFile("hoary-test_main_binary-i386", self._listdir)
507 for filelist in empty_filelists:
508 self._verifyEmpty(os.path.join(self._listdir, filelist))
509
462 def test_generateConfig(self):510 def test_generateConfig(self):
463 # Generate apt-ftparchive configuration file and run it.511 # Generate apt-ftparchive configuration file and run it.
464512
@@ -727,12 +775,16 @@ class TestFTPArchive(TestCaseWithFactory):
727 "bin%d" % i, "main", "misc", "i386",775 "bin%d" % i, "main", "misc", "i386",
728 PackagePublishingPriority.EXTRA, BinaryPackageFormat.DEB, None)776 PackagePublishingPriority.EXTRA, BinaryPackageFormat.DEB, None)
729 for i in range(50)])777 for i in range(50)])
730 fa.publishOverrides("hoary-test", source_overrides, binary_overrides)778 fa.publishOverrides(
779 self._distribution["hoary-test"], PackagePublishingPocket.RELEASE,
780 source_overrides, binary_overrides)
731 source_files = FakeSelectResult([("tiny", "tiny_0.1.dsc", "main")])781 source_files = FakeSelectResult([("tiny", "tiny_0.1.dsc", "main")])
732 binary_files = FakeSelectResult([(782 binary_files = FakeSelectResult([(
733 "bin%d" % i, "bin%d_1_i386.deb" % i, "main", "binary-i386")783 "bin%d" % i, "bin%d_1_i386.deb" % i, "main", "binary-i386")
734 for i in range(50)])784 for i in range(50)])
735 fa.publishFileLists("hoary-test", source_files, binary_files)785 fa.publishFileLists(
786 self._distribution["hoary-test"], PackagePublishingPocket.RELEASE,
787 source_files, binary_files)
736 self._addRepositoryFile("main", "tiny", "tiny_0.1.dsc")788 self._addRepositoryFile("main", "tiny", "tiny_0.1.dsc")
737 for i in range(50):789 for i in range(50):
738 self._addRepositoryFile(790 self._addRepositoryFile(

Subscribers

People subscribed via source and target branches

to status/vote changes: