Skip to content

Commit

Permalink
Basic working state
Browse files Browse the repository at this point in the history
  • Loading branch information
ahal-test committed Apr 15, 2013
1 parent ede26b9 commit d5a7a2d
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 124 deletions.
102 changes: 48 additions & 54 deletions getb2g/base.py
@@ -1,59 +1,40 @@
from abc import ABCMeta, abstractmethod
import getpass
from bs4 import BeautifulSoup
import inspect
import traceback
import os
import stat
import sys
import tempfile
import traceback

from mixins.download import DownloadMixin
import mozinfo
import mozlog
log = mozlog.getLogger('GetB2G')

__all__ = ('Base', 'GeckoBase', 'SymbolsBase', 'EmulatorBase', 'TestBase', 'valid_resources')

valid_resources = {'all': set([])}


class Base(object):
class Base(DownloadMixin):
__metaclass__ = ABCMeta
_default_busybox_url = 'http://busybox.net/downloads/binaries/latest/'

def prompt_story(self, data=None):
"""
Prompts the user to provide any additional missing information
"""
data = data or self.__dict__

# username and password
if data.username and not data.password:
print "No password found for user '%s'!" % data.username
options = {'1': 'Enter password',
'2': 'Ignore username'}
while True:
print ['[%s] %s\n' % (k, v) for k, v in options.iteritems()]
option = raw_input("$ ")
if option in options.keys():
break
if option == options.keys()[0]:
data.password = getpass.getpass()
elif option == options.keys()[1]:
data.username = None
return data

def __init__(self, **kwargs):
self.data = kwargs

@classmethod
def handled_resources(cls, request):
"""
Returns a subset of the resources that this class is capable
of handling for a specified request
"""
# A resource can be handled iff
# 1. the handler contains a callee named 'prepare_resource'
# 2. the specified args all exist in the callee
# 3. all args in the callee without a default exist in the specified args
handled_resources = []
methods = inspect.getmembers(cls, inspect.ismethod)
for resource, kwargs in request.resources:
for resource in request.resources:
for name, ref in methods:
if name == 'prepare_%s' % resource:
if set(kwargs.keys()).issubset(set(inspect.getargspec(ref)[0])):
handled_resources.append((resource, kwargs))
handled_resources.append(resource)
return handled_resources

@classmethod
Expand All @@ -62,28 +43,41 @@ def execute_request(cls, request):
Executes the specified request
"""
handled_resources = cls.handled_resources(request)
for resource, kwargs in handled_resources:
for resource in handled_resources:
success = False
try:
h = cls(**request.state)
success = getattr(h, 'prepare_%s' % resource)(**kwargs)
h = cls(**request.metadata)
getattr(h, 'prepare_%s' % resource)()
request.resources.remove(resource)
except:
traceback.print_exc()
if success:
request.resources.remove((resource, kwargs))
log.debug(traceback.format_exc())

def prepare_busybox(self, platform):
"""
Returns the path of a busybox binary for the given platform
"""

def prepare_busybox(self):
"""
Downloads a busybox binary for the given platform
"""
url = self._default_busybox_url
platform = self.data.get('busybox_platform') or self.data.get('platform', 'armv6l')

doc = self.download_file(url, tempfile.mkstemp()[1])
soup = BeautifulSoup(open(doc, 'r'))
for link in soup.find_all('a'):
if 'busybox-%s' % platform in link['href']:
path = os.path.join(self.data['workdir'], 'busybox')
if os.path.isfile(path):
os.remove(path)
file_name = self.download_file(url + link['href'], 'busybox')
os.chmod(file_name, stat.S_IEXEC)
break
else:
log.error("Couldn't find a busybox binary for platform '%s'" % platform)

class GeckoBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def prepare_gecko(self, *args, **kwargs):
def prepare_gecko(self):
"""
Returns path to an unzipped gecko directory
Downloads and extracts a gecko directory
for the given args
"""

Expand All @@ -92,7 +86,7 @@ class SymbolsBase(object):
_default_minidump_stackwalk_url = 'https://hg.mozilla.org/build/tools/file/tip/breakpad/%s/minidump_stackwalk'

@abstractmethod
def prepare_symbols(self, *args, **kwargs):
def prepare_symbols(self):
"""
Returns the path to an unzipped symbols directory
for the given args
Expand All @@ -110,20 +104,21 @@ def prepare_minidump_stackwalk(self, url=None):
url = self._default_minidump_stackwalk_url % ('osx%s' % arch)
elif mozinfo.isWin:
url = self._default_minidump_stackwalk_url % 'win32'
self.download_file(url, 'minidump_stackwalk')

