Skip to content

Commit

Permalink
Merge branch 'master' into bugs/1591208
Browse files Browse the repository at this point in the history
  • Loading branch information
josepht committed Jun 27, 2016
2 parents 79e7937 + 1470009 commit 435a715
Show file tree
Hide file tree
Showing 21 changed files with 413 additions and 71 deletions.
1 change: 1 addition & 0 deletions .bzrignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ dist
htmlcov
__pycache__
docs/**.html
*.swp
59 changes: 59 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
snapcraft (2.12) xenial; urgency=medium

[ Simon Quigley ]
* Change apt-get to apt in HACKING.md (#564) (LP: #1591421)
* Changed the mailing list in HACKING.md from snappy-devel to snapcraft
(#577)
* Add Subversion support (#567) (LP: #1543243)

[ Joe Talbott ]
* Include 'maintainer' and 'description' in the parser output. (#565)
(LP: #1591199)
* Support "```" wiki code tags in the parser. (#569) (LP: #1592133)
* Add snapcraft-parser integration test. (#560) (LP: #1590268)
* Make most wiki fields required. (#581) (LP: #LP: #1592133)
* Add more info about reusable parts. (#527) (LP: #1582499)
* Allow parts without a 'source' entry. (#599)

[ Sergio Schvezov ]
* New plugin: gulp (#563) (LP: #1575880)
* Support for a hidden snapcraft.yaml (#582) (LP: #1587933)
* Implement `snapcraft update` for parts (#588) (LP: #1594643)
* Support updating cache without content-length (#598) (LP: #1595610)
* Switch from local copy to the proper python package. (LP: #1590813)
* Integrate with new remote parts (#590) (LP: #1594976)
* Implement `snapcraft define` for parts (#594) (LP: #1594643)
* Update the remote parts cache before demo tests (#604) (LP: #1596114)
* Add missing build-packages for rpath test (#605) (LP: #1596114)
* Implement snapcraft search (#608) (LP: #1596222)

[ Bayard Randel ]
* Ignore .eggs dir. (#572)

[ Leo Arias ]
* Use pexpect when testing the building of snaps (#573) (LP: #1592943)
* Allow to run a subset of integration tests. (#576) (LP: #1593009)
* Improve the store errors returning exceptions (#585) (LP: #1594636)
* Add the register command (#586) (LP: #1595012)
* Improve error reporting (#591) (LP: #1588023)
* Fix the store update test to register a unique name (#595) (LP: #1595319)
* Use a xenial docker container for travis executions (#597) (LP: #1532213)
* Simplify the list plugins integration test (#607) (LP: #1596112)
* Remove the unittests from the autopkgtest execution (#600) (LP: #1596068)

[ Evan Dandrea ]
* Make lxd containers ephemeral. (#578) (LP: #1577548)

[ Daniel Holbach ]
* it's myapps.developer.ubuntu.com (#587) (LP: #1594844)

[ Rob Loach ]
* Fix Snap icons for Demos (#574)

[ Kyle Fazzari ]
* Add qmake plugin. (#566) (LP: #1574774)
* Don't copy libraries that are already in prime. (#580) (LP: #1570895)
* Make app names more restrictive. (#555) (LP: #1589613)

-- Sergio Schvezov <sergio.schvezov@ubuntu.com> Mon, 27 Jun 2016 13:58:10 -0300

snapcraft (2.11) xenial; urgency=medium

[ Leo Arias ]
Expand Down
2 changes: 1 addition & 1 deletion debian/copyright
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ License: GPL-3

Files: snapcraft/demos/qt4-text-editor/* snapcraft/demos/qt5-text-editor/*
Copyright: 2015 The Qt Company Ltd.
License: BSD
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
.
Expand Down
4 changes: 0 additions & 4 deletions debian/tests/control
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
Tests: unittests
Restrictions: allow-stderr
Depends: @builddeps@

Tests: integrationtests
Restrictions: allow-stderr, isolation-container, rw-build-tree
Depends: @,
Expand Down
2 changes: 0 additions & 2 deletions debian/tests/unittests

This file was deleted.

1 change: 1 addition & 0 deletions integration_tests/snaps/rpath-test/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ confinement: strict
parts:
rpath-test:
plugin: make
build-packages: [gcc, g++, libc6-dev]
source: src/
20 changes: 14 additions & 6 deletions integration_tests/test_list_plugins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2015-2016 Canonical Ltd
# Copyright (C) 2015, 2016 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -14,15 +14,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import pkgutil

from snapcraft import plugins

import integration_tests

from testtools.matchers import HasLength


class ListPluginsTestCase(integration_tests.TestCase):

def test_list_plugins(self):
output = self.run_snapcraft('list-plugins')
expected = (
'ant cmake gulp kernel nil python3 tar-content\n'
'autotools copy jdk make nodejs qmake \n'
'catkin go kbuild maven python2 scons \n')
self.assertEqual(expected, output)
expected = [
module_name.replace('_', '-') for _, module_name, _ in
pkgutil.iter_modules(plugins.__path__)
]
for plugin in expected:
self.assertIn(plugin, output)
self.assertThat(output.split(), HasLength(len(expected)))
26 changes: 22 additions & 4 deletions integration_tests/test_parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,29 @@ def test_update(self):
self.assertTrue(os.path.exists(self.parts_yaml))
self.assertTrue(os.path.exists(self.headers_yaml))

def test_curl_exists(self):
def test_curl_exists_and_properly_defined(self):
"""Curl is used in most of the demos so we test for its existence."""
self.run_snapcraft('update')
output = self.run_snapcraft(['define', 'curl'])

with open(self.parts_yaml) as parts_file:
parts = yaml.load(parts_file)
expected = """Maintainer: 'Sergio Schvezov <sergio.schvezov@ubuntu.com>'
Description: 'A tool and a library (usable from many languages) for client side URL transfers, supporting FTP, FTPS, HTTP, HTTPS, TELNET, DICT, FILE and LDAP.'
self.assertTrue('curl' in parts, parts)
curl:
configflags:
- --enable-static
- --enable-shared
- --disable-manual
plugin: autotools
snap:
- -bin
- -lib/*.a
- -lib/pkgconfig
- -lib/*.la
- -include
- -share
source: http://curl.haxx.se/download/curl-7.44.0.tar.bz2
source-type: tar
"""

self.assertEqual(expected, output)
10 changes: 10 additions & 0 deletions snapcraft/internal/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ def _search_and_replace_contents(file_path, search_pattern, replacement):
f.write(replaced)


def get_terminal_width(max_width=MAX_CHARACTERS_WRAP):
if os.isatty(sys.stdout.fileno()):
width = shutil.get_terminal_size().columns
else:
width = MAX_CHARACTERS_WRAP
if max_width:
width = min(max_width, width)
return width


def format_output_in_columns(elements_list, max_width=MAX_CHARACTERS_WRAP,
num_col_spaces=2):
"""Return a formatted list of strings ready to be printed line by line
Expand Down
71 changes: 68 additions & 3 deletions snapcraft/internal/parts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import difflib
import logging
import os
import sys

import requests
import yaml
Expand All @@ -28,7 +30,13 @@
)
from xdg import BaseDirectory

from snapcraft.internal.common import get_terminal_width


PARTS_URI = 'https://parts.snapcraft.io/v1/parts.yaml'
_MATCH_RATIO = 0.6
_HEADER_PART_NAME = 'PART NAME'
_HEADER_DESCRIPTION = 'DESCRIPTION'

logging.getLogger("urllib3").setLevel(logging.CRITICAL)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -109,12 +117,29 @@ def __init__(self):
else:
self._parts = {}

def get_part(self, part_name):
def get_part(self, part_name, full=False):
remote_part = self._parts[part_name].copy()
for key in ['description', 'maintainer']:
remote_part.pop(key)
if not full:
for key in ['description', 'maintainer']:
remote_part.pop(key)
return remote_part

def matches_for(self, part_match, max_len=0):
matcher = difflib.SequenceMatcher(isjunk=None, autojunk=False)
matcher.set_seq2(part_match)

matching_parts = {}
for part_name in self._parts.keys():
matcher.set_seq1(part_name)
add_part_name = matcher.ratio() >= _MATCH_RATIO

if add_part_name or (part_match in part_name):
matching_parts[part_name] = self._parts[part_name]
if len(part_name) > max_len:
max_len = len(part_name)

return matching_parts, max_len

def compose(self, part_name, properties):
"""Return properties composed with the ones from part name in the wiki.
:param str part_name: The name of the part to query from the wiki
Expand All @@ -134,5 +159,45 @@ def update():
_Update().execute()


def define(part_name):
try:
remote_part = _RemoteParts().get_part(part_name, full=True)
except KeyError as e:
raise RuntimeError(
'Cannot find the part name {!r} in the cache. Please '
'consider going to https://wiki.ubuntu.com/snapcraft/parts '
'to add it.') from e
print('Maintainer: {!r}'.format(remote_part.pop('maintainer')))
print('Description: {!r}'.format(remote_part.pop('description')))
print('')
yaml.dump({part_name: remote_part},
default_flow_style=False, stream=sys.stdout)


def search(part_match):
header_len = len(_HEADER_PART_NAME)
matches, part_length = _RemoteParts().matches_for(part_match, header_len)

terminal_width = get_terminal_width(max_width=None)
part_length = max(part_length, header_len)
# <space> + <space> + <description> + ... = 5
description_space = terminal_width - part_length - 5

if not matches:
# apt search does not return error, we probably shouldn't either.
logger.info('No matches found, try to run `snapcraft update` to '
'refresh the remote parts cache.')
return

print('{} {}'.format(
_HEADER_PART_NAME.ljust(part_length, ' '), _HEADER_DESCRIPTION))
for part_key in matches.keys():
description = matches[part_key]['description']
if len(description) > description_space:
description = '{}...'.format(description[0:description_space])
print('{} {}'.format(
part_key.ljust(part_length, ' '), description))


def get_remote_parts():
return _RemoteParts()
25 changes: 12 additions & 13 deletions snapcraft/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
snapcraft [options] list-plugins
snapcraft [options] tour [<directory>]
snapcraft [options] update
snapcraft [options] define <part-name>
snapcraft [options] search [<query> ...]
snapcraft [options] help (topics | <plugin> | <topic>) [--devel]
snapcraft (-h | --help)
snapcraft --version
Expand Down Expand Up @@ -91,6 +93,8 @@
Parts ecosystem commands
update Updates the parts listing from the cloud.
define Shows the definition for the cloud part.
search Searches the remotes part cache for matching parts.
Calling snapcraft without a COMMAND will default to 'snap'
Expand All @@ -104,22 +108,22 @@
http://developer.ubuntu.com/snappy/snapcraft
"""

from contextlib import suppress
import logging
import os
import pkg_resources
import pkgutil
import shutil
import sys
import subprocess
import textwrap

from docopt import docopt

import snapcraft
from snapcraft.internal import lifecycle, log, parts
from snapcraft.internal.common import (
format_output_in_columns, MAX_CHARACTERS_WRAP, get_tourdir)
format_output_in_columns,
get_terminal_width,
get_tourdir)


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -167,16 +171,7 @@ def _list_plugins():
plugins.append(modname.replace('_', '-'))

# we wrap the output depending on terminal size
width = MAX_CHARACTERS_WRAP
with suppress(OSError):
with suppress(subprocess.CalledProcessError):
# this is the only way to get current terminal size reliably
# without duplicating a bunch of logic
command = ['tput', 'cols']
candidate_width = \
subprocess.check_output(command, stderr=subprocess.DEVNULL)
width = min(int(candidate_width), width)

width = get_terminal_width()
for line in format_output_in_columns(plugins, max_width=width):
print(line)

Expand Down Expand Up @@ -256,6 +251,10 @@ def run(args, project_options): # noqa
args['--devel'], args['topics'])
elif args['update']:
parts.update()
elif args['define']:
parts.define(args['<part-name>'])
elif args['search']:
parts.search(' '.join(args['<query>']))
else: # snap by default:
lifecycle.snap(project_options, args['<directory>'], args['--output'])

Expand Down
8 changes: 7 additions & 1 deletion snapcraft/tests/fake_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,16 @@ def do_GET(self):
'description': 'test entry for part1',
'maintainer': 'none',
},
'long-described-part': {
'plugin': 'go',
'source': 'http://source.tar.gz',
'description': 'this is a repetitive description ' * 3,
'maintainer': 'none',
},
}
self.send_header('Content-Type', 'text/plain')
if 'NO_CONTENT_LENGTH' not in os.environ:
self.send_header('Content-Length', '300')
self.send_header('Content-Length', '1000')
self.send_header('ETag', '1111')
self.end_headers()
self.wfile.write(yaml.dump(response).encode())
Expand Down

0 comments on commit 435a715

Please sign in to comment.