Merge lp:~jml/pkgme/remove-binary-backend into lp:pkgme

Proposed by Jonathan Lange
Status: Merged
Approved by: James Westby
Approved revision: 76
Merged at revision: 75
Proposed branch: lp:~jml/pkgme/remove-binary-backend
Merge into: lp:pkgme
Diff against target: 857 lines (+0/-800)
9 files modified
pkgme/backends/binary/build_depends (+0/-14)
pkgme/backends/binary/depends (+0/-11)
pkgme/backends/binary/extra_files (+0/-36)
pkgme/backends/binary/package_name (+0/-17)
pkgme/backends/binary/want (+0/-15)
pkgme/binary.py (+0/-249)
pkgme/tests/__init__.py (+0/-2)
pkgme/tests/test_binary.py (+0/-339)
pkgme/tests/test_binary_backend.py (+0/-117)
To merge this branch: bzr merge lp:~jml/pkgme/remove-binary-backend
Reviewer Review Type Date Requested Status
James Westby Approve
Review via email: mp+71023@code.launchpad.net

Description of the change

This branch removes the binary backend from pkgme.

There are several reasons why this is a good idea, or at least, not a bad one.

 * As it stands in trunk, the binary backend needs a devportal-metadata.json – hardly generic
 * As it stands in lp:~jml/pkgme/improve-auto-depends, it also needs a 1.5 GB database. Any functioning implementation will need a database of similar size, or access to an external service that provides such a database
 * pkgme allows for third-party backends, so why not use that

To post a comment you must log in.
lp:~jml/pkgme/remove-binary-backend updated
76. By Jonathan Lange

Remove data files.

