Merge lp:~jelmer/launchpad/617393-cleanup-tmp into lp:launchpad

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 11423
Proposed branch: lp:~jelmer/launchpad/617393-cleanup-tmp
Merge into: lp:launchpad
Diff against target: 575 lines (+190/-156)
4 files modified
lib/lp/archiveuploader/dscfile.py (+131/-106)
lib/lp/archiveuploader/nascentupload.py (+0/-7)
lib/lp/archiveuploader/tests/test_dscfile.py (+58/-41)
lib/lp/archiveuploader/tests/test_nascentuploadfile.py (+1/-2)
To merge this branch: bzr merge lp:~jelmer/launchpad/617393-cleanup-tmp
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+33194@code.launchpad.net

Commit message

Clean up temporary directory after unpacking source package for changelog/copyright inspection.

Description of the change

This changes the handling of unpacking of source packages to extract copyright and changelog files.

Rather than keeping the unpacked sources around and cleaning them up afterwards, this makes us clean up the unpacked source directory immediately.

This does have the consequence that we keep the changelog file into memory before streaming it to the librarian rather than streaming it from disk. That seems like a reasonable tradeoff though, as there were already checks in place to make sure that the changelog file is never bigger than 10Mb; we also only keep a single changelog in memory.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Tests: ./bin/test lp.archiveuploader

QA: Run the process uploader and see if any files are left behind in /tmp