file_name = self.download_file(url, 'minidump_stackwalk')
os.chmod(file_name, stat.S_IEXEC)

class TestBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def prepare_tests(self, *args, **kwargs):
def prepare_tests(self):
"""
Returns the path to an unzipped tests bundle
"""

class EmulatorBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def prepare_emulator(self, *args, **kwargs):
def prepare_emulator(self):
"""
Returns the path to an unzipped emulator package
"""
Expand All @@ -132,7 +127,7 @@ def prepare_emulator(self, *args, **kwargs):
class UnagiBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def prepare_unagi(self, *args, **kwargs):
def prepare_unagi(self):
"""
Returns the path to an extracted unagi build
"""
Expand All @@ -141,7 +136,7 @@ def prepare_unagi(self, *args, **kwargs):
class OtoroBase(object):
__metaclass__ = ABCMeta
@abstractmethod
def prepare_otoro(self, *args, **kwargs):
def prepare_otoro(self):
"""
Returns the path to an extracted otoro build
"""
Expand All @@ -157,4 +152,3 @@ def prepare_otoro(self, *args, **kwargs):
if group not in valid_resources:
valid_resources[group] = set([])
valid_resources[group].add(name)
print "valid_resources: %s" % valid_resources['all']
4 changes: 4 additions & 0 deletions getb2g/errors.py
Expand Up @@ -6,3 +6,7 @@ class InvalidResourceException(Exception):
class IncompleteRequestException(Exception):
"""The requested resource was not valid"""

class MissingDataException(Exception):
"""Not enough information to complete the request"""
def __init__(self, message=None, *args):
super(MissingDataException, self).__init__(message or self.__doc__, *args)
32 changes: 23 additions & 9 deletions getb2g/getb2g.py
Expand Up @@ -12,18 +12,21 @@
from base import valid_resources
from prompt import prompt_resources
from request import Request
import prompt
import mozlog
log = mozlog.getLogger('GetB2G')

def build_request(resources, metadata={}):
request = Request()
request = Request(metadata=metadata)
for resource in resources:
request.add_resource(resource, metadata)
request.add_resource(resource)
request.dispatch()

def cli(args=sys.argv[1:]):
parser = optparse.OptionParser(usage='%prog [options]', description=__doc__)

parser.add_option('-d', '--workdir', dest='workdir',
action='store', default=None,
action='store', default=os.path.join(os.getcwd(), 'b2g-workdir'),
help='Set up everything in this directory')
parser.add_option('--no-prompt', dest='prompt_disabled',
action='store_true', default=False,
Expand All @@ -33,9 +36,13 @@ def cli(args=sys.argv[1:]):
parser.add_option('--damnit', dest='damnit',
action='store_true', default=False,
help='Just give me something that I can use to test B2G damnit!')
parser.add_option('--log-level', dest='log_level', action='store',
type='choice', default='INFO',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'],
help='Only print messages at this log level')
for resource in valid_resources['all']:
resource = resource.replace('_', '-')
parser.add_option('--prepare-%s' % resource, dest=resource,
cmdlet = resource.replace('_', '-')
parser.add_option('--prepare-%s' % cmdlet, dest=resource,
action='store_true', default=False,
help='Do whatever it takes to set up %s' % resource)
parser.add_option('-m', '--metadata', dest='metadata',
Expand All @@ -45,8 +52,13 @@ def cli(args=sys.argv[1:]):
'Store values of duplicate keys in a list. E.g --metadata '
'user=foo --metadata user=bar --metadata branch=mozilla-central')
options, args = parser.parse_args(args)
log.setLevel(getattr(mozlog, options.log_level))
prompt.prompt_disabled = options.prompt_disabled

metadata = {}
if not os.path.isdir(options.workdir):
os.makedirs(options.workdir)
metadata['workdir'] = options.workdir
for data in options.metadata:
k, v = data.split('=', 1)
if k in metadata:
Expand All @@ -55,14 +67,16 @@ def cli(args=sys.argv[1:]):
metadata[k].append(v)
else:
metadata[k] = v

if options.damnit:
resources = ('emulator', 'symbols', 'busybox', 'tests', 'minidump_stackwalk')
resources = ('emulator', 'gecko', 'symbols', 'busybox', 'tests', 'minidump_stackwalk')
return build_request(resources, metadata)

print options.minidump_stackwalk
resources = [r for r in valid_resources['all'] if getattr(options, r, False)]
if not options.prompt_disabled:
resources = prompt_resources(resources)
print resources
resources = prompt_resources(resources)
print resources
build_request(resources, metadata)

if __name__ == '__main__':
Expand Down

0 comments on commit d5a7a2d

Please sign in to comment.