Revision history for this message
James Westby (james-w) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed directory 'pkgme/backends/binary'
=== removed file 'pkgme/backends/binary/build_depends'
--- pkgme/backends/binary/build_depends 2011-07-18 11:08:14 +0000
+++ pkgme/backends/binary/build_depends 1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
1#!/usr/bin/python
2
3import os
4
5from pkgme.binary import guess_dependencies
6
7
8def main():
9 path = os.getcwd()
10 print ', '.join(guess_dependencies(path))
11
12
13if __name__ == '__main__':
14 main()
150
=== removed file 'pkgme/backends/binary/depends'
--- pkgme/backends/binary/depends 2011-07-18 11:08:14 +0000
+++ pkgme/backends/binary/depends 1970-01-01 00:00:00 +0000
@@ -1,11 +0,0 @@
1#!/usr/bin/python
2
3from pkgme.binary import DEPENDS
4
5
6def main():
7 print DEPENDS
8
9
10if __name__ == '__main__':
11 main()
120
=== removed file 'pkgme/backends/binary/extra_files'
--- pkgme/backends/binary/extra_files 2011-07-18 11:08:14 +0000
+++ pkgme/backends/binary/extra_files 1970-01-01 00:00:00 +0000
@@ -1,36 +0,0 @@
1#!/usr/bin/python
2
3import json
4import os
5import sys
6
7from pkgme.binary import (
8 CATEGORIES,
9 get_desktop_file,
10 get_install_file,
11 METADATA_FILE,
12 PACKAGE_NAME,
13 TAGLINE,
14 )
15
16
17def main():
18 with open(METADATA_FILE) as f:
19 metadata = json.load(f)
20 package_name = metadata[PACKAGE_NAME]
21 path = os.getcwd()
22 install_file = get_install_file(package_name, path, True)
23 desktop_file = get_desktop_file(
24 package_name, path,
25 tagline=metadata.get(TAGLINE, ''),
26 categories=metadata.get(CATEGORIES, ''))
27 json.dump(
28 {
29 # XXX: Hardcoded literal attack!
30 'debian/install': install_file,
31 'debian/%s.desktop' % (package_name,): desktop_file.get_contents(),
32 }, sys.stdout)
33
34
35if __name__ == '__main__':
36 main()
370
=== removed file 'pkgme/backends/binary/package_name'
--- pkgme/backends/binary/package_name 2011-07-18 11:08:14 +0000
+++ pkgme/backends/binary/package_name 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
1#!/usr/bin/python
2
3import json
4from pkgme.binary import (
5 METADATA_FILE,
6 PACKAGE_NAME,
7 )
8
9
10def main():
11 with open(METADATA_FILE) as f:
12 metadata = json.load(f)
13 print metadata[PACKAGE_NAME]
14
15
16if __name__ == '__main__':
17 main()
180
=== removed file 'pkgme/backends/binary/want'
--- pkgme/backends/binary/want 2011-07-13 13:18:03 +0000
+++ pkgme/backends/binary/want 1970-01-01 00:00:00 +0000
@@ -1,15 +0,0 @@
1#!/usr/bin/python
2
3import os
4
5from pkgme.binary import METADATA_FILE
6
7def main():
8 if os.path.exists(METADATA_FILE):
9 print 10
10 else:
11 print 0
12
13
14if __name__ == '__main__':
15 main()
160
=== removed file 'pkgme/binary.py'
--- pkgme/binary.py 2011-07-15 16:30:18 +0000
+++ pkgme/binary.py 1970-01-01 00:00:00 +0000
@@ -1,249 +0,0 @@
1"""Things to help package binary tarballs.
2
3HIGHLY EXPERIMENTAL. USE AT YOUR OWN PERIL.
4
5At the moment, we are assuming a great many things about these binary
6tarballs.
7
8* That they represent some sort of application to be run from an Ubuntu
9 desktop
10
11* Specifically, that although they might have many executables, only one is
12 the "main executable" mentioned in the 'desktop' file
13
14* They are written in C or C++ and that all dependencies can be determined
15 by inspecting the included object files
16
17* That the entire contents of the tarball can be copied into
18 /opt/<package-name> and run from there
19
20* That we have a metadata file, called 'devportal-metadata.json', in JSON,
21 that specifies:
22 * package_name
23
24The expectation is that this metadata file is generated from the developer
25portal.
26"""
27
28# XXX: No idea about architecture
29
30__all__ = [
31 'get_install_file',
32 'guess_executable',
33 'iter_executables',
34 'METADATA_FILE',
35 ]
36
37
38import os
39import subprocess
40
41from pkgme.info_elements import (
42 ApplicationName,
43 Categories,
44 Executable,
45 PackageName,
46 TagLine,
47 )
48from pkgme.package_files import (
49 DEBIAN_DIR,
50 Desktop,
51 )
52from pkgme.project_info import DictInfo
53
54
55METADATA_FILE = 'devportal-metadata.json'
56
57# Keys found in the metadata file.
58CATEGORIES = 'categories'
59# It's called package_name in the database, so this probably makes sense.
60PACKAGE_NAME = 'package_name'
61TAGLINE = 'tagline'
62
63
64# Always depend on these.
65#
66# XXX: jml just doing this because iamfuzz does. Need to either experiment or
67# consult expert.
68DEPENDS = '${shlibs:Depends}, ${misc:Depends}'
69
70# XXX: No idea about how icons will be there. Ignoring for now.
71
72def guess_executable(package_name, executables):
73 """
74 From a list of executables, guess which one is likely to be the main
75 executable.
76 """
77
78 # The lower the score, the more likely it is to be the right executable.
79
80 def score_name(name):
81 # Names that match exactly are good.
82 return -int(name.lower() == package_name.lower())
83
84 def score_path(executable):
85 # The deeper the path, the less likely it is to be the one.
86 return executable.count('/')
87
88 def rank(executable):
89 name = os.path.basename(executable)
90 # The alpha-sorting of the base name is a tie-breaker.
91 return score_name(name), score_path(executable), name
92
93 try:
94 return sorted(executables, key=rank)[0]
95 except IndexError:
96 return None
97
98
99def iter_executables(path):
100 """Iterate through all executable files under 'path'.
101
102 Paths yielded will be relative to 'path'. Directories will *not* be
103 yielded. "Executable" is determined by filesystem permissions.
104 """
105 for root, dirs, files in os.walk(path):
106 for filename in files:
107 file_path = os.path.join(root, filename)
108 if os.access(file_path, os.X_OK):
109 yield os.path.relpath(file_path, path)
110
111
112def get_install_file(package_name, path, include_desktop=False):
113 """Generate the install file for 'package_name'."""
114 lines = []
115 # Sorting not actually needed for functionality, but makes the tests more
116 # reliable.
117 for filename in sorted(os.listdir(path)):
118 if filename in (DEBIAN_DIR, METADATA_FILE):
119 # We don't want to install the 'debian/' directory or the metadata
120 # file.
121 continue
122 lines.append('%s opt/%s' % (filename, package_name))
123 if include_desktop:
124 lines.append(
125 'debian/%s.desktop usr/share/application' % (package_name,))
126 # Ending the file with a newline is basic good manners.
127 lines.append('')
128 return '\n'.join(lines)
129
130
131def get_desktop_file(package_name, path, tagline=None, categories=None):
132 executable = guess_executable(package_name, iter_executables(path))
133 info = {
134 PackageName.name: package_name,
135 ApplicationName.name: package_name.capitalize(),
136 Executable.name: '/opt/%s/%s' % (package_name, executable),
137 TagLine.name: tagline,
138 Categories.name: categories,
139 }
140 return Desktop.from_info(DictInfo(info))
141
142
143def get_file_type(path):
144 return get_file_types([path])[0]
145
146
147def get_file_types(paths):
148 paths = list(paths)
149 if not paths:
150 return []
151 cmd = ['file', '-b'] + paths
152 return subprocess.Popen(
153 cmd, stdout=subprocess.PIPE).communicate()[0].splitlines()
154
155
156def ldd(binary_paths):
157 # ldd has output of the form:
158 #
159 # path/to/elf/object:
160 # linux-vdso.so.1 => (0x00007fff4a7ff000)
161 # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7472623000)
162 # /lib64/ld-linux-x86-64.so.2 (0x00007f74729e5000)
163 #
164 # i.e.
165 # <name> => <path> (<address>)
166 #
167 # where <name> and <path> are both optional. If <name> is not given, then
168 # there is no arrow (=>).
169 binary_paths = list(binary_paths)
170 if not binary_paths:
171 return {}
172 cmd = ['ldd'] + binary_paths
173 output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
174 libraries = {}
175 current = []
176 if len(binary_paths) == 1:
177 libraries[binary_paths[0]] = current
178 for line in output.splitlines():
179 if line.endswith(':'):
180 current.sort()
181 current = libraries[line.strip(':')] = []
182 continue
183 # Last token is always irrelevant hex address.
184 tokens = line.split()[:-1]
185 name, path = None, None
186 if '=>' in tokens:
187 name = tokens[0]
188 if len(tokens) > 2:
189 path = tokens[2]
190 else:
191 path = tokens[0]
192 current.append((name, path))
193 current.sort()
194 return libraries
195
196
197def get_shared_library_dependencies(paths):
198 # XXX: Not sure which of these is more useful. Specifically, if the
199 # library isn't installed on the system, then I don't know whether it will
200 # appear in ldd as the library_path. -- jml
201 libraries = ldd(paths)
202 for libs in libraries.values():
203 for name, library_path in libs:
204 if library_path:
205 yield library_path
206
207
208def find_shared_library_dependencies(path):
209 return set(get_shared_library_dependencies(iter_binaries(path)))
210
211
212def iter_binaries(path):
213
214 def is_binary(file_type):
215 return file_type.startswith('ELF')
216
217 for root, dirs, files in os.walk(path):
218 paths = [os.path.join(root, filename) for filename in files]
219 types = get_file_types(paths)
220 for file_path, file_type in zip(paths, types):
221 if is_binary(file_type):
222 yield file_path
223
224
225def apt_file(filename):
226 # XXX: Assumes apt-file update has been run.
227
228 # XXX: Passing the full file name since it seems the least likely to yield
229 # multiple dependencies. If 'get_shared_library_dependencies' ought to
230 # return just the names, then this will have to change to be a regex, and
231 # we'll need to think about ambiguity resolution much sooner.
232 # cmd = ['apt-file', 'find', '-x', '/%s$' % (filename,)]
233
234 # XXX: Currently matching badly due to architecture.
235 cmd = ['apt-file', 'find', '-F', filename]
236 output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
237 for line in output.splitlines():
238 yield line.split(': ')[0]
239
240
241def guess_dependencies(path):
242 deps = set()
243 # XXX: ldd probably is recursive. This means it finds *all* the libraries
244 # that are needed. However, we only need to specify the top-level
245 # libraries (e.g. libc6 should almost never be a dependency).
246 for library in find_shared_library_dependencies(path):
247 for dep in apt_file(library):
248 deps.add(dep)
249 return deps
2500
=== modified file 'pkgme/tests/__init__.py'
--- pkgme/tests/__init__.py 2011-08-01 16:48:11 +0000
+++ pkgme/tests/__init__.py 2011-08-10 12:24:37 +0000
@@ -7,8 +7,6 @@
7def test_suite():7def test_suite():
8 module_names = [8 module_names = [
9 'pkgme.tests.test_backend',9 'pkgme.tests.test_backend',
10 'pkgme.tests.test_binary',
11 'pkgme.tests.test_binary_backend',
12 'pkgme.tests.test_distutils_command',10 'pkgme.tests.test_distutils_command',
13 'pkgme.tests.test_info_elements',11 'pkgme.tests.test_info_elements',
14 'pkgme.tests.test_package_files',12 'pkgme.tests.test_package_files',
1513
=== removed file 'pkgme/tests/foo.data'
16Binary files pkgme/tests/foo.data 2011-07-15 16:26:43 +0000 and pkgme/tests/foo.data 1970-01-01 00:00:00 +0000 differ14Binary files pkgme/tests/foo.data 2011-07-15 16:26:43 +0000 and pkgme/tests/foo.data 1970-01-01 00:00:00 +0000 differ
=== removed file 'pkgme/tests/hello'
17Binary files pkgme/tests/hello 2011-07-15 09:49:16 +0000 and pkgme/tests/hello 1970-01-01 00:00:00 +0000 differ15Binary files pkgme/tests/hello 2011-07-15 09:49:16 +0000 and pkgme/tests/hello 1970-01-01 00:00:00 +0000 differ
=== removed file 'pkgme/tests/simple.so.1'
18Binary files pkgme/tests/simple.so.1 2011-07-15 09:49:16 +0000 and pkgme/tests/simple.so.1 1970-01-01 00:00:00 +0000 differ16Binary files pkgme/tests/simple.so.1 2011-07-15 09:49:16 +0000 and pkgme/tests/simple.so.1 1970-01-01 00:00:00 +0000 differ
=== removed file 'pkgme/tests/test_binary.py'
--- pkgme/tests/test_binary.py 2011-07-15 16:30:18 +0000
+++ pkgme/tests/test_binary.py 1970-01-01 00:00:00 +0000
@@ -1,339 +0,0 @@
1import os
2
3from fixtures import TestWithFixtures
4from testtools import TestCase
5from testtools.matchers import StartsWith
6
7from pkgme.binary import (
8 apt_file,
9 find_shared_library_dependencies,
10 get_desktop_file,
11 get_file_type,
12 get_file_types,
13 get_install_file,
14 get_shared_library_dependencies,
15 guess_dependencies,
16 guess_executable,
17 iter_binaries,
18 iter_executables,
19 ldd,
20 METADATA_FILE,
21 )
22from pkgme.package_files import DEBIAN_DIR
23from pkgme.testing import (
24 AreDesktopValuesFor,
25 TempdirFixture,
26 )
27
28
29class BinaryTests(TestCase, TestWithFixtures):
30
31 def test_metadata_file(self):
32 self.assertEqual('devportal-metadata.json', METADATA_FILE)
33
34
35class InstallFileTests(TestCase, TestWithFixtures):
36
37 def test_install_file(self):
38 # The install file instructs debhelper to copy everything in the
39 # top-level to /opt/<package-name>.
40 tempdir = self.useFixture(TempdirFixture())
41 tempdir.touch('some-file')
42 install_file = get_install_file('package-name', tempdir.path)
43 self.assertEqual("some-file opt/package-name\n", install_file)
44
45 def test_install_file_many_files_and_directories(self):
46 # The install file instructs debhelper to copy everything in the
47 # top-level to /opt/<package-name>.
48 tempdir = self.useFixture(TempdirFixture())
49 tempdir.touch('some-file')
50 tempdir.mkdir('directory')
51 install_file = get_install_file('package-name', tempdir.path)
52 self.assertEqual(
53 "directory opt/package-name\n"
54 "some-file opt/package-name\n",
55 install_file)
56
57 def test_skip_debian(self):
58 # The install file instructs debhelper to copy everything in the
59 # top-level to /opt/<package-name>, except for the 'debian' directory.
60 tempdir = self.useFixture(TempdirFixture())
61 tempdir.touch('some-file')
62 tempdir.mkdir('directory')
63 tempdir.mkdir(DEBIAN_DIR)
64 install_file = get_install_file('package-name', tempdir.path)
65 self.assertEqual(
66 "directory opt/package-name\n"
67 "some-file opt/package-name\n",
68 install_file)
69
70 def test_skip_metadata(self):
71 # The install file instructs debhelper to copy everything in the
72 # top-level to /opt/<package-name>, except for the 'debian' directory
73 # and the metadata file.
74 tempdir = self.useFixture(TempdirFixture())
75 tempdir.touch('some-file')
76 tempdir.mkdir('directory')
77 tempdir.touch(METADATA_FILE)
78 install_file = get_install_file('package-name', tempdir.path)
79 self.assertEqual(
80 "directory opt/package-name\n"
81 "some-file opt/package-name\n",
82 install_file)
83
84 def test_include_desktop_file(self):
85 tempdir = self.useFixture(TempdirFixture())
86 tempdir.touch('some-file')
87 install_file = get_install_file(
88 'package-name', tempdir.path, include_desktop=True)
89 self.assertEqual(
90 "some-file opt/package-name\n"
91 "debian/package-name.desktop usr/share/application\n",
92 install_file)
93
94
95class DesktopFileTests(TestCase):
96
97 def test_executable_is_best_guess(self):
98 package_name = self.getUniqueString()
99 tempdir = self.useFixture(TempdirFixture())
100 tempdir.mkdir('whatever')
101 tempdir.touch('whatever/not-the-best', 0755)
102 tempdir.touch('the-best', 0755)
103 desktop_file = get_desktop_file(package_name, tempdir.path)
104 self.assertThat(
105 {'Exec': '/opt/%s/the-best' % (package_name,)},
106 AreDesktopValuesFor(desktop_file))
107
108 def test_app_name_is_capitalized_package_name(self):
109 # We don't have any information on the package name, so try to guess
110 # the application name.
111 tempdir = self.useFixture(TempdirFixture())
112 package_name = self.getUniqueString()
113 desktop_file = get_desktop_file(package_name, tempdir.path)
114 self.assertThat(
115 {'Name': package_name.capitalize()},
116 AreDesktopValuesFor(desktop_file))
117
118 def test_category_and_tagline_are_specified(self):
119 # We just pass the category and comment through.
120 tempdir = self.useFixture(TempdirFixture())
121 package_name = self.getUniqueString()
122 tagline = self.getUniqueString()
123 categories = self.getUniqueString()
124 desktop_file = get_desktop_file(
125 package_name, tempdir.path, tagline=tagline, categories=categories)
126 self.assertThat(
127 {'Comment': tagline, 'Categories': categories},
128 AreDesktopValuesFor(desktop_file))
129
130
131class FindExecutableTests(TestCase, TestWithFixtures):
132
133 def test_only_one_file_and_it_is_executable(self):
134 # If there is only one file and it's executable, find that.
135 tempdir = self.useFixture(TempdirFixture())
136 tempdir.touch('some-file', mode=0755)
137 executables = list(iter_executables(tempdir.path))
138 self.assertEqual(['some-file'], executables)
139
140 def test_no_files_at_all(self):
141 # iter_executables finds no executables if there are no files at all.
142 tempdir = self.useFixture(TempdirFixture())
143 executables = list(iter_executables(tempdir.path))
144 self.assertEqual([], executables)
145
146 def test_no_executable_files(self):
147 # If there are no executable files, iter_executables returns None.
148 tempdir = self.useFixture(TempdirFixture())
149 tempdir.touch('some-file', mode=0644)
150 executables = list(iter_executables(tempdir.path))
151 self.assertEqual([], executables)
152
153 def test_directory_is_not_executable_file(self):
154 # A directory does not count as an executable file.
155 tempdir = self.useFixture(TempdirFixture())
156 tempdir.mkdir('directory')
157 executables = list(iter_executables(tempdir.path))
158 self.assertEqual([], executables)
159
160 def test_finds_executable_in_nested_directory(self):
161 # Even if the file is in some nested directory, we are able to find
162 # it.
163 tempdir = self.useFixture(TempdirFixture())
164 tempdir.mkdir('directory')
165 tempdir.touch('directory/my-executable', mode=0755)
166 executables = list(iter_executables(tempdir.path))
167 self.assertEqual(['directory/my-executable'], executables)
168
169 def test_multiple_executables(self):
170 # If there are many executables, iter_executables finds them all.
171 tempdir = self.useFixture(TempdirFixture())
172 tempdir.touch('some-file', mode=0755)
173 tempdir.touch('another-file', mode=0755)
174 executables = sorted(list(iter_executables(tempdir.path)))
175 self.assertEqual(['another-file', 'some-file'], executables)
176
177
178class GuessExecutableTests(TestCase):
179
180 def test_no_executables(self):
181 # If there are no executables to select from, then return None,
182 # indicating the fact.
183 executable = guess_executable('package-name', iter([]))
184 self.assertIs(None, executable)
185
186 def test_only_one_executable(self):
187 # If there's only one executable, then return that, since it's
188 # probably the main executable for the package.
189 executable = guess_executable('package-name', ['whatever'])
190 self.assertEqual('whatever', executable)
191
192 def test_exact_package_name_match(self):
193 # If there are many executables, but one of them has the same name as
194 # the package, then that is probably the main executable.
195 executable = guess_executable(
196 'package-name', ['whatever', 'package-name'])
197 self.assertEqual('package-name', executable)
198
199 def test_exact_package_name_match_in_subdir(self):
200 # If there are many executables, but one of them has the same name as
201 # the package, then that is probably the main executable, even if it
202 # is in a sub-directory.
203 executable = guess_executable(
204 'package-name', ['whatever', 'subdir/package-name', 'foo'])
205 self.assertEqual('subdir/package-name', executable)
206
207 def test_multiple_exact_matches(self):
208 # If there are many executables that have the same name as the
209 # package, then the one that is the least nested is our best guess.
210 executable = guess_executable(
211 'package-name', [
212 'whatever', 'a/b/c/d/e/subdir/package-name', 'foo',
213 'subdir/package-name'])
214 self.assertEqual('subdir/package-name', executable)
215
216 def test_different_case_match(self):
217 # If one of the executables has the same name as the package, but
218 # spelled with different case, then that is our best guess.
219 executable = guess_executable(
220 'packagename', [
221 'whatever', 'a/b/c/d/e/subdir/packagename', 'foo',
222 'subdir/PackageName'])
223 self.assertEqual('subdir/PackageName', executable)
224
225 def test_many_executables(self):
226 # If there are many executables, and their names have no particular
227 # relationship to the package name, then just pick the top-most
228 # one. If there's more than one, take the alphabetically sorted.
229 executable = guess_executable(
230 'package-name', ['dir/x', 'dir/sub/y', 'z', 'a'])
231 self.assertEqual('a', executable)
232
233
234class GetFileTypeTests(TestCase):
235
236 def test_plain_text(self):
237 tempdir = self.useFixture(TempdirFixture())
238 tempdir.create_file('foo.txt', 'boring content\n')
239 file_type = get_file_type(tempdir.abspath('foo.txt'))
240 self.assertEqual('ASCII text', file_type)
241
242 def test_data(self):
243 file_type = get_file_type(
244 os.path.join(os.path.dirname(__file__), 'foo.data'))
245 self.assertEqual('data', file_type)
246
247 def test_elf_binary(self):
248 binary_path = os.path.join(os.path.dirname(__file__), 'hello')
249 file_type = get_file_type(binary_path)
250 self.assertThat(file_type, StartsWith('ELF'))
251
252 def test_elf_library(self):
253 binary_path = os.path.join(os.path.dirname(__file__), 'simple.so.1')
254 file_type = get_file_type(binary_path)
255 self.assertThat(file_type, StartsWith('ELF'))
256
257 def test_multiple(self):
258 tempdir = self.useFixture(TempdirFixture())
259 tempdir.create_file('foo.txt', 'boring content\n')
260 file_types = get_file_types(
261 [tempdir.abspath('foo.txt'),
262 os.path.join(os.path.dirname(__file__), 'foo.data')])
263 self.assertEqual(['ASCII text', 'data'], file_types)
264
265 def test_no_files_given(self):
266 self.assertEqual([], get_file_types([]))
267 self.assertEqual([], get_file_types(iter([])))
268
269
270class IterBinariesTests(TestCase):
271
272 def test_no_binaries(self):
273 tempdir = self.useFixture(TempdirFixture())
274 self.assertEqual([], list(iter_binaries(tempdir.path)))
275
276 def test_some_binaries(self):
277 path = os.path.dirname(os.path.dirname(__file__))
278 binaries = sorted(iter_binaries(path))
279 self.assertEqual(
280 [os.path.join(os.path.dirname(__file__), 'hello'),
281 os.path.join(os.path.dirname(__file__), 'simple.so.1')],
282 binaries)
283
284
285class GetSharedLibraryDependenciesTests(TestCase):
286
287 def test_ldd_none(self):
288 deps = ldd([])
289 self.assertEqual({}, deps)
290
291 def test_ldd(self):
292 hello = os.path.join(os.path.dirname(__file__), 'hello')
293 deps = ldd([hello])
294 self.assertEqual(
295 {hello: [(None, '/lib64/ld-linux-x86-64.so.2'),
296 ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'),
297 ('linux-vdso.so.1', None)]},
298 deps)
299
300 def test_ldd_multiple(self):
301 hello = os.path.join(os.path.dirname(__file__), 'hello')
302 simple = os.path.join(os.path.dirname(__file__), 'simple.so.1')
303 deps = ldd([hello, simple])
304 self.assertEqual(
305 {hello: [(None, '/lib64/ld-linux-x86-64.so.2'),
306 ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'),
307 ('linux-vdso.so.1', None)],
308 simple: [(None, '/lib64/ld-linux-x86-64.so.2'),
309 ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'),
310 ('linux-vdso.so.1', None)]},
311 deps)
312
313 def test_get_shared_library_dependencies(self):
314 hello = os.path.join(os.path.dirname(__file__), 'hello')
315 deps = sorted(get_shared_library_dependencies([hello]))
316 self.assertEqual(
317 ['/lib/x86_64-linux-gnu/libc.so.6',
318 '/lib64/ld-linux-x86-64.so.2',
319 ], deps)
320
321 def test_find_shared_library_dependencies(self):
322 deps = find_shared_library_dependencies(os.path.dirname(__file__))
323 self.assertEqual(
324 set(['/lib/x86_64-linux-gnu/libc.so.6',
325 '/lib64/ld-linux-x86-64.so.2']), deps)
326
327
328class AptFileTests(TestCase):
329
330 def test_full_file(self):
331 packages = list(apt_file('/usr/lib32/libasound.so.2'))
332 self.assertEqual(['lib32asound2'], packages)
333
334
335class GuessDependenciesTests(TestCase):
336
337 def test_guess_dependencies(self):
338 deps = guess_dependencies(os.path.dirname(__file__))
339 self.assertEqual(set(['libc6']), deps)
3400
=== removed file 'pkgme/tests/test_binary_backend.py'
--- pkgme/tests/test_binary_backend.py 2011-07-18 11:08:14 +0000
+++ pkgme/tests/test_binary_backend.py 1970-01-01 00:00:00 +0000
@@ -1,117 +0,0 @@
1import json
2import os
3import shutil
4
5from fixtures import TestWithFixtures
6from testtools import TestCase
7
8from pkgme.backend import ExternalHelpersBackend, get_backend_dir
9from pkgme.binary import (
10 CATEGORIES,
11 DEPENDS,
12 get_desktop_file,
13 get_install_file,
14 guess_dependencies,
15 METADATA_FILE,
16 PACKAGE_NAME,
17 TAGLINE,
18 )
19from pkgme.info_elements import (
20 BuildDepends,
21 Depends,
22 ExtraFiles,
23 PackageName,
24 )
25from pkgme.testing import TempdirFixture
26
27
28BACKEND_NAME = 'binary'
29
30backend_dir = get_backend_dir(__file__, BACKEND_NAME)
31
32
33class BinaryBackendTests(TestCase, TestWithFixtures):
34
35 def test_want_with_metadata(self):
36 # If we detect a binary, then we score 10. The way we determine if
37 # something is a binary is if it has a devportal-metadata.json in its
38 # top-level.
39 tempdir = self.useFixture(TempdirFixture())
40 tempdir.touch(METADATA_FILE)
41 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
42 self.assertEqual(10, backend.want(tempdir.path))
43
44 def test_want_without_metadata(self):
45 # If we do *not* detect a binary, then we score 0. The way we
46 # determine if something is a binary is if it has a
47 # devportal-metadata.json in its top-level.
48 tempdir = self.useFixture(TempdirFixture())
49 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
50 self.assertEqual(0, backend.want(tempdir.path))
51
52 def test_package_name(self):
53 # The binary backend gets the package name from the metadata file.
54 tempdir = self.useFixture(TempdirFixture())
55 tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'}))
56 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
57 info = backend.get_info(tempdir.path)
58 self.assertEqual(
59 {PackageName.name: "foo"}, info.get_all([PackageName.name]))
60
61 def test_build_depends(self):
62 tempdir = self.useFixture(TempdirFixture())
63 tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'}))
64 shutil.copy(
65 os.path.join(os.path.dirname(__file__), 'hello'),
66 tempdir.path)
67 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
68 info = backend.get_info(tempdir.path)
69 deps = ', '.join(guess_dependencies(tempdir.path))
70 self.assertEqual(
71 {BuildDepends.name: deps}, info.get_all([BuildDepends.name]))
72
73 def test_depends(self):
74 tempdir = self.useFixture(TempdirFixture())
75 tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'}))
76 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
77 info = backend.get_info(tempdir.path)
78 self.assertEqual({Depends.name: DEPENDS}, info.get_all([Depends.name]))
79
80 def test_extra_files_install_file(self):
81 # We create an 'install' file that tells debhelper to just copy
82 # everything to opt.
83 tempdir = self.useFixture(TempdirFixture())
84 package_name = self.getUniqueString()
85 tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: package_name}))
86 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
87 info = backend.get_info(tempdir.path)
88 extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name]
89 install_file = json.loads(extra_files)['debian/install']
90 self.assertEqual(
91 get_install_file(package_name, tempdir.path, True),
92 install_file)
93
94 def test_extra_files_desktop_file(self):
95 # We create an 'install' file that tells debhelper to just copy
96 # everything to opt.
97 tempdir = self.useFixture(TempdirFixture())
98 package_name = self.getUniqueString()
99 tagline = self.getUniqueString()
100 categories = self.getUniqueString()
101 metadata = {
102 PACKAGE_NAME: package_name,
103 TAGLINE: tagline,
104 CATEGORIES: categories,
105 }
106 tempdir.create_file(METADATA_FILE, json.dumps(metadata))
107 # We need to create an executable in order to be able to generate a
108 # desktop.
109 tempdir.touch('executable', 0755)
110 expected_desktop_file = get_desktop_file(
111 package_name, tempdir.path, tagline=tagline,
112 categories=categories).get_contents()
113 backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir)
114 info = backend.get_info(tempdir.path)
115 extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name]
116 desktop = json.loads(extra_files)['debian/%s.desktop' % (package_name,)]
117 self.assertEqual(expected_desktop_file, desktop)

Subscribers

People subscribed via source and target branches