ubuntutools.archive: Don't write .dsc files until we pull the entire

source package, just hold it in memory. Avoids littering the current
directory (LP: #838361)
This commit is contained in:
Stefano Rivera 2011-09-04 19:01:01 +02:00
parent 0d4c692262
commit 17b287e7bf
3 changed files with 50 additions and 37 deletions

3
debian/changelog vendored
View File

@ -21,6 +21,9 @@ ubuntu-dev-tools (0.129) UNRELEASED; urgency=low
native syncs. (Bugs are closed one individually, via the API, post-sync) native syncs. (Bugs are closed one individually, via the API, post-sync)
* dgetlp, submittodebian, 404main: Use unicode strings for literal strings * dgetlp, submittodebian, 404main: Use unicode strings for literal strings
containing non-ASCII characters (LP: #836661) containing non-ASCII characters (LP: #836661)
* ubuntutools.archive: Don't write .dsc files until we pull the entire
source package, just hold it in memory. Avoids littering the current
directory (LP: #838361)
-- Stefano Rivera <stefanor@debian.org> Sat, 03 Sep 2011 21:04:38 +0200 -- Stefano Rivera <stefanor@debian.org> Sat, 03 Sep 2011 21:04:38 +0200

View File

@ -201,9 +201,8 @@ class SourcePackage(object):
@property @property
def dsc(self): def dsc(self):
"Return a the Dsc" "Return a the Dsc"
if not self._dsc: if self._dsc is None:
if self._dsc_fetched: self.pull_dsc()
self._dsc = Dsc(file(self.dsc_pathname, 'rb').read())
return self._dsc return self._dsc
def _mirror_url(self, mirror, filename): def _mirror_url(self, mirror, filename):
@ -238,34 +237,35 @@ class SourcePackage(object):
if parsed.scheme == '': if parsed.scheme == '':
self._dsc_source = 'file://' + os.path.abspath(self._dsc_source) self._dsc_source = 'file://' + os.path.abspath(self._dsc_source)
parsed = urlparse.urlparse(self._dsc_source) parsed = urlparse.urlparse(self._dsc_source)
url = self._dsc_source
source_is_workdir = (os.path.realpath(os.path.dirname(parsed.path))
== os.path.realpath(self.workdir))
if parsed.scheme == 'file' and source_is_workdir:
# Temporarily rename to the filename we are going to open
os.rename(parsed.path, self.dsc_pathname)
else:
if not self._download_file(self._dsc_source, self.dsc_name):
raise DownloadError('dsc not found')
else: else:
if not self._download_file(self._lp_url(self.dsc_name), url = self._lp_url(self.dsc_name)
self.dsc_name): self._download_dsc(url)
raise DownloadError('dsc not found')
self._check_dsc() self._check_dsc()
def _download_dsc(self, url):
"Download specified dscfile and parse"
# Launchpad will try to redirect us to plain-http Launchpad Librarian,
# but we want SSL when fetching the dsc
if url.startswith('https') and url.endswith('.dsc'):
opener = urllib2.build_opener(ForceHTTPSRedirectHandler())
else:
opener = urllib2.build_opener()
try:
f = opener.open(url)
self._dsc = Dsc(f.read())
f.close()
except urllib2.URLError:
raise DownloadError('dsc not found')
self._dsc_fetched = True
def _check_dsc(self, verify_signature=False): def _check_dsc(self, verify_signature=False):
"Check that the dsc matches what we are expecting" "Check that the dsc matches what we are expecting"
assert os.path.exists(self.dsc_pathname) assert self._dsc is not None
self._dsc_fetched = True
old_pathname = self.dsc_pathname
self.source = self.dsc['Source'] self.source = self.dsc['Source']
self.version = debian.debian_support.Version(self.dsc['Version']) self.version = debian.debian_support.Version(self.dsc['Version'])
# If source or version was previously unknown
if self.dsc_pathname != old_pathname:
os.rename(old_pathname, self.dsc_pathname)
valid = False valid = False
message = None message = None
gpg_info = None gpg_info = None
@ -296,13 +296,20 @@ class SourcePackage(object):
else: else:
Logger.info(message) Logger.info(message)
def _write_dsc(self):
"Write dsc file to workdir"
if self._dsc is None:
self.pull_dsc()
with open(self.dsc_pathname, 'w') as f:
f.write(self.dsc.raw_text)
def _download_file(self, url, filename): def _download_file(self, url, filename):
"Download url to filename in workdir." "Download url to filename in workdir."
logurl = url logurl = url
if os.path.basename(url) != filename: if os.path.basename(url) != filename:
logurl += ' -> ' + filename logurl += ' -> ' + filename
pathname = os.path.join(self.workdir, filename) pathname = os.path.join(self.workdir, filename)
if self.dsc and not url.endswith('.dsc'): if self.dsc:
if self.dsc.verify_file(pathname): if self.dsc.verify_file(pathname):
Logger.debug('Using existing %s', filename) Logger.debug('Using existing %s', filename)
return True return True
@ -315,15 +322,8 @@ class SourcePackage(object):
else: else:
Logger.normal('Downloading %s', logurl) Logger.normal('Downloading %s', logurl)
# Launchpad will try to redirect us to plain-http Launchpad Librarian,
# but we want SSL when fetching the dsc
if url.startswith('https') and url.endswith('.dsc'):
opener = urllib2.build_opener(ForceHTTPSRedirectHandler())
else:
opener = urllib2.build_opener()
try: try:
in_ = opener.open(url) in_ = urllib2.build_opener().open(url)
except urllib2.URLError: except urllib2.URLError:
return False return False
@ -338,7 +338,7 @@ class SourcePackage(object):
in_.close() in_.close()
Logger.stdout.write(' done\n') Logger.stdout.write(' done\n')
Logger.stdout.flush() Logger.stdout.flush()
if self.dsc and not url.endswith('.dsc'): if self.dsc:
if not self.dsc.verify_file(pathname): if not self.dsc.verify_file(pathname):
Logger.error('Checksum does not match.') Logger.error('Checksum does not match.')
return False return False
@ -346,8 +346,7 @@ class SourcePackage(object):
def pull(self): def pull(self):
"Pull into workdir" "Pull into workdir"
if self.dsc is None: self._write_dsc()
self.pull_dsc()
for entry in self.dsc['Files']: for entry in self.dsc['Files']:
name = entry['name'] name = entry['name']
for url in self._source_urls(name): for url in self._source_urls(name):
@ -467,8 +466,11 @@ class DebianSourcePackage(SourcePackage):
# Not all Debian Source packages get imported to LP # Not all Debian Source packages get imported to LP
# (or the importer could be lagging) # (or the importer could be lagging)
for url in self._source_urls(self.dsc_name): for url in self._source_urls(self.dsc_name):
if self._download_file(url, self.dsc_name): try:
break self._download_dsc(url)
except DownloadError:
continue
break
else: else:
raise DownloadError('dsc could not be found anywhere') raise DownloadError('dsc could not be found anywhere')
self._check_dsc(verify_signature=True) self._check_dsc(verify_signature=True)

View File

@ -145,6 +145,10 @@ class LocalSourcePackageTestCase(mox.MoxTestBase, unittest.TestCase):
shutil.copy2('test-data/example_1.0-1.dsc', self.workdir) shutil.copy2('test-data/example_1.0-1.dsc', self.workdir)
shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir) shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir)
shutil.copy2('test-data/example_1.0-1.debian.tar.gz', self.workdir) shutil.copy2('test-data/example_1.0-1.debian.tar.gz', self.workdir)
urllib2.build_opener().MultipleTimes().AndReturn(self.mock_opener)
self.mock_opener.open(mox.Regex('^file://.*\.dsc$')
).WithSideEffects(self.real_opener.open)
self.mox.ReplayAll() self.mox.ReplayAll()
pkg = self.SourcePackage(dscfile=os.path.join(self.workdir, pkg = self.SourcePackage(dscfile=os.path.join(self.workdir,
'example_1.0-1.dsc'), 'example_1.0-1.dsc'),
@ -156,6 +160,10 @@ class LocalSourcePackageTestCase(mox.MoxTestBase, unittest.TestCase):
shutil.copy2('test-data/example_1.0-1.dsc', self.workdir) shutil.copy2('test-data/example_1.0-1.dsc', self.workdir)
shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir) shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir)
shutil.copy2('test-data/example_1.0-1.debian.tar.gz', self.workdir) shutil.copy2('test-data/example_1.0-1.debian.tar.gz', self.workdir)
urllib2.build_opener().MultipleTimes().AndReturn(self.mock_opener)
self.mock_opener.open(mox.Regex('^file://.*\.dsc$')
).WithSideEffects(self.real_opener.open)
self.mox.ReplayAll() self.mox.ReplayAll()
pkg = self.SourcePackage('example', '1.0-1', 'main', pkg = self.SourcePackage('example', '1.0-1', 'main',
dscfile=os.path.join(self.workdir, dscfile=os.path.join(self.workdir,