def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.platform_dir = os.path.join(self.config.cwd, 'platforms/ubuntu/') self.sdk = 'ubuntu-sdk-16.04' if self.config.is_xenial else 'ubuntu-sdk-15.04' self._dirs = { 'build': '{}/{}/{}/build/' .format(self.platform_dir, self.sdk, self.config.build_arch), 'prefix': '{}/{}/{}/prefix/'.format(self.platform_dir, self.sdk, self.config.build_arch), 'make': '{}/build'.format(self.platform_dir) } self.config.temp = self._dirs['build'] self.config.build_dir = self._dirs['prefix'] if not os.path.isdir(self.platform_dir): # fail when not using docker, need it anyways if self.config.container_mode or self.config.lxd: print_error('Docker is required to intialize cordova directories. Enable docker or run "cordova platform add ubuntu" manually to remove this message') sys.exit(1) command = 'cordova platform add ubuntu' # Can't use self.container.run_command because need to set -e HOME=/tmp wrapped_command = 'docker run -v {cwd}:{cwd} -w {cwd} -u {uid}:{uid} -e HOME=/tmp --rm -i {img} {cmd}'.format( cwd=self.config.cwd, uid=os.getuid(), img=self.config.docker_image, cmd=command ) subprocess.check_call(shlex.split(wrapped_command))
def __init__(self, *args, **kwargs): super(CMakeClickable, self).__init__(*args, **kwargs) self.platform_dir = os.path.join(self.cwd, 'platforms/ubuntu/') self._dirs = { 'build': '{}/{}/{}/build/' .format(self.platform_dir, self.config.sdk, self.build_arch), 'prefix': '{}/{}/{}/prefix/'.format(self.platform_dir, self.config.sdk, self.build_arch), 'make': '{}/build'.format(self.platform_dir) } self.temp = self._dirs['build'] if not os.path.isdir(self.platform_dir): # fail when not using docker, need it anyways if self.config.container_mode or self.config.lxd or self.config.chroot: print_error('Docker is required to intialize cordova directories. Enable docker or run "cordova platform add ubuntu" manually to remove this message') sys.exit(1) cordova_docker_image = "beevelop/cordova:v7.0.0" # TODO add cordova to the clickable image command = "cordova platform add ubuntu" # Can't use self.run_container_command because need to set -e HOME=/tmp wrapped_command = 'docker run -v {cwd}:{cwd} -w {cwd} -u {uid}:{uid} -e HOME=/tmp --rm -i {img} {cmd}'.format( cwd=self.cwd, uid=os.getuid(), img=cordova_docker_image, cmd=command ) subprocess.check_call(shlex.split(wrapped_command)) self.config.dir = self._dirs['prefix']
def __init__(self, *args, **kwargs): super(CMakeClickable, self).__init__(*args, **kwargs) self.platform_dir = os.path.join(self.cwd, 'platforms/ubuntu/') self._dirs = { 'build': '{}/{}/{}/build/'.format(self.platform_dir, 'ubuntu-sdk-{}'.format(self.config.sdk), self.build_arch), 'prefix': '{}/{}/{}/prefix/'.format(self.platform_dir, 'ubuntu-sdk-{}'.format(self.config.sdk), self.build_arch), 'make': '{}/build'.format(self.platform_dir) } self.temp = self._dirs['build'] if not os.path.isdir(self.platform_dir): if (self.config.container_mode or self.config.lxd or self.config.chroot) and not shutil.which("cordova"): print_error( 'Docker is required to intialize cordova directories. Enable docker or run "cordova platform add ubuntu" manually to remove this message' ) sys.exit(1) cordova_docker_image = "beevelop/cordova:v7.0.0" # TODO add cordova to the clickable image command = "cordova platform add ubuntu" old_docker_image = (hasattr(self, "docker_image"), getattr(self, "docker_image", None)) self.docker_image = cordova_docker_image self.run_container_command(command, use_dir=False) if old_docker_image[0]: self.docker_image = old_docker_image[1] else: del self.docker_image os.makedirs(self._dirs["build"], exist_ok=True) self.config.dir = self._dirs['prefix']
def publish(self): # TODO allow publishing app for the first time if not self.config.apikey: print_error( 'No api key specified, use OPENSTORE_API_KEY or --apikey') return click = '{}_{}_{}.click'.format(self.find_package_name(), self.find_version(), self.config.arch) click_path = os.path.join(self.config.dir, click) url = OPENSTORE_API if 'OPENSTORE_API' in os.environ and os.environ['OPENSTORE_API']: url = os.environ['OPENSTORE_API'] url = url + OPENSTORE_API_PATH.format(self.find_package_name()) channel = 'xenial' if self.config.isXenial else 'vivid' files = {'file': open(click_path, 'rb')} data = {'channel': channel} params = {'apikey': self.config.apikey} print_info('Uploading version {} of {} for {} to the OpenStore'.format( self.find_version(), self.find_package_name(), channel)) response = requests.post(url, files=files, data=data, params=params) if response.status_code == requests.codes.ok: print_success('Upload successful') else: if response.text == 'Unauthorized': print_error('Failed to upload click: Unauthorized') else: print_error('Failed to upload click: {}'.format( response.json()['message']))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.platform_dir = os.path.join(self.config.cwd, 'platforms/ubuntu/') self.sdk = 'ubuntu-sdk-16.04' if self.config.is_xenial else 'ubuntu-sdk-15.04' self._dirs = { 'build': '{}/{}/{}/build/'.format(self.platform_dir, self.sdk, self.config.build_arch), 'prefix': '{}/{}/{}/prefix/'.format(self.platform_dir, self.sdk, self.config.build_arch), 'make': '{}/build'.format(self.platform_dir) } self.config.temp = self._dirs['build'] self.config.dir = self._dirs['prefix'] if not os.path.isdir(self.platform_dir): # fail when not using docker, need it anyways if self.config.container_mode or self.config.lxd: print_error( 'Docker is required to intialize cordova directories. Enable docker or run "cordova platform add ubuntu" manually to remove this message' ) sys.exit(1) command = 'cordova platform add ubuntu' # Can't use self.container.run_command because need to set -e HOME=/tmp wrapped_command = 'docker run -v {cwd}:{cwd} -w {cwd} -u {uid}:{uid} -e HOME=/tmp --rm -i {img} {cmd}'.format( cwd=self.config.cwd, uid=os.getuid(), img=self.base_docker_image, cmd=command) subprocess.check_call(shlex.split(wrapped_command))
def or_exit(self): if not self.query.is_met(): self.print_instructions() print_error('System requirement not met') exit(1)
def main(): config = None command_classes = {} command_names = [] command_aliases = {} command_help = {} command_dir = dirname(__file__) modules = glob.glob(join(command_dir, 'commands/*.py')) command_modules = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py') ] for name in command_modules: command_submodule = __import__('clickable.commands.{}'.format(name), globals(), locals(), [name]) for name, cls in inspect.getmembers(command_submodule): if inspect.isclass(cls) and issubclass( cls, Command ) and cls != Command and cls.name not in command_classes: command_classes[cls.name] = cls command_names.append(cls.name) if cls.help: command_help[cls.name] = cls.help for alias in cls.aliases: command_aliases[alias] = cls.name # TODO show the help text def show_valid_commands(): n = ['Valid commands:', ', '.join(sorted(command_names))] if config and hasattr(config, 'scripts') and config.scripts: n += [ 'Project-specific custom commands:', ', '.join(sorted(config.scripts.keys())) ] return '\n'.join(n) def print_valid_commands(): print(show_valid_commands()) parser = argparse.ArgumentParser(description='clickable') parser.add_argument('--version', '-v', action='version', version='%(prog)s ' + __version__) parser.add_argument('commands', nargs='*', help=show_valid_commands()) parser.add_argument( '--serial-number', '-s', help= 'Directs command to the device or emulator with the given serial number or qualifier (using adb)', default=None) parser.add_argument( '--config', '-c', help= 'Use specified config file instead of looking for the optional "clickable.json" in the current directory', default=None) parser.add_argument( '--ssh', help= 'Directs command to the device with the given IP address (using ssh)', default=None) parser.add_argument( '--arch', '-a', help= 'Use the specified arch when building (ignores the setting in clickable.json)' ) parser.add_argument( '--debug', action='store_true', help='Runs clickable in debug mode', default=False, ) parser.add_argument( '--lxd', action='store_true', help='Run build commands in a lxd container', default=False, ) parser.add_argument( '--output', help='Where to output the compiled click package', ) parser.add_argument( '--container-mode', action='store_true', help= 'Run all build commands on the current machine and not a container', default=False, ) parser.add_argument( '--nvidia', action='store_true', help='Use docker with --runtime=nvidia and *-nvidia docker image', default=False, ) parser.add_argument( '--apikey', help='Api key for the OpenStore', ) parser.add_argument( '--vivid', action='store_true', help='Use the old vivid build container', default=False, ) parser.add_argument('--docker-image', help='Use a specific docker image to build with') parser.add_argument( '--dirty', action='store_true', help='Do not clean build directory', default=False, ) parser.add_argument( '--debug-build', action='store_true', help='Perform a debug build', default=False, ) parser.add_argument( '--gdbserver', help= 'Start gdbserver at the given port to debug the app remotely (only desktop mode)', ) parser.add_argument( '--gdb', action='store_true', help='Start gdb to debug the app (only desktop mode)', default=False, ) args = parser.parse_args() try: config = Config( args=args, clickable_version=__version__, desktop=('desktop' in args.commands or 'test' in args.commands), ) config.container = Container(config) VALID_COMMANDS = command_names + list(config.scripts.keys()) commands = args.commands if len(args.commands) == 0: commands = config.default.split(' ') ''' Detect senarios when an argument is passed to a command. For example: `clickable install /path/to/click`. Since clickable allows commands to be strung together it makes detecting this harder. This check has been limited to just the case when we have 2 values in args.commands as stringing together multiple commands and a command with an argument is unlikely to occur. TODO determine if there is a better way to do this. ''' command_arg = '' if len(commands) == 2 and commands[1] not in VALID_COMMANDS: command_arg = commands[1] commands = commands[:1] commands = [ command_aliases[command] if command in command_aliases else command for command in commands ] for command in commands: if command in command_names: cmd = command_classes[command](config) cmd.preprocess(command_arg) # TODO consider removing the ability to string together multiple commands # This should help clean up the arguments & command_arg for command in commands: if command in config.scripts: subprocess.check_call(config.scripts[command], cwd=config.cwd, shell=True) elif command in command_names: cmd = command_classes[command](config) cmd.run(command_arg) elif command == 'help': parser.print_help() else: print_error( 'There is no builtin or custom command named "{}"'.format( command)) print_valid_commands() sys.exit(1) except Exception: if args.debug: raise else: print_error(str(sys.exc_info()[1])) sys.exit(1)
def setup_lxd(self): print_error( 'Setting up lxd is no longer supported, use docker instead')
def main(): config = None COMMAND_ALIASES = { 'click_build': 'click_build', 'build_click': 'click_build', 'build-click': 'click_build', 'writeable-image': 'writable_image', } COMMAND_HANDLERS = { 'kill': 'kill', 'clean': 'clean', 'build': 'build', 'click-build': 'click_build', 'install': 'install', 'launch': 'launch', 'logs': 'logs', 'setup-lxd': 'setup_lxd', 'display-on': 'display_on', 'no-lock': 'no_lock', 'setup-docker': 'setup_docker', 'update-docker': 'update_docker', 'shell': 'shell', 'devices': 'devices', 'init': 'init_app', 'run': 'run', 'review': 'click_review', 'writable-image': 'writable_image', 'publish': 'publish', } def show_valid_commands(): n = [ 'Valid commands:', ', '.join(sorted(COMMAND_HANDLERS.keys())) ] if config and hasattr(config, 'scripts') and config.scripts: n += [ 'Project-specific custom commands:', ', '.join(sorted(config.scripts.keys())) ] return '\n'.join(n) def print_valid_commands(): print(show_valid_commands()) parser = argparse.ArgumentParser(description='clickable') parser.add_argument('--version', '-v', action='version', version='%(prog)s ' + __version__) parser.add_argument('commands', nargs='*', help=show_valid_commands()) parser.add_argument( '--device', '-d', action='store_true', help='Whether or not to run the custom command on the device', default=False, ) parser.add_argument( '--device-serial-number', '-s', help='Directs command to the device or emulator with the given serial number or qualifier (using adb)', default=None ) parser.add_argument( '--ip', '-i', help='Directs command to the device with the given IP address (using ssh)' ) parser.add_argument( '--arch', '-a', help='Use the specified arch when building (ignores the setting in clickable.json)' ) parser.add_argument( '--template', '-t', help='Use the specified template when building (ignores the setting in clickable.json)' ) # TODO depricate parser.add_argument( '--click', '-c', help='Installs the specified click (use with the "install" command)' ) # TODO depricate parser.add_argument( '--app', '-p', help='Launches the specified app (use with the "launch" command)' ) parser.add_argument( '--debug', action='store_true', help='Runs in debug mode', default=False, ) parser.add_argument( '--lxd', action='store_true', help='Run build commands in a lxd container', default=False, ) parser.add_argument( '--output', help='Where to output the compiled click package', ) parser.add_argument( '--container-mode', action='store_true', help='Run all build commands on the current machine and not a container', default=False, ) parser.add_argument( '--name', '-n', help='Specify an app template name to use when running "clickable init"' ) parser.add_argument( '--desktop', '-e', action='store_true', help='Run the app on the current machine for testing', default=False, ) parser.add_argument( '--sdk', '-k', help='Use a specific version of the ubuntu sdk to compile against', ) parser.add_argument( '--nvidia', action='store_true', help='Use nvidia-docker rather than docker', default=False, ) parser.add_argument( '--apikey', help='Api key for the OpenStore', ) parser.add_argument( '--xenial', action='store_true', help='Shortcut for --sdk=16.04', default=False, ) args = parser.parse_args() skip_detection = False if args.click: skip_detection = True if len(args.commands) == 1: skip_commands = [ 'setup-lxd', 'setup-docker', 'shell', 'no-lock', 'display-on', 'devices', 'init', ] if args.commands[0] in skip_commands: skip_detection = True try: # TODO clean this up config = Config( ip=args.ip, arch=args.arch, template=args.template, skip_detection=skip_detection, lxd=args.lxd, click_output=args.output, container_mode=args.container_mode, desktop=args.desktop, sdk='16.04' if args.xenial else args.sdk, use_nvidia=args.nvidia, apikey=args.apikey, ) VALID_COMMANDS = list(COMMAND_HANDLERS.keys()) + list(config.scripts.keys()) clickable = None if config.template == config.PURE_QML_QMAKE: clickable = PureQMLQMakeClickable(config, args.device_serial_number) elif config.template == config.QMAKE: clickable = QMakeClickable(config, args.device_serial_number) elif config.template == config.PURE_QML_CMAKE: clickable = PureQMLCMakeClickable(config, args.device_serial_number) elif config.template == config.CMAKE: clickable = CMakeClickable(config, args.device_serial_number) elif config.template == config.CUSTOM: clickable = CustomClickable(config, args.device_serial_number) elif config.template == config.CORDOVA: clickable = CordovaClickable(config, args.device_serial_number) elif config.template == config.PURE: clickable = PureClickable(config, args.device_serial_number) elif config.template == config.PYTHON: clickable = PythonClickable(config, args.device_serial_number) elif config.template == config.GO: clickable = GoClickable(config, args.device_serial_number) commands = args.commands if len(args.commands) == 0: commands = config.default.split(' ') ''' Detect senarios when an argument is passed to a command. For example: `clickable install /path/to/click`. Since clickable allows commands to be strung together it makes detecting this harder. This check has been limited to just the case when we have 2 values in args.commands as stringing together multiple commands and a command with an argument is unlikely to occur. TODO determine if there is a better way to do this. ''' command_arg = '' if len(commands) == 2 and commands[1] not in VALID_COMMANDS: command_arg = commands[1] commands = commands[:1] # TODO consider removing the ability to string together multiple commands # This should help clean up the arguments & new command_arg for command in commands: if command in config.scripts: clickable.script(command, args.device) elif command == 'install': clickable.install(args.click if args.click else command_arg) elif command == 'review': clickable.click_review(args.click if args.click else command_arg) elif command == 'launch': clickable.launch(args.app if args.app else command_arg) elif command == 'init': clickable.init_app(args.name) elif command == 'run': if not command_arg: raise ValueError('No command supplied for `clickable run`') clickable.run(command_arg) elif command in COMMAND_HANDLERS: getattr(clickable, COMMAND_HANDLERS[command])() elif command in COMMAND_ALIASES: getattr(clickable, COMMAND_ALIASES[command])() elif command == 'help': parser.print_help() else: print_error('There is no builtin or custom command named "{}"'.format(command)) print_valid_commands() except Exception: if args.debug: raise else: print_error(str(sys.exc_info()[1])) sys.exit(1)
def main(): config = None command_classes = {} command_names = [] command_aliases = {} command_help = {} command_dir = dirname(__file__) modules = glob.glob(join(command_dir, 'commands/*.py')) command_modules = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] for name in command_modules: command_submodule = __import__('clickable.commands.{}'.format(name), globals(), locals(), [name]) for name, cls in inspect.getmembers(command_submodule): if inspect.isclass(cls) and issubclass(cls, Command) and cls != Command and cls.name not in command_classes: command_classes[cls.name] = cls command_names.append(cls.name) if cls.help: command_help[cls.name] = cls.help for alias in cls.aliases: command_aliases[alias] = cls.name # TODO show the help text def show_valid_commands(): n = [ 'Valid commands:', ', '.join(sorted(command_names)) ] if config and hasattr(config, 'scripts') and config.scripts: n += [ 'Project-specific custom commands:', ', '.join(sorted(config.scripts.keys())) ] return '\n'.join(n) def print_valid_commands(): print(show_valid_commands()) parser = argparse.ArgumentParser(description='clickable') parser.add_argument('--version', '-v', action='version', version='%(prog)s ' + __version__) parser.add_argument('commands', nargs='*', help=show_valid_commands()) parser.add_argument( '--serial-number', '-s', help='Directs command to the device or emulator with the given serial number or qualifier (using adb)', default=None ) parser.add_argument( '--config', '-c', help='Use specified config file instead of looking for the optional "clickable.json" in the current directory', default=None ) parser.add_argument( '--ssh', help='Directs command to the device with the given IP address (using ssh)', default=None ) parser.add_argument( '--arch', '-a', help='Use the specified arch when building (ignores the setting in clickable.json)' ) parser.add_argument( '--debug', action='store_true', help='Runs clickable in debug mode', default=False, ) parser.add_argument( '--lxd', action='store_true', help='Run build commands in a lxd container', default=False, ) parser.add_argument( '--output', help='Where to output the compiled click package', ) parser.add_argument( '--container-mode', action='store_true', help='Run all build commands on the current machine and not a container', default=False, ) parser.add_argument( '--nvidia', action='store_true', help='Use nvidia-docker rather than docker', default=False, ) parser.add_argument( '--apikey', help='Api key for the OpenStore', ) parser.add_argument( '--vivid', action='store_true', help='Use the old vivid build container', default=False, ) parser.add_argument( '--docker-image', help='Use a specific docker image to build with' ) parser.add_argument( '--dirty', action='store_true', help='Do not clean build directory', default=False, ) parser.add_argument( '--debug-build', action='store_true', help='Perform a debug build', default=False, ) args = parser.parse_args() try: config = Config( args=args, clickable_version=__version__, desktop=('desktop' in args.commands), ) VALID_COMMANDS = command_names + list(config.scripts.keys()) commands = args.commands if len(args.commands) == 0: commands = config.default.split(' ') ''' Detect senarios when an argument is passed to a command. For example: `clickable install /path/to/click`. Since clickable allows commands to be strung together it makes detecting this harder. This check has been limited to just the case when we have 2 values in args.commands as stringing together multiple commands and a command with an argument is unlikely to occur. TODO determine if there is a better way to do this. ''' command_arg = '' if len(commands) == 2 and commands[1] not in VALID_COMMANDS: command_arg = commands[1] commands = commands[:1] commands = [command_aliases[command] if command in command_aliases else command for command in commands] for command in commands: if command in command_names: cmd = command_classes[command](config) cmd.preprocess(command_arg) # TODO consider removing the ability to string together multiple commands # This should help clean up the arguments & command_arg for command in commands: if command in config.scripts: subprocess.check_call(config.scripts[command], cwd=config.cwd, shell=True) elif command in command_names: cmd = command_classes[command](config) cmd.run(command_arg) elif command == 'help': parser.print_help() else: print_error('There is no builtin or custom command named "{}"'.format(command)) print_valid_commands() sys.exit(1) except Exception: if args.debug: raise else: print_error(str(sys.exc_info()[1])) sys.exit(1)