Merge lp:~jml/pkgme/remove-binary-backend into lp:pkgme
- remove-binary-backend
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+71023@code.launchpad.net |
Commit message
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-
* 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.
- 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
1 | === removed directory 'pkgme/backends/binary' | |||
2 | === removed file 'pkgme/backends/binary/build_depends' | |||
3 | --- pkgme/backends/binary/build_depends 2011-07-18 11:08:14 +0000 | |||
4 | +++ pkgme/backends/binary/build_depends 1970-01-01 00:00:00 +0000 | |||
5 | @@ -1,14 +0,0 @@ | |||
6 | 1 | #!/usr/bin/python | ||
7 | 2 | |||
8 | 3 | import os | ||
9 | 4 | |||
10 | 5 | from pkgme.binary import guess_dependencies | ||
11 | 6 | |||
12 | 7 | |||
13 | 8 | def main(): | ||
14 | 9 | path = os.getcwd() | ||
15 | 10 | print ', '.join(guess_dependencies(path)) | ||
16 | 11 | |||
17 | 12 | |||
18 | 13 | if __name__ == '__main__': | ||
19 | 14 | main() | ||
20 | 15 | 0 | ||
21 | === removed file 'pkgme/backends/binary/depends' | |||
22 | --- pkgme/backends/binary/depends 2011-07-18 11:08:14 +0000 | |||
23 | +++ pkgme/backends/binary/depends 1970-01-01 00:00:00 +0000 | |||
24 | @@ -1,11 +0,0 @@ | |||
25 | 1 | #!/usr/bin/python | ||
26 | 2 | |||
27 | 3 | from pkgme.binary import DEPENDS | ||
28 | 4 | |||
29 | 5 | |||
30 | 6 | def main(): | ||
31 | 7 | print DEPENDS | ||
32 | 8 | |||
33 | 9 | |||
34 | 10 | if __name__ == '__main__': | ||
35 | 11 | main() | ||
36 | 12 | 0 | ||
37 | === removed file 'pkgme/backends/binary/extra_files' | |||
38 | --- pkgme/backends/binary/extra_files 2011-07-18 11:08:14 +0000 | |||
39 | +++ pkgme/backends/binary/extra_files 1970-01-01 00:00:00 +0000 | |||
40 | @@ -1,36 +0,0 @@ | |||
41 | 1 | #!/usr/bin/python | ||
42 | 2 | |||
43 | 3 | import json | ||
44 | 4 | import os | ||
45 | 5 | import sys | ||
46 | 6 | |||
47 | 7 | from pkgme.binary import ( | ||
48 | 8 | CATEGORIES, | ||
49 | 9 | get_desktop_file, | ||
50 | 10 | get_install_file, | ||
51 | 11 | METADATA_FILE, | ||
52 | 12 | PACKAGE_NAME, | ||
53 | 13 | TAGLINE, | ||
54 | 14 | ) | ||
55 | 15 | |||
56 | 16 | |||
57 | 17 | def main(): | ||
58 | 18 | with open(METADATA_FILE) as f: | ||
59 | 19 | metadata = json.load(f) | ||
60 | 20 | package_name = metadata[PACKAGE_NAME] | ||
61 | 21 | path = os.getcwd() | ||
62 | 22 | install_file = get_install_file(package_name, path, True) | ||
63 | 23 | desktop_file = get_desktop_file( | ||
64 | 24 | package_name, path, | ||
65 | 25 | tagline=metadata.get(TAGLINE, ''), | ||
66 | 26 | categories=metadata.get(CATEGORIES, '')) | ||
67 | 27 | json.dump( | ||
68 | 28 | { | ||
69 | 29 | # XXX: Hardcoded literal attack! | ||
70 | 30 | 'debian/install': install_file, | ||
71 | 31 | 'debian/%s.desktop' % (package_name,): desktop_file.get_contents(), | ||
72 | 32 | }, sys.stdout) | ||
73 | 33 | |||
74 | 34 | |||
75 | 35 | if __name__ == '__main__': | ||
76 | 36 | main() | ||
77 | 37 | 0 | ||
78 | === removed file 'pkgme/backends/binary/package_name' | |||
79 | --- pkgme/backends/binary/package_name 2011-07-18 11:08:14 +0000 | |||
80 | +++ pkgme/backends/binary/package_name 1970-01-01 00:00:00 +0000 | |||
81 | @@ -1,17 +0,0 @@ | |||
82 | 1 | #!/usr/bin/python | ||
83 | 2 | |||
84 | 3 | import json | ||
85 | 4 | from pkgme.binary import ( | ||
86 | 5 | METADATA_FILE, | ||
87 | 6 | PACKAGE_NAME, | ||
88 | 7 | ) | ||
89 | 8 | |||
90 | 9 | |||
91 | 10 | def main(): | ||
92 | 11 | with open(METADATA_FILE) as f: | ||
93 | 12 | metadata = json.load(f) | ||
94 | 13 | print metadata[PACKAGE_NAME] | ||
95 | 14 | |||
96 | 15 | |||
97 | 16 | if __name__ == '__main__': | ||
98 | 17 | main() | ||
99 | 18 | 0 | ||
100 | === removed file 'pkgme/backends/binary/want' | |||
101 | --- pkgme/backends/binary/want 2011-07-13 13:18:03 +0000 | |||
102 | +++ pkgme/backends/binary/want 1970-01-01 00:00:00 +0000 | |||
103 | @@ -1,15 +0,0 @@ | |||
104 | 1 | #!/usr/bin/python | ||
105 | 2 | |||
106 | 3 | import os | ||
107 | 4 | |||
108 | 5 | from pkgme.binary import METADATA_FILE | ||
109 | 6 | |||
110 | 7 | def main(): | ||
111 | 8 | if os.path.exists(METADATA_FILE): | ||
112 | 9 | print 10 | ||
113 | 10 | else: | ||
114 | 11 | print 0 | ||
115 | 12 | |||
116 | 13 | |||
117 | 14 | if __name__ == '__main__': | ||
118 | 15 | main() | ||
119 | 16 | 0 | ||
120 | === removed file 'pkgme/binary.py' | |||
121 | --- pkgme/binary.py 2011-07-15 16:30:18 +0000 | |||
122 | +++ pkgme/binary.py 1970-01-01 00:00:00 +0000 | |||
123 | @@ -1,249 +0,0 @@ | |||
124 | 1 | """Things to help package binary tarballs. | ||
125 | 2 | |||
126 | 3 | HIGHLY EXPERIMENTAL. USE AT YOUR OWN PERIL. | ||
127 | 4 | |||
128 | 5 | At the moment, we are assuming a great many things about these binary | ||
129 | 6 | tarballs. | ||
130 | 7 | |||
131 | 8 | * That they represent some sort of application to be run from an Ubuntu | ||
132 | 9 | desktop | ||
133 | 10 | |||
134 | 11 | * Specifically, that although they might have many executables, only one is | ||
135 | 12 | the "main executable" mentioned in the 'desktop' file | ||
136 | 13 | |||
137 | 14 | * They are written in C or C++ and that all dependencies can be determined | ||
138 | 15 | by inspecting the included object files | ||
139 | 16 | |||
140 | 17 | * That the entire contents of the tarball can be copied into | ||
141 | 18 | /opt/<package-name> and run from there | ||
142 | 19 | |||
143 | 20 | * That we have a metadata file, called 'devportal-metadata.json', in JSON, | ||
144 | 21 | that specifies: | ||
145 | 22 | * package_name | ||
146 | 23 | |||
147 | 24 | The expectation is that this metadata file is generated from the developer | ||
148 | 25 | portal. | ||
149 | 26 | """ | ||
150 | 27 | |||
151 | 28 | # XXX: No idea about architecture | ||
152 | 29 | |||
153 | 30 | __all__ = [ | ||
154 | 31 | 'get_install_file', | ||
155 | 32 | 'guess_executable', | ||
156 | 33 | 'iter_executables', | ||
157 | 34 | 'METADATA_FILE', | ||
158 | 35 | ] | ||
159 | 36 | |||
160 | 37 | |||
161 | 38 | import os | ||
162 | 39 | import subprocess | ||
163 | 40 | |||
164 | 41 | from pkgme.info_elements import ( | ||
165 | 42 | ApplicationName, | ||
166 | 43 | Categories, | ||
167 | 44 | Executable, | ||
168 | 45 | PackageName, | ||
169 | 46 | TagLine, | ||
170 | 47 | ) | ||
171 | 48 | from pkgme.package_files import ( | ||
172 | 49 | DEBIAN_DIR, | ||
173 | 50 | Desktop, | ||
174 | 51 | ) | ||
175 | 52 | from pkgme.project_info import DictInfo | ||
176 | 53 | |||
177 | 54 | |||
178 | 55 | METADATA_FILE = 'devportal-metadata.json' | ||
179 | 56 | |||
180 | 57 | # Keys found in the metadata file. | ||
181 | 58 | CATEGORIES = 'categories' | ||
182 | 59 | # It's called package_name in the database, so this probably makes sense. | ||
183 | 60 | PACKAGE_NAME = 'package_name' | ||
184 | 61 | TAGLINE = 'tagline' | ||
185 | 62 | |||
186 | 63 | |||
187 | 64 | # Always depend on these. | ||
188 | 65 | # | ||
189 | 66 | # XXX: jml just doing this because iamfuzz does. Need to either experiment or | ||
190 | 67 | # consult expert. | ||
191 | 68 | DEPENDS = '${shlibs:Depends}, ${misc:Depends}' | ||
192 | 69 | |||
193 | 70 | # XXX: No idea about how icons will be there. Ignoring for now. | ||
194 | 71 | |||
195 | 72 | def guess_executable(package_name, executables): | ||
196 | 73 | """ | ||
197 | 74 | From a list of executables, guess which one is likely to be the main | ||
198 | 75 | executable. | ||
199 | 76 | """ | ||
200 | 77 | |||
201 | 78 | # The lower the score, the more likely it is to be the right executable. | ||
202 | 79 | |||
203 | 80 | def score_name(name): | ||
204 | 81 | # Names that match exactly are good. | ||
205 | 82 | return -int(name.lower() == package_name.lower()) | ||
206 | 83 | |||
207 | 84 | def score_path(executable): | ||
208 | 85 | # The deeper the path, the less likely it is to be the one. | ||
209 | 86 | return executable.count('/') | ||
210 | 87 | |||
211 | 88 | def rank(executable): | ||
212 | 89 | name = os.path.basename(executable) | ||
213 | 90 | # The alpha-sorting of the base name is a tie-breaker. | ||
214 | 91 | return score_name(name), score_path(executable), name | ||
215 | 92 | |||
216 | 93 | try: | ||
217 | 94 | return sorted(executables, key=rank)[0] | ||
218 | 95 | except IndexError: | ||
219 | 96 | return None | ||
220 | 97 | |||
221 | 98 | |||
222 | 99 | def iter_executables(path): | ||
223 | 100 | """Iterate through all executable files under 'path'. | ||
224 | 101 | |||
225 | 102 | Paths yielded will be relative to 'path'. Directories will *not* be | ||
226 | 103 | yielded. "Executable" is determined by filesystem permissions. | ||
227 | 104 | """ | ||
228 | 105 | for root, dirs, files in os.walk(path): | ||
229 | 106 | for filename in files: | ||
230 | 107 | file_path = os.path.join(root, filename) | ||
231 | 108 | if os.access(file_path, os.X_OK): | ||
232 | 109 | yield os.path.relpath(file_path, path) | ||
233 | 110 | |||
234 | 111 | |||
235 | 112 | def get_install_file(package_name, path, include_desktop=False): | ||
236 | 113 | """Generate the install file for 'package_name'.""" | ||
237 | 114 | lines = [] | ||
238 | 115 | # Sorting not actually needed for functionality, but makes the tests more | ||
239 | 116 | # reliable. | ||
240 | 117 | for filename in sorted(os.listdir(path)): | ||
241 | 118 | if filename in (DEBIAN_DIR, METADATA_FILE): | ||
242 | 119 | # We don't want to install the 'debian/' directory or the metadata | ||
243 | 120 | # file. | ||
244 | 121 | continue | ||
245 | 122 | lines.append('%s opt/%s' % (filename, package_name)) | ||
246 | 123 | if include_desktop: | ||
247 | 124 | lines.append( | ||
248 | 125 | 'debian/%s.desktop usr/share/application' % (package_name,)) | ||
249 | 126 | # Ending the file with a newline is basic good manners. | ||
250 | 127 | lines.append('') | ||
251 | 128 | return '\n'.join(lines) | ||
252 | 129 | |||
253 | 130 | |||
254 | 131 | def get_desktop_file(package_name, path, tagline=None, categories=None): | ||
255 | 132 | executable = guess_executable(package_name, iter_executables(path)) | ||
256 | 133 | info = { | ||
257 | 134 | PackageName.name: package_name, | ||
258 | 135 | ApplicationName.name: package_name.capitalize(), | ||
259 | 136 | Executable.name: '/opt/%s/%s' % (package_name, executable), | ||
260 | 137 | TagLine.name: tagline, | ||
261 | 138 | Categories.name: categories, | ||
262 | 139 | } | ||
263 | 140 | return Desktop.from_info(DictInfo(info)) | ||
264 | 141 | |||
265 | 142 | |||
266 | 143 | def get_file_type(path): | ||
267 | 144 | return get_file_types([path])[0] | ||
268 | 145 | |||
269 | 146 | |||
270 | 147 | def get_file_types(paths): | ||
271 | 148 | paths = list(paths) | ||
272 | 149 | if not paths: | ||
273 | 150 | return [] | ||
274 | 151 | cmd = ['file', '-b'] + paths | ||
275 | 152 | return subprocess.Popen( | ||
276 | 153 | cmd, stdout=subprocess.PIPE).communicate()[0].splitlines() | ||
277 | 154 | |||
278 | 155 | |||
279 | 156 | def ldd(binary_paths): | ||
280 | 157 | # ldd has output of the form: | ||
281 | 158 | # | ||
282 | 159 | # path/to/elf/object: | ||
283 | 160 | # linux-vdso.so.1 => (0x00007fff4a7ff000) | ||
284 | 161 | # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7472623000) | ||
285 | 162 | # /lib64/ld-linux-x86-64.so.2 (0x00007f74729e5000) | ||
286 | 163 | # | ||
287 | 164 | # i.e. | ||
288 | 165 | # <name> => <path> (<address>) | ||
289 | 166 | # | ||
290 | 167 | # where <name> and <path> are both optional. If <name> is not given, then | ||
291 | 168 | # there is no arrow (=>). | ||
292 | 169 | binary_paths = list(binary_paths) | ||
293 | 170 | if not binary_paths: | ||
294 | 171 | return {} | ||
295 | 172 | cmd = ['ldd'] + binary_paths | ||
296 | 173 | output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] | ||
297 | 174 | libraries = {} | ||
298 | 175 | current = [] | ||
299 | 176 | if len(binary_paths) == 1: | ||
300 | 177 | libraries[binary_paths[0]] = current | ||
301 | 178 | for line in output.splitlines(): | ||
302 | 179 | if line.endswith(':'): | ||
303 | 180 | current.sort() | ||
304 | 181 | current = libraries[line.strip(':')] = [] | ||
305 | 182 | continue | ||
306 | 183 | # Last token is always irrelevant hex address. | ||
307 | 184 | tokens = line.split()[:-1] | ||
308 | 185 | name, path = None, None | ||
309 | 186 | if '=>' in tokens: | ||
310 | 187 | name = tokens[0] | ||
311 | 188 | if len(tokens) > 2: | ||
312 | 189 | path = tokens[2] | ||
313 | 190 | else: | ||
314 | 191 | path = tokens[0] | ||
315 | 192 | current.append((name, path)) | ||
316 | 193 | current.sort() | ||
317 | 194 | return libraries | ||
318 | 195 | |||
319 | 196 | |||
320 | 197 | def get_shared_library_dependencies(paths): | ||
321 | 198 | # XXX: Not sure which of these is more useful. Specifically, if the | ||
322 | 199 | # library isn't installed on the system, then I don't know whether it will | ||
323 | 200 | # appear in ldd as the library_path. -- jml | ||
324 | 201 | libraries = ldd(paths) | ||
325 | 202 | for libs in libraries.values(): | ||
326 | 203 | for name, library_path in libs: | ||
327 | 204 | if library_path: | ||
328 | 205 | yield library_path | ||
329 | 206 | |||
330 | 207 | |||
331 | 208 | def find_shared_library_dependencies(path): | ||
332 | 209 | return set(get_shared_library_dependencies(iter_binaries(path))) | ||
333 | 210 | |||
334 | 211 | |||
335 | 212 | def iter_binaries(path): | ||
336 | 213 | |||
337 | 214 | def is_binary(file_type): | ||
338 | 215 | return file_type.startswith('ELF') | ||
339 | 216 | |||
340 | 217 | for root, dirs, files in os.walk(path): | ||
341 | 218 | paths = [os.path.join(root, filename) for filename in files] | ||
342 | 219 | types = get_file_types(paths) | ||
343 | 220 | for file_path, file_type in zip(paths, types): | ||
344 | 221 | if is_binary(file_type): | ||
345 | 222 | yield file_path | ||
346 | 223 | |||
347 | 224 | |||
348 | 225 | def apt_file(filename): | ||
349 | 226 | # XXX: Assumes apt-file update has been run. | ||
350 | 227 | |||
351 | 228 | # XXX: Passing the full file name since it seems the least likely to yield | ||
352 | 229 | # multiple dependencies. If 'get_shared_library_dependencies' ought to | ||
353 | 230 | # return just the names, then this will have to change to be a regex, and | ||
354 | 231 | # we'll need to think about ambiguity resolution much sooner. | ||
355 | 232 | # cmd = ['apt-file', 'find', '-x', '/%s$' % (filename,)] | ||
356 | 233 | |||
357 | 234 | # XXX: Currently matching badly due to architecture. | ||
358 | 235 | cmd = ['apt-file', 'find', '-F', filename] | ||
359 | 236 | output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] | ||
360 | 237 | for line in output.splitlines(): | ||
361 | 238 | yield line.split(': ')[0] | ||
362 | 239 | |||
363 | 240 | |||
364 | 241 | def guess_dependencies(path): | ||
365 | 242 | deps = set() | ||
366 | 243 | # XXX: ldd probably is recursive. This means it finds *all* the libraries | ||
367 | 244 | # that are needed. However, we only need to specify the top-level | ||
368 | 245 | # libraries (e.g. libc6 should almost never be a dependency). | ||
369 | 246 | for library in find_shared_library_dependencies(path): | ||
370 | 247 | for dep in apt_file(library): | ||
371 | 248 | deps.add(dep) | ||
372 | 249 | return deps | ||
373 | 250 | 0 | ||
374 | === modified file 'pkgme/tests/__init__.py' | |||
375 | --- pkgme/tests/__init__.py 2011-08-01 16:48:11 +0000 | |||
376 | +++ pkgme/tests/__init__.py 2011-08-10 12:24:37 +0000 | |||
377 | @@ -7,8 +7,6 @@ | |||
378 | 7 | def test_suite(): | 7 | def test_suite(): |
379 | 8 | module_names = [ | 8 | module_names = [ |
380 | 9 | 'pkgme.tests.test_backend', | 9 | 'pkgme.tests.test_backend', |
381 | 10 | 'pkgme.tests.test_binary', | ||
382 | 11 | 'pkgme.tests.test_binary_backend', | ||
383 | 12 | 'pkgme.tests.test_distutils_command', | 10 | 'pkgme.tests.test_distutils_command', |
384 | 13 | 'pkgme.tests.test_info_elements', | 11 | 'pkgme.tests.test_info_elements', |
385 | 14 | 'pkgme.tests.test_package_files', | 12 | 'pkgme.tests.test_package_files', |
386 | 15 | 13 | ||
387 | === removed file 'pkgme/tests/foo.data' | |||
388 | 16 | Binary 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 | 14 | Binary 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 |
389 | === removed file 'pkgme/tests/hello' | |||
390 | 17 | Binary files pkgme/tests/hello 2011-07-15 09:49:16 +0000 and pkgme/tests/hello 1970-01-01 00:00:00 +0000 differ | 15 | Binary files pkgme/tests/hello 2011-07-15 09:49:16 +0000 and pkgme/tests/hello 1970-01-01 00:00:00 +0000 differ |
391 | === removed file 'pkgme/tests/simple.so.1' | |||
392 | 18 | Binary 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 | 16 | Binary 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 |
393 | === removed file 'pkgme/tests/test_binary.py' | |||
394 | --- pkgme/tests/test_binary.py 2011-07-15 16:30:18 +0000 | |||
395 | +++ pkgme/tests/test_binary.py 1970-01-01 00:00:00 +0000 | |||
396 | @@ -1,339 +0,0 @@ | |||
397 | 1 | import os | ||
398 | 2 | |||
399 | 3 | from fixtures import TestWithFixtures | ||
400 | 4 | from testtools import TestCase | ||
401 | 5 | from testtools.matchers import StartsWith | ||
402 | 6 | |||
403 | 7 | from pkgme.binary import ( | ||
404 | 8 | apt_file, | ||
405 | 9 | find_shared_library_dependencies, | ||
406 | 10 | get_desktop_file, | ||
407 | 11 | get_file_type, | ||
408 | 12 | get_file_types, | ||
409 | 13 | get_install_file, | ||
410 | 14 | get_shared_library_dependencies, | ||
411 | 15 | guess_dependencies, | ||
412 | 16 | guess_executable, | ||
413 | 17 | iter_binaries, | ||
414 | 18 | iter_executables, | ||
415 | 19 | ldd, | ||
416 | 20 | METADATA_FILE, | ||
417 | 21 | ) | ||
418 | 22 | from pkgme.package_files import DEBIAN_DIR | ||
419 | 23 | from pkgme.testing import ( | ||
420 | 24 | AreDesktopValuesFor, | ||
421 | 25 | TempdirFixture, | ||
422 | 26 | ) | ||
423 | 27 | |||
424 | 28 | |||
425 | 29 | class BinaryTests(TestCase, TestWithFixtures): | ||
426 | 30 | |||
427 | 31 | def test_metadata_file(self): | ||
428 | 32 | self.assertEqual('devportal-metadata.json', METADATA_FILE) | ||
429 | 33 | |||
430 | 34 | |||
431 | 35 | class InstallFileTests(TestCase, TestWithFixtures): | ||
432 | 36 | |||
433 | 37 | def test_install_file(self): | ||
434 | 38 | # The install file instructs debhelper to copy everything in the | ||
435 | 39 | # top-level to /opt/<package-name>. | ||
436 | 40 | tempdir = self.useFixture(TempdirFixture()) | ||
437 | 41 | tempdir.touch('some-file') | ||
438 | 42 | install_file = get_install_file('package-name', tempdir.path) | ||
439 | 43 | self.assertEqual("some-file opt/package-name\n", install_file) | ||
440 | 44 | |||
441 | 45 | def test_install_file_many_files_and_directories(self): | ||
442 | 46 | # The install file instructs debhelper to copy everything in the | ||
443 | 47 | # top-level to /opt/<package-name>. | ||
444 | 48 | tempdir = self.useFixture(TempdirFixture()) | ||
445 | 49 | tempdir.touch('some-file') | ||
446 | 50 | tempdir.mkdir('directory') | ||
447 | 51 | install_file = get_install_file('package-name', tempdir.path) | ||
448 | 52 | self.assertEqual( | ||
449 | 53 | "directory opt/package-name\n" | ||
450 | 54 | "some-file opt/package-name\n", | ||
451 | 55 | install_file) | ||
452 | 56 | |||
453 | 57 | def test_skip_debian(self): | ||
454 | 58 | # The install file instructs debhelper to copy everything in the | ||
455 | 59 | # top-level to /opt/<package-name>, except for the 'debian' directory. | ||
456 | 60 | tempdir = self.useFixture(TempdirFixture()) | ||
457 | 61 | tempdir.touch('some-file') | ||
458 | 62 | tempdir.mkdir('directory') | ||
459 | 63 | tempdir.mkdir(DEBIAN_DIR) | ||
460 | 64 | install_file = get_install_file('package-name', tempdir.path) | ||
461 | 65 | self.assertEqual( | ||
462 | 66 | "directory opt/package-name\n" | ||
463 | 67 | "some-file opt/package-name\n", | ||
464 | 68 | install_file) | ||
465 | 69 | |||
466 | 70 | def test_skip_metadata(self): | ||
467 | 71 | # The install file instructs debhelper to copy everything in the | ||
468 | 72 | # top-level to /opt/<package-name>, except for the 'debian' directory | ||
469 | 73 | # and the metadata file. | ||
470 | 74 | tempdir = self.useFixture(TempdirFixture()) | ||
471 | 75 | tempdir.touch('some-file') | ||
472 | 76 | tempdir.mkdir('directory') | ||
473 | 77 | tempdir.touch(METADATA_FILE) | ||
474 | 78 | install_file = get_install_file('package-name', tempdir.path) | ||
475 | 79 | self.assertEqual( | ||
476 | 80 | "directory opt/package-name\n" | ||
477 | 81 | "some-file opt/package-name\n", | ||
478 | 82 | install_file) | ||
479 | 83 | |||
480 | 84 | def test_include_desktop_file(self): | ||
481 | 85 | tempdir = self.useFixture(TempdirFixture()) | ||
482 | 86 | tempdir.touch('some-file') | ||
483 | 87 | install_file = get_install_file( | ||
484 | 88 | 'package-name', tempdir.path, include_desktop=True) | ||
485 | 89 | self.assertEqual( | ||
486 | 90 | "some-file opt/package-name\n" | ||
487 | 91 | "debian/package-name.desktop usr/share/application\n", | ||
488 | 92 | install_file) | ||
489 | 93 | |||
490 | 94 | |||
491 | 95 | class DesktopFileTests(TestCase): | ||
492 | 96 | |||
493 | 97 | def test_executable_is_best_guess(self): | ||
494 | 98 | package_name = self.getUniqueString() | ||
495 | 99 | tempdir = self.useFixture(TempdirFixture()) | ||
496 | 100 | tempdir.mkdir('whatever') | ||
497 | 101 | tempdir.touch('whatever/not-the-best', 0755) | ||
498 | 102 | tempdir.touch('the-best', 0755) | ||
499 | 103 | desktop_file = get_desktop_file(package_name, tempdir.path) | ||
500 | 104 | self.assertThat( | ||
501 | 105 | {'Exec': '/opt/%s/the-best' % (package_name,)}, | ||
502 | 106 | AreDesktopValuesFor(desktop_file)) | ||
503 | 107 | |||
504 | 108 | def test_app_name_is_capitalized_package_name(self): | ||
505 | 109 | # We don't have any information on the package name, so try to guess | ||
506 | 110 | # the application name. | ||
507 | 111 | tempdir = self.useFixture(TempdirFixture()) | ||
508 | 112 | package_name = self.getUniqueString() | ||
509 | 113 | desktop_file = get_desktop_file(package_name, tempdir.path) | ||
510 | 114 | self.assertThat( | ||
511 | 115 | {'Name': package_name.capitalize()}, | ||
512 | 116 | AreDesktopValuesFor(desktop_file)) | ||
513 | 117 | |||
514 | 118 | def test_category_and_tagline_are_specified(self): | ||
515 | 119 | # We just pass the category and comment through. | ||
516 | 120 | tempdir = self.useFixture(TempdirFixture()) | ||
517 | 121 | package_name = self.getUniqueString() | ||
518 | 122 | tagline = self.getUniqueString() | ||
519 | 123 | categories = self.getUniqueString() | ||
520 | 124 | desktop_file = get_desktop_file( | ||
521 | 125 | package_name, tempdir.path, tagline=tagline, categories=categories) | ||
522 | 126 | self.assertThat( | ||
523 | 127 | {'Comment': tagline, 'Categories': categories}, | ||
524 | 128 | AreDesktopValuesFor(desktop_file)) | ||
525 | 129 | |||
526 | 130 | |||
527 | 131 | class FindExecutableTests(TestCase, TestWithFixtures): | ||
528 | 132 | |||
529 | 133 | def test_only_one_file_and_it_is_executable(self): | ||
530 | 134 | # If there is only one file and it's executable, find that. | ||
531 | 135 | tempdir = self.useFixture(TempdirFixture()) | ||
532 | 136 | tempdir.touch('some-file', mode=0755) | ||
533 | 137 | executables = list(iter_executables(tempdir.path)) | ||
534 | 138 | self.assertEqual(['some-file'], executables) | ||
535 | 139 | |||
536 | 140 | def test_no_files_at_all(self): | ||
537 | 141 | # iter_executables finds no executables if there are no files at all. | ||
538 | 142 | tempdir = self.useFixture(TempdirFixture()) | ||
539 | 143 | executables = list(iter_executables(tempdir.path)) | ||
540 | 144 | self.assertEqual([], executables) | ||
541 | 145 | |||
542 | 146 | def test_no_executable_files(self): | ||
543 | 147 | # If there are no executable files, iter_executables returns None. | ||
544 | 148 | tempdir = self.useFixture(TempdirFixture()) | ||
545 | 149 | tempdir.touch('some-file', mode=0644) | ||
546 | 150 | executables = list(iter_executables(tempdir.path)) | ||
547 | 151 | self.assertEqual([], executables) | ||
548 | 152 | |||
549 | 153 | def test_directory_is_not_executable_file(self): | ||
550 | 154 | # A directory does not count as an executable file. | ||
551 | 155 | tempdir = self.useFixture(TempdirFixture()) | ||
552 | 156 | tempdir.mkdir('directory') | ||
553 | 157 | executables = list(iter_executables(tempdir.path)) | ||
554 | 158 | self.assertEqual([], executables) | ||
555 | 159 | |||
556 | 160 | def test_finds_executable_in_nested_directory(self): | ||
557 | 161 | # Even if the file is in some nested directory, we are able to find | ||
558 | 162 | # it. | ||
559 | 163 | tempdir = self.useFixture(TempdirFixture()) | ||
560 | 164 | tempdir.mkdir('directory') | ||
561 | 165 | tempdir.touch('directory/my-executable', mode=0755) | ||
562 | 166 | executables = list(iter_executables(tempdir.path)) | ||
563 | 167 | self.assertEqual(['directory/my-executable'], executables) | ||
564 | 168 | |||
565 | 169 | def test_multiple_executables(self): | ||
566 | 170 | # If there are many executables, iter_executables finds them all. | ||
567 | 171 | tempdir = self.useFixture(TempdirFixture()) | ||
568 | 172 | tempdir.touch('some-file', mode=0755) | ||
569 | 173 | tempdir.touch('another-file', mode=0755) | ||
570 | 174 | executables = sorted(list(iter_executables(tempdir.path))) | ||
571 | 175 | self.assertEqual(['another-file', 'some-file'], executables) | ||
572 | 176 | |||
573 | 177 | |||
574 | 178 | class GuessExecutableTests(TestCase): | ||
575 | 179 | |||
576 | 180 | def test_no_executables(self): | ||
577 | 181 | # If there are no executables to select from, then return None, | ||
578 | 182 | # indicating the fact. | ||
579 | 183 | executable = guess_executable('package-name', iter([])) | ||
580 | 184 | self.assertIs(None, executable) | ||
581 | 185 | |||
582 | 186 | def test_only_one_executable(self): | ||
583 | 187 | # If there's only one executable, then return that, since it's | ||
584 | 188 | # probably the main executable for the package. | ||
585 | 189 | executable = guess_executable('package-name', ['whatever']) | ||
586 | 190 | self.assertEqual('whatever', executable) | ||
587 | 191 | |||
588 | 192 | def test_exact_package_name_match(self): | ||
589 | 193 | # If there are many executables, but one of them has the same name as | ||
590 | 194 | # the package, then that is probably the main executable. | ||
591 | 195 | executable = guess_executable( | ||
592 | 196 | 'package-name', ['whatever', 'package-name']) | ||
593 | 197 | self.assertEqual('package-name', executable) | ||
594 | 198 | |||
595 | 199 | def test_exact_package_name_match_in_subdir(self): | ||
596 | 200 | # If there are many executables, but one of them has the same name as | ||
597 | 201 | # the package, then that is probably the main executable, even if it | ||
598 | 202 | # is in a sub-directory. | ||
599 | 203 | executable = guess_executable( | ||
600 | 204 | 'package-name', ['whatever', 'subdir/package-name', 'foo']) | ||
601 | 205 | self.assertEqual('subdir/package-name', executable) | ||
602 | 206 | |||
603 | 207 | def test_multiple_exact_matches(self): | ||
604 | 208 | # If there are many executables that have the same name as the | ||
605 | 209 | # package, then the one that is the least nested is our best guess. | ||
606 | 210 | executable = guess_executable( | ||
607 | 211 | 'package-name', [ | ||
608 | 212 | 'whatever', 'a/b/c/d/e/subdir/package-name', 'foo', | ||
609 | 213 | 'subdir/package-name']) | ||
610 | 214 | self.assertEqual('subdir/package-name', executable) | ||
611 | 215 | |||
612 | 216 | def test_different_case_match(self): | ||
613 | 217 | # If one of the executables has the same name as the package, but | ||
614 | 218 | # spelled with different case, then that is our best guess. | ||
615 | 219 | executable = guess_executable( | ||
616 | 220 | 'packagename', [ | ||
617 | 221 | 'whatever', 'a/b/c/d/e/subdir/packagename', 'foo', | ||
618 | 222 | 'subdir/PackageName']) | ||
619 | 223 | self.assertEqual('subdir/PackageName', executable) | ||
620 | 224 | |||
621 | 225 | def test_many_executables(self): | ||
622 | 226 | # If there are many executables, and their names have no particular | ||
623 | 227 | # relationship to the package name, then just pick the top-most | ||
624 | 228 | # one. If there's more than one, take the alphabetically sorted. | ||
625 | 229 | executable = guess_executable( | ||
626 | 230 | 'package-name', ['dir/x', 'dir/sub/y', 'z', 'a']) | ||
627 | 231 | self.assertEqual('a', executable) | ||
628 | 232 | |||
629 | 233 | |||
630 | 234 | class GetFileTypeTests(TestCase): | ||
631 | 235 | |||
632 | 236 | def test_plain_text(self): | ||
633 | 237 | tempdir = self.useFixture(TempdirFixture()) | ||
634 | 238 | tempdir.create_file('foo.txt', 'boring content\n') | ||
635 | 239 | file_type = get_file_type(tempdir.abspath('foo.txt')) | ||
636 | 240 | self.assertEqual('ASCII text', file_type) | ||
637 | 241 | |||
638 | 242 | def test_data(self): | ||
639 | 243 | file_type = get_file_type( | ||
640 | 244 | os.path.join(os.path.dirname(__file__), 'foo.data')) | ||
641 | 245 | self.assertEqual('data', file_type) | ||
642 | 246 | |||
643 | 247 | def test_elf_binary(self): | ||
644 | 248 | binary_path = os.path.join(os.path.dirname(__file__), 'hello') | ||
645 | 249 | file_type = get_file_type(binary_path) | ||
646 | 250 | self.assertThat(file_type, StartsWith('ELF')) | ||
647 | 251 | |||
648 | 252 | def test_elf_library(self): | ||
649 | 253 | binary_path = os.path.join(os.path.dirname(__file__), 'simple.so.1') | ||
650 | 254 | file_type = get_file_type(binary_path) | ||
651 | 255 | self.assertThat(file_type, StartsWith('ELF')) | ||
652 | 256 | |||
653 | 257 | def test_multiple(self): | ||
654 | 258 | tempdir = self.useFixture(TempdirFixture()) | ||
655 | 259 | tempdir.create_file('foo.txt', 'boring content\n') | ||
656 | 260 | file_types = get_file_types( | ||
657 | 261 | [tempdir.abspath('foo.txt'), | ||
658 | 262 | os.path.join(os.path.dirname(__file__), 'foo.data')]) | ||
659 | 263 | self.assertEqual(['ASCII text', 'data'], file_types) | ||
660 | 264 | |||
661 | 265 | def test_no_files_given(self): | ||
662 | 266 | self.assertEqual([], get_file_types([])) | ||
663 | 267 | self.assertEqual([], get_file_types(iter([]))) | ||
664 | 268 | |||
665 | 269 | |||
666 | 270 | class IterBinariesTests(TestCase): | ||
667 | 271 | |||
668 | 272 | def test_no_binaries(self): | ||
669 | 273 | tempdir = self.useFixture(TempdirFixture()) | ||
670 | 274 | self.assertEqual([], list(iter_binaries(tempdir.path))) | ||
671 | 275 | |||
672 | 276 | def test_some_binaries(self): | ||
673 | 277 | path = os.path.dirname(os.path.dirname(__file__)) | ||
674 | 278 | binaries = sorted(iter_binaries(path)) | ||
675 | 279 | self.assertEqual( | ||
676 | 280 | [os.path.join(os.path.dirname(__file__), 'hello'), | ||
677 | 281 | os.path.join(os.path.dirname(__file__), 'simple.so.1')], | ||
678 | 282 | binaries) | ||
679 | 283 | |||
680 | 284 | |||
681 | 285 | class GetSharedLibraryDependenciesTests(TestCase): | ||
682 | 286 | |||
683 | 287 | def test_ldd_none(self): | ||
684 | 288 | deps = ldd([]) | ||
685 | 289 | self.assertEqual({}, deps) | ||
686 | 290 | |||
687 | 291 | def test_ldd(self): | ||
688 | 292 | hello = os.path.join(os.path.dirname(__file__), 'hello') | ||
689 | 293 | deps = ldd([hello]) | ||
690 | 294 | self.assertEqual( | ||
691 | 295 | {hello: [(None, '/lib64/ld-linux-x86-64.so.2'), | ||
692 | 296 | ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'), | ||
693 | 297 | ('linux-vdso.so.1', None)]}, | ||
694 | 298 | deps) | ||
695 | 299 | |||
696 | 300 | def test_ldd_multiple(self): | ||
697 | 301 | hello = os.path.join(os.path.dirname(__file__), 'hello') | ||
698 | 302 | simple = os.path.join(os.path.dirname(__file__), 'simple.so.1') | ||
699 | 303 | deps = ldd([hello, simple]) | ||
700 | 304 | self.assertEqual( | ||
701 | 305 | {hello: [(None, '/lib64/ld-linux-x86-64.so.2'), | ||
702 | 306 | ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'), | ||
703 | 307 | ('linux-vdso.so.1', None)], | ||
704 | 308 | simple: [(None, '/lib64/ld-linux-x86-64.so.2'), | ||
705 | 309 | ('libc.so.6', '/lib/x86_64-linux-gnu/libc.so.6'), | ||
706 | 310 | ('linux-vdso.so.1', None)]}, | ||
707 | 311 | deps) | ||
708 | 312 | |||
709 | 313 | def test_get_shared_library_dependencies(self): | ||
710 | 314 | hello = os.path.join(os.path.dirname(__file__), 'hello') | ||
711 | 315 | deps = sorted(get_shared_library_dependencies([hello])) | ||
712 | 316 | self.assertEqual( | ||
713 | 317 | ['/lib/x86_64-linux-gnu/libc.so.6', | ||
714 | 318 | '/lib64/ld-linux-x86-64.so.2', | ||
715 | 319 | ], deps) | ||
716 | 320 | |||
717 | 321 | def test_find_shared_library_dependencies(self): | ||
718 | 322 | deps = find_shared_library_dependencies(os.path.dirname(__file__)) | ||
719 | 323 | self.assertEqual( | ||
720 | 324 | set(['/lib/x86_64-linux-gnu/libc.so.6', | ||
721 | 325 | '/lib64/ld-linux-x86-64.so.2']), deps) | ||
722 | 326 | |||
723 | 327 | |||
724 | 328 | class AptFileTests(TestCase): | ||
725 | 329 | |||
726 | 330 | def test_full_file(self): | ||
727 | 331 | packages = list(apt_file('/usr/lib32/libasound.so.2')) | ||
728 | 332 | self.assertEqual(['lib32asound2'], packages) | ||
729 | 333 | |||
730 | 334 | |||
731 | 335 | class GuessDependenciesTests(TestCase): | ||
732 | 336 | |||
733 | 337 | def test_guess_dependencies(self): | ||
734 | 338 | deps = guess_dependencies(os.path.dirname(__file__)) | ||
735 | 339 | self.assertEqual(set(['libc6']), deps) | ||
736 | 340 | 0 | ||
737 | === removed file 'pkgme/tests/test_binary_backend.py' | |||
738 | --- pkgme/tests/test_binary_backend.py 2011-07-18 11:08:14 +0000 | |||
739 | +++ pkgme/tests/test_binary_backend.py 1970-01-01 00:00:00 +0000 | |||
740 | @@ -1,117 +0,0 @@ | |||
741 | 1 | import json | ||
742 | 2 | import os | ||
743 | 3 | import shutil | ||
744 | 4 | |||
745 | 5 | from fixtures import TestWithFixtures | ||
746 | 6 | from testtools import TestCase | ||
747 | 7 | |||
748 | 8 | from pkgme.backend import ExternalHelpersBackend, get_backend_dir | ||
749 | 9 | from pkgme.binary import ( | ||
750 | 10 | CATEGORIES, | ||
751 | 11 | DEPENDS, | ||
752 | 12 | get_desktop_file, | ||
753 | 13 | get_install_file, | ||
754 | 14 | guess_dependencies, | ||
755 | 15 | METADATA_FILE, | ||
756 | 16 | PACKAGE_NAME, | ||
757 | 17 | TAGLINE, | ||
758 | 18 | ) | ||
759 | 19 | from pkgme.info_elements import ( | ||
760 | 20 | BuildDepends, | ||
761 | 21 | Depends, | ||
762 | 22 | ExtraFiles, | ||
763 | 23 | PackageName, | ||
764 | 24 | ) | ||
765 | 25 | from pkgme.testing import TempdirFixture | ||
766 | 26 | |||
767 | 27 | |||
768 | 28 | BACKEND_NAME = 'binary' | ||
769 | 29 | |||
770 | 30 | backend_dir = get_backend_dir(__file__, BACKEND_NAME) | ||
771 | 31 | |||
772 | 32 | |||
773 | 33 | class BinaryBackendTests(TestCase, TestWithFixtures): | ||
774 | 34 | |||
775 | 35 | def test_want_with_metadata(self): | ||
776 | 36 | # If we detect a binary, then we score 10. The way we determine if | ||
777 | 37 | # something is a binary is if it has a devportal-metadata.json in its | ||
778 | 38 | # top-level. | ||
779 | 39 | tempdir = self.useFixture(TempdirFixture()) | ||
780 | 40 | tempdir.touch(METADATA_FILE) | ||
781 | 41 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
782 | 42 | self.assertEqual(10, backend.want(tempdir.path)) | ||
783 | 43 | |||
784 | 44 | def test_want_without_metadata(self): | ||
785 | 45 | # If we do *not* detect a binary, then we score 0. The way we | ||
786 | 46 | # determine if something is a binary is if it has a | ||
787 | 47 | # devportal-metadata.json in its top-level. | ||
788 | 48 | tempdir = self.useFixture(TempdirFixture()) | ||
789 | 49 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
790 | 50 | self.assertEqual(0, backend.want(tempdir.path)) | ||
791 | 51 | |||
792 | 52 | def test_package_name(self): | ||
793 | 53 | # The binary backend gets the package name from the metadata file. | ||
794 | 54 | tempdir = self.useFixture(TempdirFixture()) | ||
795 | 55 | tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'})) | ||
796 | 56 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
797 | 57 | info = backend.get_info(tempdir.path) | ||
798 | 58 | self.assertEqual( | ||
799 | 59 | {PackageName.name: "foo"}, info.get_all([PackageName.name])) | ||
800 | 60 | |||
801 | 61 | def test_build_depends(self): | ||
802 | 62 | tempdir = self.useFixture(TempdirFixture()) | ||
803 | 63 | tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'})) | ||
804 | 64 | shutil.copy( | ||
805 | 65 | os.path.join(os.path.dirname(__file__), 'hello'), | ||
806 | 66 | tempdir.path) | ||
807 | 67 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
808 | 68 | info = backend.get_info(tempdir.path) | ||
809 | 69 | deps = ', '.join(guess_dependencies(tempdir.path)) | ||
810 | 70 | self.assertEqual( | ||
811 | 71 | {BuildDepends.name: deps}, info.get_all([BuildDepends.name])) | ||
812 | 72 | |||
813 | 73 | def test_depends(self): | ||
814 | 74 | tempdir = self.useFixture(TempdirFixture()) | ||
815 | 75 | tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'})) | ||
816 | 76 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
817 | 77 | info = backend.get_info(tempdir.path) | ||
818 | 78 | self.assertEqual({Depends.name: DEPENDS}, info.get_all([Depends.name])) | ||
819 | 79 | |||
820 | 80 | def test_extra_files_install_file(self): | ||
821 | 81 | # We create an 'install' file that tells debhelper to just copy | ||
822 | 82 | # everything to opt. | ||
823 | 83 | tempdir = self.useFixture(TempdirFixture()) | ||
824 | 84 | package_name = self.getUniqueString() | ||
825 | 85 | tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: package_name})) | ||
826 | 86 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
827 | 87 | info = backend.get_info(tempdir.path) | ||
828 | 88 | extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name] | ||
829 | 89 | install_file = json.loads(extra_files)['debian/install'] | ||
830 | 90 | self.assertEqual( | ||
831 | 91 | get_install_file(package_name, tempdir.path, True), | ||
832 | 92 | install_file) | ||
833 | 93 | |||
834 | 94 | def test_extra_files_desktop_file(self): | ||
835 | 95 | # We create an 'install' file that tells debhelper to just copy | ||
836 | 96 | # everything to opt. | ||
837 | 97 | tempdir = self.useFixture(TempdirFixture()) | ||
838 | 98 | package_name = self.getUniqueString() | ||
839 | 99 | tagline = self.getUniqueString() | ||
840 | 100 | categories = self.getUniqueString() | ||
841 | 101 | metadata = { | ||
842 | 102 | PACKAGE_NAME: package_name, | ||
843 | 103 | TAGLINE: tagline, | ||
844 | 104 | CATEGORIES: categories, | ||
845 | 105 | } | ||
846 | 106 | tempdir.create_file(METADATA_FILE, json.dumps(metadata)) | ||
847 | 107 | # We need to create an executable in order to be able to generate a | ||
848 | 108 | # desktop. | ||
849 | 109 | tempdir.touch('executable', 0755) | ||
850 | 110 | expected_desktop_file = get_desktop_file( | ||
851 | 111 | package_name, tempdir.path, tagline=tagline, | ||
852 | 112 | categories=categories).get_contents() | ||
853 | 113 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) | ||
854 | 114 | info = backend.get_info(tempdir.path) | ||
855 | 115 | extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name] | ||
856 | 116 | desktop = json.loads(extra_files)['debian/%s.desktop' % (package_name,)] | ||
857 | 117 | self.assertEqual(expected_desktop_file, desktop) |