Merge lp:~sergiusens/snapcraft/cleanup into lp:~snappy-dev/snapcraft/core
- cleanup
- Merge into core
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Sergio Schvezov | ||||
Approved revision: | 212 | ||||
Merged at revision: | 247 | ||||
Proposed branch: | lp:~sergiusens/snapcraft/cleanup | ||||
Merge into: | lp:~snappy-dev/snapcraft/core | ||||
Diff against target: |
946 lines (+260/-210) 16 files modified
snapcraft/__init__.py (+63/-100) snapcraft/plugin.py (+8/-1) snapcraft/plugins/ant.py (+0/-4) snapcraft/plugins/catkin.py (+25/-11) snapcraft/plugins/jdk.py (+3/-0) snapcraft/plugins/make.py (+0/-3) snapcraft/plugins/maven.py (+0/-4) snapcraft/plugins/python2.py (+1/-1) snapcraft/plugins/python3.py (+1/-1) snapcraft/plugins/scons.py (+0/-3) snapcraft/repo.py (+15/-0) snapcraft/sources.py (+48/-0) snapcraft/tests/test_base_plugin.py (+25/-45) snapcraft/tests/test_common.py (+7/-0) snapcraft/tests/test_plugin.py (+1/-0) snapcraft/tests/test_sources.py (+63/-37) |
||||
To merge this branch: | bzr merge lp:~sergiusens/snapcraft/cleanup | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Leo Arias (community) | Approve | ||
John Lenton (community) | Approve | ||
Review via email: mp+274801@code.launchpad.net |
Commit message
Document and cleanup the plugin base class
This cleans up the base class to only expose things plugins will need, since the basic schema includes 'source' options it makes sense for pull to implement that as well automatically if supported.
This also moves everything from the base plugin the plugin.py (which should be renamed to lifecycle.py in a future MP, this one is already too big) and any other thing to its own supporting class.
This branch also includes all the plugin cleanup required for things to keep on working.
Description of the change
This all started with trying to get the catkin plugin out of using the private implementation (setup_
Leo Arias (elopio) wrote : | # |
This is a nice step forward, thanks.
I'm marking it needs fixing because of a couple of typos. Also some wording suggestions in the diff.
- 210. By Sergio Schvezov
-
Use a dictionary for source type handlers
- 211. By Sergio Schvezov
-
Compile the tar regex only once
Sergio Schvezov (sergiusens) wrote : | # |
Thanks for the reviews, I've updated da things
- 212. By Sergio Schvezov
-
Improve docstrings
Preview Diff
1 | === modified file 'snapcraft/__init__.py' |
2 | --- snapcraft/__init__.py 2015-10-14 20:00:25 +0000 |
3 | +++ snapcraft/__init__.py 2015-10-19 19:01:20 +0000 |
4 | @@ -17,7 +17,6 @@ |
5 | import contextlib |
6 | import logging |
7 | import os |
8 | -import re |
9 | |
10 | import snapcraft.common |
11 | import snapcraft.sources |
12 | @@ -31,15 +30,14 @@ |
13 | |
14 | @classmethod |
15 | def schema(cls): |
16 | - ''' |
17 | - Returns a json-schema for the plugin's properties as a dictionary. |
18 | + """Return a json-schema for the plugin's properties as a dictionary. |
19 | Of importance to plugin authors is the 'properties' keyword and |
20 | optionally the 'requires' keyword with a list of required |
21 | 'properties'. |
22 | |
23 | By default the the properties will be that of a standard VCS, override |
24 | in custom implementations if required. |
25 | - ''' |
26 | + """ |
27 | return { |
28 | '$schema': 'http://json-schema.org/draft-04/schema#', |
29 | 'type': 'object', |
30 | @@ -67,6 +65,7 @@ |
31 | |
32 | @property |
33 | def PLUGIN_STAGE_SOURCES(self): |
34 | + """Define additional sources.list.""" |
35 | return getattr(self, '_PLUGIN_STAGE_SOURCES', []) |
36 | |
37 | def __init__(self, name, options): |
38 | @@ -92,19 +91,74 @@ |
39 | |
40 | # The API |
41 | def pull(self): |
42 | - return True |
43 | + """Pull the source code and/or internal prereqs to build the part. |
44 | + |
45 | + By default, the base implementation for pull will use the following |
46 | + part properties to retrieve source code: |
47 | + |
48 | + - source |
49 | + - source-branch |
50 | + - source-tag |
51 | + - source-type |
52 | + |
53 | + If source is empty or does not exist, the phase will be skipped. |
54 | + |
55 | + Override or inherit from this method if you need to implement or |
56 | + enhance with custom pull logic. |
57 | + """ |
58 | + if not getattr(self.options, 'source', None): |
59 | + return True |
60 | + try: |
61 | + return snapcraft.sources.get( |
62 | + self.sourcedir, self.builddir, self.options) |
63 | + except ValueError as e: |
64 | + logger.error('Unrecognized source %r for part %r: %s.', |
65 | + self.options.source, self.name, e) |
66 | + snapcraft.common.fatal() |
67 | + except snapcraft.sources.IncompatibleOptionsError as e: |
68 | + logger.error( |
69 | + 'Issues while setting up sources for part \'%s\': %s.', |
70 | + self.name, |
71 | + e.message) |
72 | + snapcraft.common.fatal() |
73 | |
74 | def build(self): |
75 | + """Build the source code retrieved from the pull phase. |
76 | + |
77 | + The base implementation does nothing by default. Override this method |
78 | + if you need to process the source code to make it runnable. |
79 | + """ |
80 | return True |
81 | |
82 | def snap_fileset(self): |
83 | - """Returns one iteratables of globs specific to the plugin: |
84 | + """Return a list of files to include or exclude in the resulting snap |
85 | + |
86 | + The staging phase of a plugin's lifecycle may populate many things |
87 | + into the staging directory in order to succeed in building a project. |
88 | + During the stripping phase and in order to have a clean snap, the |
89 | + plugin can provide additional logic for stripping build components |
90 | + from the final snap and alleviate the part author from doing so for |
91 | + repetetive filesets. |
92 | + |
93 | + These are the rules to honor when creating such list: |
94 | + |
95 | - includes can be just listed |
96 | - excludes must be preceded by - |
97 | - For example: (['bin', 'lib', '-include'])""" |
98 | + |
99 | + For example:: |
100 | + (['bin', 'lib', '-include']) |
101 | + """ |
102 | return ([]) |
103 | |
104 | def env(self, root): |
105 | + """Return a list with the execution environment for building. |
106 | + |
107 | + Plugins often need special environment variables exported to the |
108 | + system for some builds to take place. This is a list of strings |
109 | + of the form key=value. The parameter root is the path to this part. |
110 | + |
111 | + :param str root: The root for the part |
112 | + """ |
113 | return [] |
114 | |
115 | # Helpers |
116 | @@ -113,7 +167,7 @@ |
117 | cwd = self.builddir |
118 | if True: |
119 | print(' '.join(cmd)) |
120 | - self.makedirs(cwd) |
121 | + os.makedirs(cwd, exist_ok=True) |
122 | return snapcraft.common.run(cmd, cwd=cwd, **kwargs) |
123 | |
124 | def run_output(self, cmd, cwd=None, **kwargs): |
125 | @@ -121,96 +175,5 @@ |
126 | cwd = self.builddir |
127 | if True: |
128 | print(' '.join(cmd)) |
129 | - self.makedirs(cwd) |
130 | + os.makedirs(cwd, exist_ok=True) |
131 | return snapcraft.common.run_output(cmd, cwd=cwd, **kwargs) |
132 | - |
133 | - def isurl(self, url): |
134 | - return snapcraft.common.isurl(url) |
135 | - |
136 | - def get_source(self, source, source_type=None, source_tag=None, |
137 | - source_branch=None): |
138 | - try: |
139 | - handler_class = _get_source_handler(source_type, source) |
140 | - except ValueError as e: |
141 | - logger.error('Unrecognized source %r for part %r: %s.', source, |
142 | - self.name, e) |
143 | - snapcraft.common.fatal() |
144 | - |
145 | - try: |
146 | - handler = handler_class(source, self.sourcedir, source_tag, |
147 | - source_branch) |
148 | - except snapcraft.sources.IncompatibleOptionsError as e: |
149 | - logger.error( |
150 | - 'Issues while setting up sources for part \'%s\': %s.', |
151 | - self.name, |
152 | - e.message) |
153 | - snapcraft.common.fatal() |
154 | - if not handler.pull(): |
155 | - return False |
156 | - return handler.provision(self.builddir) |
157 | - |
158 | - def handle_source_options(self): |
159 | - stype = getattr(self.options, 'source_type', None) |
160 | - stag = getattr(self.options, 'source_tag', None) |
161 | - sbranch = getattr(self.options, 'source_branch', None) |
162 | - return self.get_source(self.options.source, |
163 | - source_type=stype, |
164 | - source_tag=stag, |
165 | - source_branch=sbranch) |
166 | - |
167 | - def makedirs(self, d): |
168 | - os.makedirs(d, exist_ok=True) |
169 | - |
170 | - def setup_stage_packages(self): |
171 | - if self.stage_packages: |
172 | - ubuntu = snapcraft.repo.Ubuntu(self.ubuntudir, |
173 | - sources=self.PLUGIN_STAGE_SOURCES) |
174 | - ubuntu.get(self.stage_packages) |
175 | - ubuntu.unpack(self.installdir) |
176 | - self._fixup(self.installdir) |
177 | - |
178 | - def _fixup(self, root): |
179 | - if os.path.isfile(os.path.join(root, 'usr', 'bin', 'xml2-config')): |
180 | - self.run( |
181 | - ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. |
182 | - format(root), |
183 | - os.path.join(root, 'usr', 'bin', 'xml2-config')]) |
184 | - if os.path.isfile(os.path.join(root, 'usr', 'bin', 'xslt-config')): |
185 | - self.run( |
186 | - ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. |
187 | - format(root), |
188 | - os.path.join(root, 'usr', 'bin', 'xslt-config')]) |
189 | - |
190 | - |
191 | -def _get_source_handler(source_type, source): |
192 | - if not source_type: |
193 | - source_type = _get_source_type_from_uri(source) |
194 | - |
195 | - if source_type == 'bzr': |
196 | - handler = snapcraft.sources.Bazaar |
197 | - elif source_type == 'git': |
198 | - handler = snapcraft.sources.Git |
199 | - elif source_type == 'mercurial' or source_type == 'hg': |
200 | - handler = snapcraft.sources.Mercurial |
201 | - elif source_type == 'tar': |
202 | - handler = snapcraft.sources.Tar |
203 | - else: |
204 | - handler = snapcraft.sources.Local |
205 | - |
206 | - return handler |
207 | - |
208 | - |
209 | -def _get_source_type_from_uri(source): |
210 | - source_type = '' |
211 | - if source.startswith("bzr:") or source.startswith("lp:"): |
212 | - source_type = 'bzr' |
213 | - elif source.startswith("git:"): |
214 | - source_type = 'git' |
215 | - elif re.compile(r'.*\.((tar\.(xz|gz|bz2))|tgz)$').match(source): |
216 | - source_type = 'tar' |
217 | - elif snapcraft.common.isurl(source): |
218 | - raise ValueError('No handler to manage source') |
219 | - elif not os.path.isdir(source): |
220 | - raise ValueError('Local source is not a directory') |
221 | - |
222 | - return source_type |
223 | |
224 | === modified file 'snapcraft/plugin.py' |
225 | --- snapcraft/plugin.py 2015-10-15 17:01:43 +0000 |
226 | +++ snapcraft/plugin.py 2015-10-19 19:01:20 +0000 |
227 | @@ -137,6 +137,13 @@ |
228 | with open(self.statefile, 'w+') as f: |
229 | f.write(stage) |
230 | |
231 | + def _setup_stage_packages(self): |
232 | + if self.code.stage_packages: |
233 | + ubuntu = snapcraft.repo.Ubuntu( |
234 | + self.code.ubuntudir, sources=self.code.PLUGIN_STAGE_SOURCES) |
235 | + ubuntu.get(self.code.stage_packages) |
236 | + ubuntu.unpack(self.code.installdir) |
237 | + |
238 | def pull(self, force=False): |
239 | if not self.should_stage_run('pull', force): |
240 | return True |
241 | @@ -145,7 +152,7 @@ |
242 | self.notify_stage("Pulling") |
243 | |
244 | try: |
245 | - self.code.setup_stage_packages() |
246 | + self._setup_stage_packages() |
247 | except repo.PackageNotFoundError as e: |
248 | logger.error(e.message) |
249 | return False |
250 | |
251 | === modified file 'snapcraft/plugins/ant.py' |
252 | --- snapcraft/plugins/ant.py 2015-10-09 17:43:20 +0000 |
253 | +++ snapcraft/plugins/ant.py 2015-10-19 19:01:20 +0000 |
254 | @@ -33,10 +33,6 @@ |
255 | super().__init__(name, options) |
256 | self.build_packages.append('ant') |
257 | |
258 | - def pull(self): |
259 | - super().pull() |
260 | - return self.handle_source_options() |
261 | - |
262 | def build(self): |
263 | super().build() |
264 | if not self.run(['ant']): |
265 | |
266 | === modified file 'snapcraft/plugins/catkin.py' |
267 | --- snapcraft/plugins/catkin.py 2015-10-16 19:05:42 +0000 |
268 | +++ snapcraft/plugins/catkin.py 2015-10-19 19:01:20 +0000 |
269 | @@ -20,6 +20,7 @@ |
270 | import logging |
271 | |
272 | import snapcraft |
273 | +import snapcraft.repo |
274 | |
275 | logger = logging.getLogger(__name__) |
276 | |
277 | @@ -61,6 +62,19 @@ |
278 | self.dependencies = ['ros-core'] |
279 | self.package_deps_found = False |
280 | self.package_local_deps = {} |
281 | + self._deb_packages = [] |
282 | + |
283 | + def pull(self): |
284 | + if not super().pull(): |
285 | + return False |
286 | + |
287 | + try: |
288 | + self._setup_deb_packages() |
289 | + except snapcraft.repo.PackageNotFoundError as e: |
290 | + logger.error(e.message) |
291 | + return False |
292 | + |
293 | + return True |
294 | |
295 | def env(self, root): |
296 | return [ |
297 | @@ -124,19 +138,18 @@ |
298 | self.package_local_deps[pkg].add(dep) |
299 | continue |
300 | |
301 | - # If we're already getting this through a stage package, |
302 | + # If we're already getting this through a deb package, |
303 | # we don't need it |
304 | - if self.options.stage_packages and ( |
305 | - dep in self.options.stage_packages or |
306 | - dep.replace('_', '-') in self.options.stage_packages): |
307 | + if (dep in self._deb_packages or |
308 | + dep.replace('_', '-') in self._deb_packages): |
309 | continue |
310 | |
311 | # Get the ROS package for it |
312 | - self.stage_packages.append( |
313 | + self._deb_packages.append( |
314 | 'ros-'+self.options.rosversion+'-'+dep.replace('_', '-')) |
315 | |
316 | if dep == 'roscpp': |
317 | - self.stage_packages.append('g++') |
318 | + self._deb_packages.append('g++') |
319 | |
320 | def _find_package_deps(self): |
321 | if self.package_deps_found: |
322 | @@ -158,13 +171,14 @@ |
323 | |
324 | self.package_deps_found = True |
325 | |
326 | - def setup_stage_packages(self): |
327 | - if not self.handle_source_options(): |
328 | - return False |
329 | - |
330 | + def _setup_deb_packages(self): |
331 | self._find_package_deps() |
332 | |
333 | - return super().setup_stage_packages() |
334 | + if self._deb_packages: |
335 | + ubuntu = snapcraft.repo.Ubuntu( |
336 | + self.ubuntudir, sources=self.PLUGIN_STAGE_SOURCES) |
337 | + ubuntu.get(self._deb_packages) |
338 | + ubuntu.unpack(self.installdir) |
339 | |
340 | def _rosrun(self, commandlist, cwd=None): |
341 | with tempfile.NamedTemporaryFile(mode='w') as f: |
342 | |
343 | === modified file 'snapcraft/plugins/jdk.py' |
344 | --- snapcraft/plugins/jdk.py 2015-10-09 02:18:59 +0000 |
345 | +++ snapcraft/plugins/jdk.py 2015-10-19 19:01:20 +0000 |
346 | @@ -23,6 +23,9 @@ |
347 | super().__init__(name, options) |
348 | self.stage_packages.append('default-jdk') |
349 | |
350 | + def pull(self): |
351 | + return True |
352 | + |
353 | def env(self, root): |
354 | return ['JAVA_HOME=%s/usr/lib/jvm/default-java' % root, |
355 | 'PATH=%s/usr/lib/jvm/default-java/bin:' |
356 | |
357 | === modified file 'snapcraft/plugins/make.py' |
358 | --- snapcraft/plugins/make.py 2015-10-09 17:43:20 +0000 |
359 | +++ snapcraft/plugins/make.py 2015-10-19 19:01:20 +0000 |
360 | @@ -23,9 +23,6 @@ |
361 | super().__init__(name, options) |
362 | self.build_packages.append('make') |
363 | |
364 | - def pull(self): |
365 | - return self.handle_source_options() |
366 | - |
367 | def build(self): |
368 | return self.run(['make']) and \ |
369 | self.run(['make', 'install', 'DESTDIR=' + self.installdir]) |
370 | |
371 | === modified file 'snapcraft/plugins/maven.py' |
372 | --- snapcraft/plugins/maven.py 2015-10-09 17:43:20 +0000 |
373 | +++ snapcraft/plugins/maven.py 2015-10-19 19:01:20 +0000 |
374 | @@ -32,10 +32,6 @@ |
375 | super().__init__(name, options) |
376 | self.build_packages.append('maven') |
377 | |
378 | - def pull(self): |
379 | - super().pull() |
380 | - return self.handle_source_options() |
381 | - |
382 | def build(self): |
383 | super().build() |
384 | |
385 | |
386 | === modified file 'snapcraft/plugins/python2.py' |
387 | --- snapcraft/plugins/python2.py 2015-10-09 17:43:20 +0000 |
388 | +++ snapcraft/plugins/python2.py 2015-10-19 19:01:20 +0000 |
389 | @@ -45,7 +45,7 @@ |
390 | root, 'usr', 'lib', self.python_version, 'dist-packages')] |
391 | |
392 | def pull(self): |
393 | - if self.options.source and not self.handle_source_options(): |
394 | + if not super().pull(): |
395 | return False |
396 | |
397 | return self._pip() |
398 | |
399 | === modified file 'snapcraft/plugins/python3.py' |
400 | --- snapcraft/plugins/python3.py 2015-10-09 17:43:20 +0000 |
401 | +++ snapcraft/plugins/python3.py 2015-10-19 19:01:20 +0000 |
402 | @@ -45,7 +45,7 @@ |
403 | root, 'usr', 'lib', self.python_version, 'dist-packages')] |
404 | |
405 | def pull(self): |
406 | - if self.options.source and not self.handle_source_options(): |
407 | + if not super().pull(): |
408 | return False |
409 | |
410 | return self._pip() |
411 | |
412 | === modified file 'snapcraft/plugins/scons.py' |
413 | --- snapcraft/plugins/scons.py 2015-10-09 17:43:20 +0000 |
414 | +++ snapcraft/plugins/scons.py 2015-10-19 19:01:20 +0000 |
415 | @@ -40,9 +40,6 @@ |
416 | super().__init__(name, options) |
417 | self.build_packages.append('scons') |
418 | |
419 | - def pull(self): |
420 | - return self.handle_source_options() |
421 | - |
422 | def build(self): |
423 | env = os.environ.copy() |
424 | env['DESTDIR'] = self.installdir |
425 | |
426 | === modified file 'snapcraft/repo.py' |
427 | --- snapcraft/repo.py 2015-10-16 20:38:56 +0000 |
428 | +++ snapcraft/repo.py 2015-10-19 19:01:20 +0000 |
429 | @@ -135,6 +135,7 @@ |
430 | raise UnpackError(pkg) |
431 | |
432 | _fix_contents(rootdir) |
433 | + _fix_xml_tools(rootdir) |
434 | |
435 | def _manifest_dep_names(self): |
436 | manifest_dep_names = set() |
437 | @@ -252,6 +253,20 @@ |
438 | _fix_filemode(path) |
439 | |
440 | |
441 | +def _fix_xml_tools(root): |
442 | + xml2_config_path = os.path.join(root, 'usr', 'bin', 'xml2-config') |
443 | + if os.path.isfile(xml2_config_path): |
444 | + snapcraft.common.run( |
445 | + ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. |
446 | + format(root), xml2_config_path]) |
447 | + |
448 | + xslt_config_path = os.path.join(root, 'usr', 'bin', 'xslt-config') |
449 | + if os.path.isfile(xslt_config_path): |
450 | + snapcraft.common.run( |
451 | + ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. |
452 | + format(root), xslt_config_path]) |
453 | + |
454 | + |
455 | def _fix_filemode(path): |
456 | mode = stat.S_IMODE(os.stat(path).st_mode) |
457 | if mode & 0o4000 or mode & 0o2000: |
458 | |
459 | === modified file 'snapcraft/sources.py' |
460 | --- snapcraft/sources.py 2015-10-14 18:14:47 +0000 |
461 | +++ snapcraft/sources.py 2015-10-19 19:01:20 +0000 |
462 | @@ -227,3 +227,51 @@ |
463 | os.symlink(path, dst) |
464 | |
465 | return True |
466 | + |
467 | + |
468 | +def get(sourcedir, builddir, options): |
469 | + source_type = getattr(options, 'source_type', None) |
470 | + source_tag = getattr(options, 'source_tag', None) |
471 | + source_branch = getattr(options, 'source_branch', None) |
472 | + |
473 | + handler_class = _get_source_handler(source_type, options.source) |
474 | + handler = handler_class(options.source, sourcedir, source_tag, |
475 | + source_branch) |
476 | + if not handler.pull(): |
477 | + return False |
478 | + return handler.provision(builddir) |
479 | + |
480 | + |
481 | +_source_handler = { |
482 | + 'bzr': Bazaar, |
483 | + 'git': Git, |
484 | + 'hg': Mercurial, |
485 | + 'mercurial': Mercurial, |
486 | + 'tar': Tar, |
487 | +} |
488 | + |
489 | + |
490 | +def _get_source_handler(source_type, source): |
491 | + if not source_type: |
492 | + source_type = _get_source_type_from_uri(source) |
493 | + |
494 | + return _source_handler.get(source_type, Local) |
495 | + |
496 | + |
497 | +_tar_type_regex = re.compile(r'.*\.((tar\.(xz|gz|bz2))|tgz)$') |
498 | + |
499 | + |
500 | +def _get_source_type_from_uri(source): |
501 | + source_type = '' |
502 | + if source.startswith("bzr:") or source.startswith("lp:"): |
503 | + source_type = 'bzr' |
504 | + elif source.startswith("git:"): |
505 | + source_type = 'git' |
506 | + elif _tar_type_regex.match(source): |
507 | + source_type = 'tar' |
508 | + elif snapcraft.common.isurl(source): |
509 | + raise ValueError('No handler to manage source') |
510 | + elif not os.path.isdir(source): |
511 | + raise ValueError('Local source is not a directory') |
512 | + |
513 | + return source_type |
514 | |
515 | === modified file 'snapcraft/tests/test_base_plugin.py' |
516 | --- snapcraft/tests/test_base_plugin.py 2015-10-14 20:00:25 +0000 |
517 | +++ snapcraft/tests/test_base_plugin.py 2015-10-19 19:01:20 +0000 |
518 | @@ -16,30 +16,32 @@ |
519 | |
520 | import fixtures |
521 | import logging |
522 | -import os |
523 | import unittest.mock |
524 | |
525 | import snapcraft |
526 | from snapcraft import tests |
527 | |
528 | |
529 | +class MockOptions: |
530 | + |
531 | + def __init__(self, source, source_type=None, source_branch=None, |
532 | + source_tag=None): |
533 | + self.source = source |
534 | + self.source_type = source_type |
535 | + self.source_branch = source_branch |
536 | + self.source_tag = source_tag |
537 | + |
538 | + |
539 | class TestBasePlugin(tests.TestCase): |
540 | |
541 | - def test_isurl(self): |
542 | - plugin = snapcraft.BasePlugin('mock', {}) |
543 | - self.assertTrue(plugin.isurl('git://')) |
544 | - self.assertTrue(plugin.isurl('bzr://')) |
545 | - self.assertFalse(plugin.isurl('./')) |
546 | - self.assertFalse(plugin.isurl('/foo')) |
547 | - self.assertFalse(plugin.isurl('/fo:o')) |
548 | - |
549 | def test_get_source_with_unrecognized_source_must_raise_error(self): |
550 | fake_logger = fixtures.FakeLogger(level=logging.ERROR) |
551 | self.useFixture(fake_logger) |
552 | |
553 | - plugin = snapcraft.BasePlugin('test_plugin', 'dummy_options') |
554 | + options = MockOptions('unrecognized://test_source') |
555 | + plugin = snapcraft.BasePlugin('test_plugin', options) |
556 | with self.assertRaises(SystemExit) as raised: |
557 | - plugin.get_source('unrecognized://test_source') |
558 | + plugin.pull() |
559 | |
560 | self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.') |
561 | expected = ( |
562 | @@ -52,10 +54,11 @@ |
563 | fake_logger = fixtures.FakeLogger(level=logging.ERROR) |
564 | self.useFixture(fake_logger) |
565 | |
566 | + options = MockOptions('file') |
567 | mock_isdir.return_value = False |
568 | - plugin = snapcraft.BasePlugin('test_plugin', 'dummy_options') |
569 | + plugin = snapcraft.BasePlugin('test_plugin', options) |
570 | with self.assertRaises(SystemExit) as raised: |
571 | - plugin.get_source('file') |
572 | + plugin.pull() |
573 | |
574 | mock_isdir.assert_called_once_with('file') |
575 | self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.') |
576 | @@ -64,30 +67,6 @@ |
577 | "Local source is not a directory.\n") |
578 | self.assertEqual(expected, fake_logger.output) |
579 | |
580 | - def test_makedirs_with_existing_dir(self): |
581 | - plugin = snapcraft.BasePlugin('dummy_plugin', 'dummy_options') |
582 | - plugin.makedirs(self.path) |
583 | - self.assertTrue(os.path.exists(self.path)) |
584 | - |
585 | - def test_makedirs_with_unexisting_dir(self): |
586 | - path = os.path.join(self.path, 'unexisting') |
587 | - plugin = snapcraft.BasePlugin('dummy_plugin', 'dummy_options') |
588 | - plugin.makedirs(path) |
589 | - self.assertTrue(os.path.exists(path)) |
590 | - |
591 | - def test_get_tar_source_from_uri(self): |
592 | - sources = [ |
593 | - 'https://golang.tar.gz', |
594 | - 'https://golang.tar.xz', |
595 | - 'https://golang.tar.bz2', |
596 | - 'https://golang.tar.tgz', |
597 | - ] |
598 | - |
599 | - for source in sources: |
600 | - with self.subTest(key=source): |
601 | - self.assertEqual( |
602 | - snapcraft._get_source_type_from_uri(source), 'tar') |
603 | - |
604 | |
605 | class GetSourceWithBranches(tests.TestCase): |
606 | |
607 | @@ -108,11 +87,11 @@ |
608 | fake_logger = fixtures.FakeLogger(level=logging.ERROR) |
609 | self.useFixture(fake_logger) |
610 | |
611 | - plugin = snapcraft.BasePlugin('test_plugin', 'dummy_options') |
612 | + options = MockOptions('lp:source', self.source_type, |
613 | + self.source_branch, self.source_tag) |
614 | + plugin = snapcraft.BasePlugin('test_plugin', options) |
615 | with self.assertRaises(SystemExit) as raised: |
616 | - plugin.get_source( |
617 | - 'dummy_source', source_type=self.source_type, |
618 | - source_branch=self.source_branch, source_tag=self.source_tag) |
619 | + plugin.pull() |
620 | |
621 | self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.') |
622 | expected = ( |
623 | @@ -146,11 +125,12 @@ |
624 | fake_logger = fixtures.FakeLogger(level=logging.ERROR) |
625 | self.useFixture(fake_logger) |
626 | |
627 | - plugin = snapcraft.BasePlugin('test_plugin', 'dummy_options') |
628 | + options = MockOptions('lp:this', self.source_type, self.source_branch, |
629 | + self.source_tag) |
630 | + plugin = snapcraft.BasePlugin('test_plugin', options) |
631 | + |
632 | with self.assertRaises(SystemExit) as raised: |
633 | - plugin.get_source( |
634 | - 'dummy_source', source_type=self.source_type, |
635 | - source_branch=self.source_branch, source_tag=self.source_tag) |
636 | + plugin.pull() |
637 | |
638 | self.assertEqual(raised.exception.code, 1, 'Wrong exit code returned.') |
639 | expected = ( |
640 | |
641 | === modified file 'snapcraft/tests/test_common.py' |
642 | --- snapcraft/tests/test_common.py 2015-07-23 17:26:18 +0000 |
643 | +++ snapcraft/tests/test_common.py 2015-10-19 19:01:20 +0000 |
644 | @@ -40,3 +40,10 @@ |
645 | plugindir = os.path.join(self.path, 'testplugin') |
646 | common.set_plugindir(plugindir) |
647 | self.assertEqual(plugindir, common.get_plugindir()) |
648 | + |
649 | + def test_isurl(self): |
650 | + self.assertTrue(common.isurl('git://')) |
651 | + self.assertTrue(common.isurl('bzr://')) |
652 | + self.assertFalse(common.isurl('./')) |
653 | + self.assertFalse(common.isurl('/foo')) |
654 | + self.assertFalse(common.isurl('/fo:o')) |
655 | |
656 | === modified file 'snapcraft/tests/test_plugin.py' |
657 | --- snapcraft/tests/test_plugin.py 2015-10-09 17:43:20 +0000 |
658 | +++ snapcraft/tests/test_plugin.py 2015-10-19 19:01:20 +0000 |
659 | @@ -52,6 +52,7 @@ |
660 | p.statefile = tempfile.NamedTemporaryFile().name |
661 | self.addCleanup(os.remove, p.statefile) |
662 | p.code = Mock() |
663 | + p._setup_stage_packages = Mock() |
664 | # pull once |
665 | p.pull() |
666 | p.code.pull.assert_called() |
667 | |
668 | === modified file 'snapcraft/tests/test_sources.py' |
669 | --- snapcraft/tests/test_sources.py 2015-10-14 18:14:47 +0000 |
670 | +++ snapcraft/tests/test_sources.py 2015-10-19 19:01:20 +0000 |
671 | @@ -19,7 +19,8 @@ |
672 | import threading |
673 | import unittest.mock |
674 | |
675 | -from snapcraft import sources |
676 | +import snapcraft.sources |
677 | + |
678 | from snapcraft import tests |
679 | |
680 | |
681 | @@ -56,7 +57,7 @@ |
682 | tar_file_name = 'test.tar' |
683 | source = 'http://{}:{}/{file_name}'.format( |
684 | *server.server_address, file_name=tar_file_name) |
685 | - tar_source = sources.Tar(source, dest_dir) |
686 | + tar_source = snapcraft.sources.Tar(source, dest_dir) |
687 | |
688 | self.assertTrue(tar_source.pull()) |
689 | |
690 | @@ -87,7 +88,7 @@ |
691 | class TestBazaar(SourceTestCase): |
692 | |
693 | def test_pull(self): |
694 | - bzr = sources.Bazaar('lp:my-source', 'source_dir') |
695 | + bzr = snapcraft.sources.Bazaar('lp:my-source', 'source_dir') |
696 | |
697 | bzr.pull() |
698 | |
699 | @@ -96,7 +97,8 @@ |
700 | ['bzr', 'branch', 'lp:my-source', 'source_dir'], cwd=os.getcwd()) |
701 | |
702 | def test_pull_tag(self): |
703 | - bzr = sources.Bazaar('lp:my-source', 'source_dir', source_tag='tag') |
704 | + bzr = snapcraft.sources.Bazaar( |
705 | + 'lp:my-source', 'source_dir', source_tag='tag') |
706 | bzr.pull() |
707 | |
708 | self.mock_run.assert_called_once_with( |
709 | @@ -106,7 +108,8 @@ |
710 | def test_pull_existing_with_tag(self): |
711 | self.mock_path_exists.return_value = True |
712 | |
713 | - bzr = sources.Bazaar('lp:my-source', 'source_dir', source_tag='tag') |
714 | + bzr = snapcraft.sources.Bazaar( |
715 | + 'lp:my-source', 'source_dir', source_tag='tag') |
716 | bzr.pull() |
717 | |
718 | self.mock_run.assert_called_once_with( |
719 | @@ -114,15 +117,17 @@ |
720 | 'source_dir'], cwd=os.getcwd()) |
721 | |
722 | def test_provision(self): |
723 | - bzr = sources.Bazaar('lp:my-source', 'source_dir') |
724 | + bzr = snapcraft.sources.Bazaar('lp:my-source', 'source_dir') |
725 | bzr.provision('dst') |
726 | |
727 | self.mock_run.assert_called_once_with( |
728 | ['cp', '-Trfa', 'source_dir', 'dst'], cwd=os.getcwd()) |
729 | |
730 | def test_init_with_source_branch_raises_exception(self): |
731 | - with self.assertRaises(sources.IncompatibleOptionsError) as raised: |
732 | - sources.Bazaar('lp:mysource', 'source_dir', source_branch='branch') |
733 | + with self.assertRaises( |
734 | + snapcraft.sources.IncompatibleOptionsError) as raised: |
735 | + snapcraft.sources.Bazaar('lp:mysource', 'source_dir', |
736 | + source_branch='branch') |
737 | |
738 | expected_message = 'can\'t specify a source-branch for a bzr source' |
739 | self.assertEqual(raised.exception.message, expected_message) |
740 | @@ -131,7 +136,7 @@ |
741 | class TestGit(SourceTestCase): |
742 | |
743 | def test_pull(self): |
744 | - git = sources.Git('git://my-source', 'source_dir') |
745 | + git = snapcraft.sources.Git('git://my-source', 'source_dir') |
746 | |
747 | git.pull() |
748 | |
749 | @@ -139,8 +144,8 @@ |
750 | ['git', 'clone', 'git://my-source', 'source_dir'], cwd=os.getcwd()) |
751 | |
752 | def test_pull_branch(self): |
753 | - git = sources.Git('git://my-source', 'source_dir', |
754 | - source_branch='my-branch') |
755 | + git = snapcraft.sources.Git('git://my-source', 'source_dir', |
756 | + source_branch='my-branch') |
757 | git.pull() |
758 | |
759 | self.mock_run.assert_called_once_with( |
760 | @@ -148,7 +153,8 @@ |
761 | 'source_dir'], cwd=os.getcwd()) |
762 | |
763 | def test_pull_tag(self): |
764 | - git = sources.Git('git://my-source', 'source_dir', source_tag='tag') |
765 | + git = snapcraft.sources.Git('git://my-source', 'source_dir', |
766 | + source_tag='tag') |
767 | git.pull() |
768 | |
769 | self.mock_run.assert_called_once_with( |
770 | @@ -158,7 +164,7 @@ |
771 | def test_pull_existing(self): |
772 | self.mock_path_exists.return_value = True |
773 | |
774 | - git = sources.Git('git://my-source', 'source_dir') |
775 | + git = snapcraft.sources.Git('git://my-source', 'source_dir') |
776 | git.pull() |
777 | |
778 | self.mock_run.assert_called_once_with( |
779 | @@ -168,7 +174,8 @@ |
780 | def test_pull_existing_with_tag(self): |
781 | self.mock_path_exists.return_value = True |
782 | |
783 | - git = sources.Git('git://my-source', 'source_dir', source_tag='tag') |
784 | + git = snapcraft.sources.Git('git://my-source', 'source_dir', |
785 | + source_tag='tag') |
786 | git.pull() |
787 | |
788 | self.mock_run.assert_called_once_with( |
789 | @@ -178,8 +185,8 @@ |
790 | def test_pull_existing_with_branch(self): |
791 | self.mock_path_exists.return_value = True |
792 | |
793 | - git = sources.Git('git://my-source', 'source_dir', |
794 | - source_branch='my-branch') |
795 | + git = snapcraft.sources.Git('git://my-source', 'source_dir', |
796 | + source_branch='my-branch') |
797 | git.pull() |
798 | |
799 | self.mock_run.assert_called_once_with( |
800 | @@ -187,16 +194,17 @@ |
801 | 'refs/heads/my-branch'], cwd=os.getcwd()) |
802 | |
803 | def test_provision(self): |
804 | - bzr = sources.Git('git://my-source', 'source_dir') |
805 | + bzr = snapcraft.sources.Git('git://my-source', 'source_dir') |
806 | bzr.provision('dst') |
807 | |
808 | self.mock_run.assert_called_once_with( |
809 | ['cp', '-Trfa', 'source_dir', 'dst'], cwd=os.getcwd()) |
810 | |
811 | def test_init_with_source_branch_and_tag_raises_exception(self): |
812 | - with self.assertRaises(sources.IncompatibleOptionsError) as raised: |
813 | - sources.Git('git://mysource', 'source_dir', source_tag='tag', |
814 | - source_branch='branch') |
815 | + with self.assertRaises( |
816 | + snapcraft.sources.IncompatibleOptionsError) as raised: |
817 | + snapcraft.sources.Git('git://mysource', 'source_dir', |
818 | + source_tag='tag', source_branch='branch') |
819 | |
820 | expected_message = \ |
821 | 'can\'t specify both source-tag and source-branch for a git source' |
822 | @@ -206,15 +214,15 @@ |
823 | class TestMercurial(SourceTestCase): |
824 | |
825 | def test_pull(self): |
826 | - hg = sources.Mercurial('hg://my-source', 'source_dir') |
827 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir') |
828 | hg.pull() |
829 | |
830 | self.mock_run.assert_called_once_with( |
831 | ['hg', 'clone', 'hg://my-source', 'source_dir'], cwd=os.getcwd()) |
832 | |
833 | def test_pull_branch(self): |
834 | - hg = sources.Mercurial('hg://my-source', 'source_dir', |
835 | - source_branch='my-branch') |
836 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir', |
837 | + source_branch='my-branch') |
838 | hg.pull() |
839 | |
840 | self.mock_run.assert_called_once_with( |
841 | @@ -222,8 +230,8 @@ |
842 | 'source_dir'], cwd=os.getcwd()) |
843 | |
844 | def test_pull_tag(self): |
845 | - hg = sources.Mercurial('hg://my-source', 'source_dir', |
846 | - source_tag='tag') |
847 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir', |
848 | + source_tag='tag') |
849 | hg.pull() |
850 | |
851 | self.mock_run.assert_called_once_with( |
852 | @@ -233,7 +241,7 @@ |
853 | def test_pull_existing(self): |
854 | self.mock_path_exists.return_value = True |
855 | |
856 | - hg = sources.Mercurial('hg://my-source', 'source_dir') |
857 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir') |
858 | hg.pull() |
859 | |
860 | self.mock_run.assert_called_once_with( |
861 | @@ -242,8 +250,8 @@ |
862 | def test_pull_existing_with_tag(self): |
863 | self.mock_path_exists.return_value = True |
864 | |
865 | - hg = sources.Mercurial('hg://my-source', 'source_dir', |
866 | - source_tag='tag') |
867 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir', |
868 | + source_tag='tag') |
869 | hg.pull() |
870 | |
871 | self.mock_run.assert_called_once_with( |
872 | @@ -252,8 +260,8 @@ |
873 | def test_pull_existing_with_branch(self): |
874 | self.mock_path_exists.return_value = True |
875 | |
876 | - hg = sources.Mercurial('hg://my-source', 'source_dir', |
877 | - source_branch='my-branch') |
878 | + hg = snapcraft.sources.Mercurial('hg://my-source', 'source_dir', |
879 | + source_branch='my-branch') |
880 | hg.pull() |
881 | |
882 | self.mock_run.assert_called_once_with( |
883 | @@ -261,16 +269,18 @@ |
884 | cwd=os.getcwd()) |
885 | |
886 | def test_provision(self): |
887 | - bzr = sources.Mercurial('hg://my-source', 'source_dir') |
888 | + bzr = snapcraft.sources.Mercurial('hg://my-source', 'source_dir') |
889 | bzr.provision('dst') |
890 | |
891 | self.mock_run.assert_called_once_with( |
892 | ['cp', '-Trfa', 'source_dir', 'dst'], cwd=os.getcwd()) |
893 | |
894 | def test_init_with_source_branch_and_tag_raises_exception(self): |
895 | - with self.assertRaises(sources.IncompatibleOptionsError) as raised: |
896 | - sources.Mercurial('hg://mysource', 'source_dir', source_tag='tag', |
897 | - source_branch='branch') |
898 | + with self.assertRaises( |
899 | + snapcraft.sources.IncompatibleOptionsError) as raised: |
900 | + snapcraft.sources.Mercurial( |
901 | + 'hg://mysource', 'source_dir', source_tag='tag', |
902 | + source_branch='branch') |
903 | |
904 | expected_message = ( |
905 | 'can\'t specify both source-tag and source-branch for a mercurial ' |
906 | @@ -303,11 +313,11 @@ |
907 | self.addCleanup(patcher.stop) |
908 | |
909 | def test_pull(self): |
910 | - local = sources.Local('.', 'source_dir') |
911 | + local = snapcraft.sources.Local('.', 'source_dir') |
912 | self.assertTrue(local.pull()) |
913 | |
914 | def test_provision(self): |
915 | - local = sources.Local('.', 'source_dir') |
916 | + local = snapcraft.sources.Local('.', 'source_dir') |
917 | local.provision('dst') |
918 | |
919 | self.mock_rmdir.assert_called_once_with('dst') |
920 | @@ -317,9 +327,25 @@ |
921 | def test_provision_when_target_is_file(self): |
922 | self.mock_isdir.return_value = False |
923 | |
924 | - local = sources.Local('.', 'source_dir') |
925 | + local = snapcraft.sources.Local('.', 'source_dir') |
926 | local.provision('dst') |
927 | |
928 | self.mock_remove.assert_called_once_with('dst') |
929 | self.mock_symlink.assert_called_once_with( |
930 | '/home/ubuntu/sources/snap/source', 'dst') |
931 | + |
932 | + |
933 | +class TestUri(tests.TestCase): |
934 | + |
935 | + def test_get_tar_source_from_uri(self): |
936 | + sources = [ |
937 | + 'https://golang.tar.gz', |
938 | + 'https://golang.tar.xz', |
939 | + 'https://golang.tar.bz2', |
940 | + 'https://golang.tar.tgz', |
941 | + ] |
942 | + |
943 | + for source in sources: |
944 | + with self.subTest(key=source): |
945 | + self.assertEqual( |
946 | + snapcraft.sources._get_source_type_from_uri(source), 'tar') |
Looks good. A couple of comments on code that I know is just moved, so not a blocker to land.