cli: pull command migrated to docopts #145

Merged
merged 1 commit into from Dec 3, 2015
Jump to file or symbol
Failed to load files and symbols.
+238 −265
Split
View
@@ -14,83 +14,13 @@
# 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 apt
import filecmp
import logging
import os
-import shlex
-import shutil
-import subprocess
-import sys
-import time
-
-import snapcraft.yaml
-from snapcraft import (
- common,
- meta,
-)
logger = logging.getLogger(__name__)
-def shell(args):
- config = snapcraft.yaml.load_config()
- common.env = config.stage_env()
- userCommand = args.userCommand
- if not userCommand:
- userCommand = ['/usr/bin/env',
- 'PS1=\[\e[1;32m\]snapcraft:\w\$\[\e[0m\] ',
- '/bin/bash',
- '--norc']
- common.run(userCommand)
-
-
-def snap(args):
- cmd(args)
-
- config = snapcraft.yaml.load_config()
- # TODO move all this to meta.create
- if 'architectures' in config.data:
- arches = config.data['architectures']
- else:
- arches = [snapcraft.common.get_arch(), ]
-
- # FIXME this should be done in a more contained manner
- common.env = config.snap_env()
-
- meta.create(config.data, arches)
-
-
-def assemble(args):
- args.cmd = 'snap'
- # With all the data in snapcraft.yaml, maybe it's not a good idea to call
- # snap(args) and just do a snappy build if assemble was explicitly called.
- snap(args)
-
- ticker = '/-\\|'
- i = 0
- with subprocess.Popen(['snappy', 'build', common.get_snapdir()],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,) as proc:
- ret = None
- if os.isatty(sys.stdout.fileno()):
- ret = proc.poll()
- while ret is None:
- print('\033[1m\rSnapping\033[0m {}'.format(ticker[i]), end='')
- i = (i+1) % len(ticker)
- time.sleep(.2)
- ret = proc.poll()
- else:
- print('Snapping ...')
- ret = proc.wait()
- print()
- if ret == 0:
- print(proc.stdout.read().decode('utf-8'))
- else:
- print(proc.stderr.read().decode('utf-8'), file=sys.stderr)
- sys.exit(ret)
-
-
def _check_for_collisions(parts):
parts_files = {}
for part in parts:
@@ -126,73 +56,3 @@ def _check_for_collisions(parts):
'installdir': part.installdir}
return True
-
-
-def cmd(args):
- forceAll = args.force
- forceCommand = None
-
- cmds = [args.cmd]
-
- if cmds[0] in common.COMMAND_ORDER:
- forceCommand = cmds[0]
- cmds = common.COMMAND_ORDER[0:common.COMMAND_ORDER.index(cmds[0]) + 1]
-
- config = snapcraft.yaml.load_config()
- _install_build_packages(config.build_tools)
-
- # clean the snap dir before Snapping
- snap_clean = False
-
- for part in config.all_parts:
- for cmd in cmds:
- if cmd is 'stage':
- # This ends up running multiple times, as each part gets to its
- # staging cmd. That's inefficient, but largely OK.
- # FIXME: fix the above by iterating over cmds before iterating
- # all_parts. But then we need to make sure we continue to
- # handle cases like go, where you want go built before trying
- # to pull a go project.
- if not _check_for_collisions(config.all_parts):
- sys.exit(1)
-
- # We want to make sure we have a clean snap dir
- if cmd is 'snap' and not snap_clean:
- shutil.rmtree(common.get_snapdir())
- snap_clean = True
-
- common.env = config.build_env_for_part(part)
- force = forceAll or cmd == forceCommand
-
- try:
- getattr(part, cmd)(force=force)
- except Exception as e:
- logger.error('Failed doing %s for %s: %s', cmd, part.name, e)
- sys.exit(1)
-
-
-def _call(args, **kwargs):
- logger.info('Running: %s', ' '.join(shlex.quote(arg) for arg in args))
- return subprocess.call(args, **kwargs)
-
-
-def _check_call(args, **kwargs):
- logger.info('Running: %s', ' '.join(shlex.quote(arg) for arg in args))
- return subprocess.check_call(args, **kwargs)
-
-
-def _install_build_packages(packages):
- new_packages = []
- for pkg in packages:
- try:
- if not apt.Cache()[pkg].installed:
- new_packages.append(pkg)
- except KeyError:
- logger.error('Could not find all the "build-packages" required '
- 'in snapcraft.yaml')
- sys.exit(1)
- if new_packages:
- logger.info('Installing required packages on the host system')
- _check_call(['sudo', 'apt-get', '-o', 'Dpkg::Progress-Fancy=1',
- '--no-install-recommends',
- '-y', 'install'] + new_packages)
@@ -0,0 +1,39 @@
+# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
+#
+# Copyright (C) 2015 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
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+snapcraft pull
+
+Download or retrieve artifacts defined for a part.
+
+Usage:
+ pull [options] [PART ...]
+
+Options:
+ -h --help show this help message and exit.
+
+"""
+
+from docopt import docopt
+
+from snapcraft import lifecycle
+
+
+def main(argv=None):
+ argv = argv if argv else []
+ args = docopt(__doc__, argv=argv)
+
+ lifecycle.execute('pull', args['PART'])
View
@@ -115,3 +115,8 @@ def get_schemadir():
def isurl(url):
return urllib.parse.urlparse(url).scheme != ''
+
+
+def reset_env():
+ global env
+ env = []
View
@@ -17,14 +17,16 @@
import contextlib
import glob
import importlib
-import jsonschema
import logging
import os
import sys
import shutil
+
+import jsonschema
import yaml
import snapcraft
+import snapcraft.yaml
from snapcraft import common
from snapcraft import repo
@@ -36,6 +38,27 @@ def _local_plugindir():
return os.path.abspath(os.path.join('parts', 'plugins'))
+def execute(step, part_names=None):
+ # TODO: add a docstring once strip is implemented.
+ config = snapcraft.yaml.load_config()
+ repo.install_build_packages(config.build_tools)
+
+ if part_names:
+ config.validate_parts(part_names)
+ parts = {p for p in config.all_parts if p.name in part_names}
+ else:
+ parts = config.all_parts
+
+ # TODO: cycle through the steps until we reach the desired step. Since
+ # pull is the first one, and the only one supported in this drop, it
+ # doesn't make sense to cycle through them... yet.
+ for part in parts:
+ common.env = config.build_env_for_part(part)
+ # pull() for a part is always called, the plugin will decide
+ # if it is run or not.
+ part.pull()
+
+
class PluginError(Exception):
pass
View
@@ -14,7 +14,6 @@
# 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 apt
import glob
import itertools
import logging
@@ -26,10 +25,12 @@
import subprocess
import urllib
import urllib.request
+import sys
+import apt
from xml.etree import ElementTree
-import snapcraft.common
+from snapcraft import common
logger = logging.getLogger(__name__)
@@ -47,6 +48,25 @@
_GEOIP_SERVER = "http://geoip.ubuntu.com/lookup"
+def install_build_packages(packages):
+ new_packages = []
+ for pkg in packages:
+ try:
+ if not apt.Cache()[pkg].installed:
+ new_packages.append(pkg)
+ except KeyError:
+ logger.error('Could not find all the "build-packages" required '
+ 'in snapcraft.yaml')
+ sys.exit(1)
+ if new_packages:
+ logger.info(
+ 'Installing build dependencies: %s', ' '.join(new_packages))
+ subprocess.check_call(['sudo', 'apt-get', '-o',
+ 'Dpkg::Progress-Fancy=1',
+ '--no-install-recommends',
+ '-y', 'install'] + new_packages)
+
+
class PackageNotFoundError(Exception):
@property
@@ -202,9 +222,8 @@ def _setup_apt_cache(rootdir, sources, local=False):
srcfile = os.path.join(rootdir, 'etc', 'apt', 'sources.list')
if not local:
- arch = snapcraft.common.get_arch()
series = platform.linux_distribution()[2]
- sources = _format_sources_list(sources, arch, series)
+ sources = _format_sources_list(sources, common.get_arch(), series)
with open(srcfile, 'w') as f:
f.write(sources)
@@ -261,13 +280,13 @@ def _fix_contents(debdir):
def _fix_xml_tools(root):
xml2_config_path = os.path.join(root, 'usr', 'bin', 'xml2-config')
if os.path.isfile(xml2_config_path):
- snapcraft.common.run(
+ common.run(
['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'.
format(root), xml2_config_path])
xslt_config_path = os.path.join(root, 'usr', 'bin', 'xslt-config')
if os.path.isfile(xslt_config_path):
- snapcraft.common.run(
+ common.run(
['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'.
format(root), xslt_config_path])
@@ -285,7 +304,7 @@ def _fix_filemode(path):
def _skip_link(target):
global _skip_list
if not _skip_list:
- output = snapcraft.common.run_output(['dpkg', '-L', 'libc6']).split()
+ output = common.run_output(['dpkg', '-L', 'libc6']).split()
_skip_list = [i for i in output if 'lib' in i]
return target in _skip_list
@@ -14,6 +14,9 @@
# 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 os
+import tempfile
+
import fixtures
import testscenarios
@@ -33,3 +36,14 @@ def setUp(self):
# value when a test ends.
self.addCleanup(common.set_plugindir, common.get_plugindir())
self.addCleanup(common.set_schemadir, common.get_schemadir())
+ self.addCleanup(common.set_schemadir, common.get_schemadir())
+ self.addCleanup(common.reset_env)
+ common.set_schemadir(os.path.join(__file__,
+ '..', '..', '..', 'schema'))
+
+ def make_snapcraft_yaml(self, content, encoding='utf-8'):
+ tempdir_obj = tempfile.TemporaryDirectory()
+ self.addCleanup(tempdir_obj.cleanup)
+ os.chdir(tempdir_obj.name)
+ with open('snapcraft.yaml', 'w', encoding=encoding) as fp:
+ fp.write(content)
Oops, something went wrong.