Revision history for this message
Abel Deuring (adeuring) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archiveuploader/dscfile.py'
--- lib/lp/archiveuploader/dscfile.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/dscfile.py 2010-08-24 08:53:41 +0000
@@ -13,10 +13,11 @@
13 'SignableTagFile',13 'SignableTagFile',
14 'DSCFile',14 'DSCFile',
15 'DSCUploadedFile',15 'DSCUploadedFile',
16 'findChangelog',16 'find_changelog',
17 'findCopyright',17 'find_copyright',
18 ]18 ]
1919
20from cStringIO import StringIO
20import errno21import errno
21import glob22import glob
22import os23import os
@@ -73,6 +74,70 @@
73from lp.soyuz.interfaces.sourcepackageformat import SourcePackageFormat74from lp.soyuz.interfaces.sourcepackageformat import SourcePackageFormat
7475
7576
77class DpkgSourceError(Exception):
78
79 _fmt = "Unable to unpack source package (%(result)s): %(output)s"
80
81 def __init__(self, output, result):
82 Exception.__init__(
83 self, self._fmt % {"output": output, "result": result})
84 self.output = output
85 self.result = result
86
87
88def unpack_source(dsc_filepath):
89 """Unpack a source package into a temporary directory
90
91 :param dsc_filepath: Path to the dsc file
92 :return: Path to the temporary directory with the unpacked sources
93 """
94 # Get a temporary dir together.
95 unpacked_dir = tempfile.mkdtemp()
96 try:
97 # chdir into it
98 cwd = os.getcwd()
99 os.chdir(unpacked_dir)
100 try:
101 args = ["dpkg-source", "-sn", "-x", dsc_filepath]
102 dpkg_source = subprocess.Popen(args, stdout=subprocess.PIPE,
103 stderr=subprocess.PIPE)
104 output, unused = dpkg_source.communicate()
105 result = dpkg_source.wait()
106 finally:
107 # When all is said and done, chdir out again so that we can
108 # clean up the tree with shutil.rmtree without leaving the
109 # process in a directory we're trying to remove.
110 os.chdir(cwd)
111
112 if result != 0:
113 dpkg_output = prefix_multi_line_string(output, " ")
114 raise DpkgSourceError(result=result, output=dpkg_output)
115 except:
116 shutil.rmtree(unpacked_dir)
117 raise
118
119 return unpacked_dir
120
121
122def cleanup_unpacked_dir(unpacked_dir):
123 """Remove the directory with an unpacked source package.
124
125 :param unpacked_dir: Path to the directory.
126 """
127 try:
128 shutil.rmtree(unpacked_dir)
129 except OSError, error:
130 if errno.errorcode[error.errno] != 'EACCES':
131 raise UploadError(
132 "couldn't remove tmp dir %s: code %s" % (
133 unpacked_dir, error.errno))
134 else:
135 result = os.system("chmod -R u+rwx " + unpacked_dir)
136 if result != 0:
137 raise UploadError("chmod failed with %s" % result)
138 shutil.rmtree(unpacked_dir)
139
140
76class SignableTagFile:141class SignableTagFile:
77 """Base class for signed file verification."""142 """Base class for signed file verification."""
78143
@@ -160,7 +225,7 @@
160 "rfc2047": rfc2047,225 "rfc2047": rfc2047,
161 "name": name,226 "name": name,
162 "email": email,227 "email": email,
163 "person": person228 "person": person,
164 }229 }
165230
166231
@@ -177,9 +242,9 @@
177242
178 # Note that files is actually only set inside verify().243 # Note that files is actually only set inside verify().
179 files = None244 files = None
180 # Copyright and changelog_path are only set inside unpackAndCheckSource().245 # Copyright and changelog are only set inside unpackAndCheckSource().
181 copyright = None246 copyright = None
182 changelog_path = None247 changelog = None
183248
184 def __init__(self, filepath, digest, size, component_and_section,249 def __init__(self, filepath, digest, size, component_and_section,
185 priority, package, version, changes, policy, logger):250 priority, package, version, changes, policy, logger):
@@ -228,12 +293,9 @@
228 else:293 else:
229 self.processSignature()294 self.processSignature()
230295
231 self.unpacked_dir = None
232
233 #296 #
234 # Useful properties.297 # Useful properties.
235 #298 #
236
237 @property299 @property
238 def source(self):300 def source(self):
239 """Return the DSC source name."""301 """Return the DSC source name."""
@@ -267,12 +329,11 @@
267 #329 #
268 # DSC file checks.330 # DSC file checks.
269 #331 #
270
271 def verify(self):332 def verify(self):
272 """Verify the uploaded .dsc file.333 """Verify the uploaded .dsc file.
273334
274 This method is an error generator, i.e, it returns an iterator over all335 This method is an error generator, i.e, it returns an iterator over
275 exceptions that are generated while processing DSC file checks.336 all exceptions that are generated while processing DSC file checks.
276 """337 """
277338
278 for error in SourceUploadFile.verify(self):339 for error in SourceUploadFile.verify(self):
@@ -508,82 +569,53 @@
508 self.logger.debug(569 self.logger.debug(
509 "Verifying uploaded source package by unpacking it.")570 "Verifying uploaded source package by unpacking it.")
510571
511 # Get a temporary dir together.
512 self.unpacked_dir = tempfile.mkdtemp()
513
514 # chdir into it
515 cwd = os.getcwd()
516 os.chdir(self.unpacked_dir)
517 dsc_in_tmpdir = os.path.join(self.unpacked_dir, self.filename)
518
519 package_files = self.files + [self]
520 try:572 try:
521 for source_file in package_files:573 unpacked_dir = unpack_source(self.filepath)
522 os.symlink(574 except DpkgSourceError, e:
523 source_file.filepath,
524 os.path.join(self.unpacked_dir, source_file.filename))
525 args = ["dpkg-source", "-sn", "-x", dsc_in_tmpdir]
526 dpkg_source = subprocess.Popen(args, stdout=subprocess.PIPE,
527 stderr=subprocess.PIPE)
528 output, unused = dpkg_source.communicate()
529 result = dpkg_source.wait()
530 finally:
531 # When all is said and done, chdir out again so that we can
532 # clean up the tree with shutil.rmtree without leaving the
533 # process in a directory we're trying to remove.
534 os.chdir(cwd)
535
536 if result != 0:
537 dpkg_output = prefix_multi_line_string(output, " ")
538 yield UploadError(575 yield UploadError(
539 "dpkg-source failed for %s [return: %s]\n"576 "dpkg-source failed for %s [return: %s]\n"
540 "[dpkg-source output: %s]"577 "[dpkg-source output: %s]"
541 % (self.filename, result, dpkg_output))578 % (self.filename, e.result, e.output))
542579 return
543 # Copy debian/copyright file content. It will be stored in the580
544 # SourcePackageRelease records.581 try:
545582 # Copy debian/copyright file content. It will be stored in the
546 # Check if 'dpkg-source' created only one directory.583 # SourcePackageRelease records.
547 temp_directories = [584
548 dirname for dirname in os.listdir(self.unpacked_dir)585 # Check if 'dpkg-source' created only one directory.
549 if os.path.isdir(dirname)]586 temp_directories = [
550 if len(temp_directories) > 1:587 dirname for dirname in os.listdir(unpacked_dir)
551 yield UploadError(588 if os.path.isdir(dirname)]
552 'Unpacked source contains more than one directory: %r'589 if len(temp_directories) > 1:
553 % temp_directories)590 yield UploadError(
554591 'Unpacked source contains more than one directory: %r'
555 # XXX cprov 20070713: We should access only the expected directory592 % temp_directories)
556 # name (<sourcename>-<no_epoch(no_revision(version))>).593
557594 # XXX cprov 20070713: We should access only the expected directory
558 # Locate both the copyright and changelog files for later processing.595 # name (<sourcename>-<no_epoch(no_revision(version))>).
559 for error in findCopyright(self, self.unpacked_dir, self.logger):596
560 yield error597 # Locate both the copyright and changelog files for later
561598 # processing.
562 for error in findChangelog(self, self.unpacked_dir, self.logger):599 try:
563 yield error600 self.copyright = find_copyright(unpacked_dir, self.logger)
564601 except UploadError, error:
565 self.logger.debug("Cleaning up source tree.")602 yield error
603 return
604 except UploadWarning, warning:
605 yield warning
606
607 try:
608 self.changelog = find_changelog(unpacked_dir, self.logger)
609 except UploadError, error:
610 yield error
611 return
612 except UploadWarning, warning:
613 yield warning
614 finally:
615 self.logger.debug("Cleaning up source tree.")
616 cleanup_unpacked_dir(unpacked_dir)
566 self.logger.debug("Done")617 self.logger.debug("Done")
567618
568 def cleanUp(self):
569 if self.unpacked_dir is None:
570 return
571 try:
572 shutil.rmtree(self.unpacked_dir)
573 except OSError, error:
574 # XXX: dsilvers 2006-03-15: We currently lack a test for this.
575 if errno.errorcode[error.errno] != 'EACCES':
576 raise UploadError(
577 "%s: couldn't remove tmp dir %s: code %s" % (
578 self.filename, self.unpacked_dir, error.errno))
579 else:
580 result = os.system("chmod -R u+rwx " + self.unpacked_dir)
581 if result != 0:
582 raise UploadError("chmod failed with %s" % result)
583 shutil.rmtree(self.unpacked_dir)
584 self.unpacked_dir = None
585
586
587 def findBuild(self):619 def findBuild(self):
588 """Find and return the SourcePackageRecipeBuild, if one is specified.620 """Find and return the SourcePackageRecipeBuild, if one is specified.
589621
@@ -641,8 +673,8 @@
641673
642 changelog_lfa = self.librarian.create(674 changelog_lfa = self.librarian.create(
643 "changelog",675 "changelog",
644 os.stat(self.changelog_path).st_size,676 len(self.changelog),
645 open(self.changelog_path, "r"),677 StringIO(self.changelog),
646 "text/x-debian-source-changelog",678 "text/x-debian-source-changelog",
647 restricted=self.policy.archive.private)679 restricted=self.policy.archive.private)
648680
@@ -702,6 +734,7 @@
702 validation inside DSCFile.verify(); there is no734 validation inside DSCFile.verify(); there is no
703 store_in_database() method.735 store_in_database() method.
704 """736 """
737
705 def __init__(self, filepath, digest, size, policy, logger):738 def __init__(self, filepath, digest, size, policy, logger):
706 component_and_section = priority = "--no-value--"739 component_and_section = priority = "--no-value--"
707 NascentUploadFile.__init__(740 NascentUploadFile.__init__(
@@ -721,7 +754,7 @@
721754
722 :param source_file: The directory where the source was extracted755 :param source_file: The directory where the source was extracted
723 :param source_dir: The directory where the source was extracted.756 :param source_dir: The directory where the source was extracted.
724 :return fullpath: The full path of the file, else return None if the 757 :return fullpath: The full path of the file, else return None if the
725 file is not found.758 file is not found.
726 """759 """
727 # Instead of trying to predict the unpacked source directory name,760 # Instead of trying to predict the unpacked source directory name,
@@ -744,50 +777,42 @@
744 return fullpath777 return fullpath
745 return None778 return None
746779
747def findCopyright(dsc_file, source_dir, logger):780
781def find_copyright(source_dir, logger):
748 """Find and store any debian/copyright.782 """Find and store any debian/copyright.
749783
750 :param dsc_file: A DSCFile object where the copyright will be stored.
751 :param source_dir: The directory where the source was extracted.784 :param source_dir: The directory where the source was extracted.
752 :param logger: A logger object for debug output.785 :param logger: A logger object for debug output.
786 :return: Contents of copyright file
753 """787 """
754 try:788 copyright_file = findFile(source_dir, 'debian/copyright')
755 copyright_file = findFile(source_dir, 'debian/copyright')
756 except UploadError, error:
757 yield error
758 return
759 if copyright_file is None:789 if copyright_file is None:
760 yield UploadWarning("No copyright file found.")790 raise UploadWarning("No copyright file found.")
761 return
762791
763 logger.debug("Copying copyright contents.")792 logger.debug("Copying copyright contents.")
764 dsc_file.copyright = open(copyright_file).read().strip()793 return open(copyright_file).read().strip()
765794
766795
767def findChangelog(dsc_file, source_dir, logger):796def find_changelog(source_dir, logger):
768 """Find and move any debian/changelog.797 """Find and move any debian/changelog.
769798
770 This function finds the changelog file within the source package. The799 This function finds the changelog file within the source package. The
771 changelog file is later uploaded to the librarian by800 changelog file is later uploaded to the librarian by
772 DSCFile.storeInDatabase().801 DSCFile.storeInDatabase().
773802
774 :param dsc_file: A DSCFile object where the copyright will be stored.
775 :param source_dir: The directory where the source was extracted.803 :param source_dir: The directory where the source was extracted.
776 :param logger: A logger object for debug output.804 :param logger: A logger object for debug output.
805 :return: Changelog contents
777 """806 """
778 try:807 changelog_file = findFile(source_dir, 'debian/changelog')
779 changelog_file = findFile(source_dir, 'debian/changelog')
780 except UploadError, error:
781 yield error
782 return
783 if changelog_file is None:808 if changelog_file is None:
784 # Policy requires debian/changelog to always exist.809 # Policy requires debian/changelog to always exist.
785 yield UploadError("No changelog file found.")810 raise UploadError("No changelog file found.")
786 return
787811
788 # Move the changelog file out of the package direcotry812 # Move the changelog file out of the package direcotry
789 logger.debug("Found changelog")813 logger.debug("Found changelog")
790 dsc_file.changelog_path = changelog_file814 return open(changelog_file, 'r').read()
815
791816
792def check_format_1_0_files(filename, file_type_counts, component_counts,817def check_format_1_0_files(filename, file_type_counts, component_counts,
793 bzip2_count):818 bzip2_count):
794819
=== modified file 'lib/lp/archiveuploader/nascentupload.py'
--- lib/lp/archiveuploader/nascentupload.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/nascentupload.py 2010-08-24 08:53:41 +0000
@@ -893,12 +893,6 @@
893 'Exception while accepting:\n %s' % e, exc_info=True)893 'Exception while accepting:\n %s' % e, exc_info=True)
894 self.do_reject(notify)894 self.do_reject(notify)
895 return False895 return False
896 else:
897 self.cleanUp()
898
899 def cleanUp(self):
900 if self.changes.dsc is not None:
901 self.changes.dsc.cleanUp()
902896
903 def do_reject(self, notify=True):897 def do_reject(self, notify=True):
904 """Reject the current upload given the reason provided."""898 """Reject the current upload given the reason provided."""
@@ -929,7 +923,6 @@
929 self.queue_root.notify(summary_text=self.rejection_message,923 self.queue_root.notify(summary_text=self.rejection_message,
930 changes_file_object=changes_file_object, logger=self.logger)924 changes_file_object=changes_file_object, logger=self.logger)
931 changes_file_object.close()925 changes_file_object.close()
932 self.cleanUp()
933926
934 def _createQueueEntry(self):927 def _createQueueEntry(self):
935 """Return a PackageUpload object."""928 """Return a PackageUpload object."""
936929
=== modified file 'lib/lp/archiveuploader/tests/test_dscfile.py'
--- lib/lp/archiveuploader/tests/test_dscfile.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tests/test_dscfile.py 2010-08-24 08:53:41 +0000
@@ -10,10 +10,12 @@
10from canonical.launchpad.scripts.logger import QuietFakeLogger10from canonical.launchpad.scripts.logger import QuietFakeLogger
11from canonical.testing.layers import LaunchpadZopelessLayer11from canonical.testing.layers import LaunchpadZopelessLayer
12from lp.archiveuploader.dscfile import (12from lp.archiveuploader.dscfile import (
13 cleanup_unpacked_dir,
13 DSCFile,14 DSCFile,
14 findChangelog,15 find_changelog,
15 findCopyright,16 find_copyright,
16 format_to_file_checker_map,17 format_to_file_checker_map,
18 unpack_source,
17 )19 )
18from lp.archiveuploader.nascentuploadfile import UploadError20from lp.archiveuploader.nascentuploadfile import UploadError
19from lp.archiveuploader.tests import (21from lp.archiveuploader.tests import (
@@ -37,9 +39,6 @@
3739
38class TestDscFile(TestCase):40class TestDscFile(TestCase):
3941
40 class MockDSCFile:
41 copyright = None
42
43 def setUp(self):42 def setUp(self):
44 super(TestDscFile, self).setUp()43 super(TestDscFile, self).setUp()
45 self.tmpdir = self.makeTemporaryDirectory()44 self.tmpdir = self.makeTemporaryDirectory()
@@ -47,7 +46,6 @@
47 os.makedirs(self.dir_path)46 os.makedirs(self.dir_path)
48 self.copyright_path = os.path.join(self.dir_path, "copyright")47 self.copyright_path = os.path.join(self.dir_path, "copyright")
49 self.changelog_path = os.path.join(self.dir_path, "changelog")48 self.changelog_path = os.path.join(self.dir_path, "changelog")
50 self.dsc_file = self.MockDSCFile()
5149
52 def testBadDebianCopyright(self):50 def testBadDebianCopyright(self):
53 """Test that a symlink as debian/copyright will fail.51 """Test that a symlink as debian/copyright will fail.
@@ -56,14 +54,10 @@
56 dangling symlink in an attempt to try and access files on the system54 dangling symlink in an attempt to try and access files on the system
57 processing the source packages."""55 processing the source packages."""
58 os.symlink("/etc/passwd", self.copyright_path)56 os.symlink("/etc/passwd", self.copyright_path)
59 errors = list(findCopyright(57 error = self.assertRaises(
60 self.dsc_file, self.tmpdir, mock_logger_quiet))58 UploadError, find_copyright, self.tmpdir, mock_logger_quiet)
61
62 self.assertEqual(len(errors), 1)
63 self.assertIsInstance(errors[0], UploadError)
64 self.assertEqual(59 self.assertEqual(
65 errors[0].args[0],60 error.args[0], "Symbolic link for debian/copyright not allowed")
66 "Symbolic link for debian/copyright not allowed")
6761
68 def testGoodDebianCopyright(self):62 def testGoodDebianCopyright(self):
69 """Test that a proper copyright file will be accepted"""63 """Test that a proper copyright file will be accepted"""
@@ -72,11 +66,8 @@
72 file.write(copyright)66 file.write(copyright)
73 file.close()67 file.close()
7468
75 errors = list(findCopyright(69 self.assertEquals(
76 self.dsc_file, self.tmpdir, mock_logger_quiet))70 copyright, find_copyright(self.tmpdir, mock_logger_quiet))
77
78 self.assertEqual(len(errors), 0)
79 self.assertEqual(self.dsc_file.copyright, copyright)
8071
81 def testBadDebianChangelog(self):72 def testBadDebianChangelog(self):
82 """Test that a symlink as debian/changelog will fail.73 """Test that a symlink as debian/changelog will fail.
@@ -85,14 +76,10 @@
85 dangling symlink in an attempt to try and access files on the system76 dangling symlink in an attempt to try and access files on the system
86 processing the source packages."""77 processing the source packages."""
87 os.symlink("/etc/passwd", self.changelog_path)78 os.symlink("/etc/passwd", self.changelog_path)
88 errors = list(findChangelog(79 error = self.assertRaises(
89 self.dsc_file, self.tmpdir, mock_logger_quiet))80 UploadError, find_changelog, self.tmpdir, mock_logger_quiet)
90
91 self.assertEqual(len(errors), 1)
92 self.assertIsInstance(errors[0], UploadError)
93 self.assertEqual(81 self.assertEqual(
94 errors[0].args[0],82 error.args[0], "Symbolic link for debian/changelog not allowed")
95 "Symbolic link for debian/changelog not allowed")
9683
97 def testGoodDebianChangelog(self):84 def testGoodDebianChangelog(self):
98 """Test that a proper changelog file will be accepted"""85 """Test that a proper changelog file will be accepted"""
@@ -101,12 +88,8 @@
101 file.write(changelog)88 file.write(changelog)
102 file.close()89 file.close()
10390
104 errors = list(findChangelog(91 self.assertEquals(
105 self.dsc_file, self.tmpdir, mock_logger_quiet))92 changelog, find_changelog(self.tmpdir, mock_logger_quiet))
106
107 self.assertEqual(len(errors), 0)
108 self.assertEqual(self.dsc_file.changelog_path,
109 self.changelog_path)
11093
111 def testOversizedFile(self):94 def testOversizedFile(self):
112 """Test that a file larger than 10MiB will fail.95 """Test that a file larger than 10MiB will fail.
@@ -125,13 +108,10 @@
125 file.write(empty_file)108 file.write(empty_file)
126 file.close()109 file.close()
127110
128 errors = list(findChangelog(111 error = self.assertRaises(
129 self.dsc_file, self.tmpdir, mock_logger_quiet))112 UploadError, find_changelog, self.tmpdir, mock_logger_quiet)
130
131 self.assertIsInstance(errors[0], UploadError)
132 self.assertEqual(113 self.assertEqual(
133 errors[0].args[0],114 error.args[0], "debian/changelog file too large, 10MiB max")
134 "debian/changelog file too large, 10MiB max")
135115
136116
137class TestDscFileLibrarian(TestCaseWithFactory):117class TestDscFileLibrarian(TestCaseWithFactory):
@@ -141,6 +121,7 @@
141121
142 def getDscFile(self, name):122 def getDscFile(self, name):
143 dsc_path = datadir(os.path.join('suite', name, name + '.dsc'))123 dsc_path = datadir(os.path.join('suite', name, name + '.dsc'))
124
144 class Changes:125 class Changes:
145 architectures = ['source']126 architectures = ['source']
146 logger = QuietFakeLogger()127 logger = QuietFakeLogger()
@@ -157,10 +138,7 @@
157 os.chmod(tempdir, 0555)138 os.chmod(tempdir, 0555)
158 try:139 try:
159 dsc_file = self.getDscFile('bar_1.0-1')140 dsc_file = self.getDscFile('bar_1.0-1')
160 try:141 list(dsc_file.verify())
161 list(dsc_file.verify())
162 finally:
163 dsc_file.cleanUp()
164 finally:142 finally:
165 os.chmod(tempdir, 0755)143 os.chmod(tempdir, 0755)
166144
@@ -292,3 +270,42 @@
292 # A 3.0 (native) source with component tarballs is invalid.270 # A 3.0 (native) source with component tarballs is invalid.
293 self.assertErrorsForFiles(271 self.assertErrorsForFiles(
294 [self.wrong_files_error], {NATIVE_TARBALL: 1}, {'foo': 1})272 [self.wrong_files_error], {NATIVE_TARBALL: 1}, {'foo': 1})
273
274
275class UnpackedDirTests(TestCase):
276 """Tests for unpack_source and cleanup_unpacked_dir."""
277
278 def test_unpack_source(self):
279 # unpack_source unpacks in a temporary directory and returns the
280 # path.
281 unpacked_dir = unpack_source(
282 datadir(os.path.join('suite', 'bar_1.0-1', 'bar_1.0-1.dsc')))
283 try:
284 self.assertEquals(["bar-1.0"], os.listdir(unpacked_dir))
285 self.assertContentEqual(
286 ["THIS_IS_BAR", "debian"],
287 os.listdir(os.path.join(unpacked_dir, "bar-1.0")))
288 finally:
289 cleanup_unpacked_dir(unpacked_dir)
290
291 def test_cleanup(self):
292 # cleanup_dir removes the temporary directory and all files under it.
293 temp_dir = self.makeTemporaryDirectory()
294 unpacked_dir = os.path.join(temp_dir, "unpacked")
295 os.mkdir(unpacked_dir)
296 os.mkdir(os.path.join(unpacked_dir, "bar_1.0"))
297 cleanup_unpacked_dir(unpacked_dir)
298 self.assertFalse(os.path.exists(unpacked_dir))
299
300 def test_cleanup_invalid_mode(self):
301 # cleanup_dir can remove a directory even if the mode does
302 # not allow it.
303 temp_dir = self.makeTemporaryDirectory()
304 unpacked_dir = os.path.join(temp_dir, "unpacked")
305 os.mkdir(unpacked_dir)
306 bar_path = os.path.join(unpacked_dir, "bar_1.0")
307 os.mkdir(bar_path)
308 os.chmod(bar_path, 0600)
309 os.chmod(unpacked_dir, 0600)
310 cleanup_unpacked_dir(unpacked_dir)
311 self.assertFalse(os.path.exists(unpacked_dir))
295312
=== modified file 'lib/lp/archiveuploader/tests/test_nascentuploadfile.py'
--- lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-08-24 08:53:41 +0000
@@ -169,8 +169,7 @@
169 uploadfile = self.createDSCFile(169 uploadfile = self.createDSCFile(
170 "foo.dsc", dsc, "main/net", "extra", "dulwich", "0.42",170 "foo.dsc", dsc, "main/net", "extra", "dulwich", "0.42",
171 self.createChangesFile("foo.changes", changes))171 self.createChangesFile("foo.changes", changes))
172 (uploadfile.changelog_path, changelog_digest, changelog_size) = (172 uploadfile.changelog = "DUMMY"
173 self.writeUploadFile("changelog", "DUMMY"))
174 uploadfile.files = []173 uploadfile.files = []
175 release = uploadfile.storeInDatabase(None)174 release = uploadfile.storeInDatabase(None)
176 self.assertEquals("0.42", release.version)175 self.assertEquals("0.42", release.version)