diff --git a/doc/man/ade-install.1 b/doc/man/ade-install.1 new file mode 100644 index 0000000000000000000000000000000000000000..14b211f70ebb959443125484929336a65b6de239 --- /dev/null +++ b/doc/man/ade-install.1 @@ -0,0 +1,50 @@ +.TH ADE\-INSTALL 1 09/12/2016 0.1612.0 Apertis\ Development\ Tools\ Manual + +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l + +.SH NAME + +ade-install \- Install application + +.SH SYNOPSIS +.sp +.nf +\fIade install\fR [--bundle=<bundle>] --simulator +\fIade install\fR [--bundle=<bundle>] --device [<user>[:<pass>]@]<hostname>[:<port>] +.fi +.sp +.SH DESCRIPTION +.sp +Install application to simulator or given device\&. +.sp +.SH OPTIONS +.sp +.PP +\fI\-\-bundle\fR +.RS 4 +Bundle to install\&. If not specified, a bundle is created from project in +current directory\&. +.sp +.RE +.PP +\fI\-\-simulator\fR +.RS 4 +Use simulator as installation target\&. +.sp +.RE +.PP +\fI\-\-device\fR +.RS 4 +Use device as installation target (e.g. user@apertis)\&. +.sp +.RE +.SH SEE ALSO + +ade(1) + +.SH COPYRIGHT + +Copyright (c) 2016 Collabora Ltd. diff --git a/doc/man/ade-uninstall.1 b/doc/man/ade-uninstall.1 new file mode 100644 index 0000000000000000000000000000000000000000..90bd378d728ebd90b5c6cf78fdc04f83d5c33a70 --- /dev/null +++ b/doc/man/ade-uninstall.1 @@ -0,0 +1,50 @@ +.TH ADE\-UNINSTALL 1 09/12/2016 0.1612.0 Apertis\ Development\ Tools\ Manual + +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l + +.SH NAME + +ade-uninstall \- Remove application + +.SH SYNOPSIS +.sp +.nf +\fIade uninstall\fR [--bundle-id=<bundle>] --simulator +\fIade uninstall\fR [--bundle-id=<bundle>] --device [<user>[:<pass>]@]<hostname>[:<port>] +.fi +.sp +.SH DESCRIPTION +.sp +Remove an application from the simulator or given device\&. +.sp +.SH OPTIONS +.sp +.PP +\fI\-\-bundle-id\fR +.RS 4 +Application to remove\&. If not specified, the bundle-id from project in +current directory is used\&. +.sp +.RE +.PP +\fI\-\-simulator\fR +.RS 4 +Use simulator as removal target\&. +.sp +.RE +.PP +\fI\-\-device\fR +.RS 4 +Use device as removal target (e.g. user@apertis)\&. +.sp +.RE +.SH SEE ALSO + +ade(1) + +.SH COPYRIGHT + +Copyright (c) 2016 Collabora Ltd. diff --git a/doc/man/ade.1 b/doc/man/ade.1 index ceeff6f0fedd056b351030da01bd9481b1b28a9b..b7f8b7d6b21e028d49ad48771aae1c6f7fc70f29 100644 --- a/doc/man/ade.1 +++ b/doc/man/ade.1 @@ -77,6 +77,22 @@ Export application to application bundle\&. See \fBade-export(1)\fR .sp .RE +.PP +\fIinstall\fR +.RS 4 +Install application to simulator or device\&. +.sp +See \fBade-install(1)\fR +.sp +.RE +.PP +\fIuninstall\fR +.RS 4 +Uninstall application from simulator or device\&. +.sp +See \fBade-uninstall(1)\fR +.sp +.RE .SH SEE ALSO ade-sysroot(1) diff --git a/tools/ade b/tools/ade index 3fa0c497216b1402c85615814ce5af0d9f1dee75..528270d2210ec4c2b54b76d376b9abde2c5c725a 100755 --- a/tools/ade +++ b/tools/ade @@ -163,6 +163,16 @@ class Simulator: def __init__(self): pass + def _exec(self, *args): + r = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return r.stdout.read().decode().strip() + + def install(self, bundle): + self._exec('ribchester-bundle', 'remove', bundle.id) + self._exec('ribchester-bundle', 'install-app-bundle', bundle.path) + + def uninstall(self, bundle_id): + self._exec('ribchester-bundle', 'remove', bundle_id) class Device: @@ -224,6 +234,20 @@ class Device: raise InvalidDeviceError("Unsupported architecture {}".format(a)) self.version.arch = triplet.arch + def install(self, bundle): + self._exec('ribchester-bundle', 'remove', bundle.id) + bundledir = '/home/user/bundles' + self._exec('mkdir', '-p', bundledir) + remote_path = os.path.join(bundledir, os.path.basename(bundle.path)) + with closing(self._connect()) as ssh: + with closing(ssh.open_sftp()) as sftp: + sftp.put(bundle.path, remote_path) + self._exec('ribchester-bundle', 'install-app-bundle', remote_path) + self._exec('rm', remote_path) + + def uninstall(self, bundle_id): + self._exec('ribchester-bundle', 'remove', bundle_id) + class SysrootVersion: @@ -804,7 +828,6 @@ class Ade: self.file = None self.dest = None - self.target = None self.sdk = False self.simulator = False self.sysroot = None @@ -865,24 +888,21 @@ class Ade: def get_sysroot_manager(self): return SysrootManager(self.path, self.url, self.user, self.password, config=self.config) - def get_target(self): - if self.target: - return self.target - - if self.sdk: + def get_object(self, classes=[Bundle, Device, Project, SDK, Simulator, Sysroot]): + if self.sdk and SDK in classes: try: - self.target = SDK() + obj = SDK() except NotInstalledError: self.die("Not running in a SDK distribution") except Exception as e: self.die("Invalid SDK installation: {0}".format(e)) - elif self.simulator: - self.target = Simulator() - elif self.sysroot: + elif self.simulator and Simulator in classes: + obj = Simulator() + elif self.sysroot and Sysroot in classes: try: version = SysrootVersion.from_id(self.sysroot) - self.target = self.get_sysroot_manager().get_installed(version) - if not self.target: + obj = self.get_sysroot_manager().get_installed(version) + if not obj: self.die("No sysroot currently installed for {0}{1}{2}" \ .format(Colors.OKBLUE, version.get_name(), Colors.ENDC)) except ValueError: @@ -890,26 +910,32 @@ class Ade: except InvalidSysrootError: self.die("Invalid sysroot installed for {0}{1}{2}" \ .format(Colors.OKBLUE, version.get_name(), Colors.ENDC)) - elif self.device: + elif self.device and Device in classes: try: - self.target = Device.from_uri(self.device) - self.target.load_sysroot_version() + obj = Device.from_uri(self.device) + obj.load_sysroot_version() except InvalidDeviceError as e: self.die("Invalid device: {0}".format(e)) - elif self.project: + elif self.project and Project in classes: try: - self.target = Project() + obj = Project() except InvalidProjectError as e: self.die("Invalid project: {0}".format(e)) - elif self.bundle: + elif self.bundle and Bundle in classes: try: - self.target = Bundle.from_file(self.bundle) + obj = Bundle.from_file(self.bundle) except InvalidBundleError as e: self.die("Invalid bundle: {0}".format(e)) else: - self.die("No target (simulator, sysroot or device) specified") + return None - return self.target + return obj + + def get_target(self): + target = self.get_object([Simulator, Sysroot, Device]) + if not target: + self.die("No target (simulator, sysroot or device) specified") + return target def do_sysroot_list(self): manager = self.get_sysroot_manager() @@ -1097,38 +1123,38 @@ class Ade: .format(Colors.OKBLUE, self.sysroot_version.get_name(), Colors.ENDC)) def do_info(self): - target = self.get_target() + obj = self.get_object() - if isinstance(target, SDK): + if isinstance(obj, SDK): self.info("* SDK version is {0}{1}{2}" - .format(Colors.WARNING, self.target.version, Colors.ENDC)) + .format(Colors.WARNING, self.obj.version, Colors.ENDC)) if self.format == 'parseable': - print("SDKVersion:{0}".format(self.target.version.get_tag())) - if isinstance(target, Sysroot): + print("SDKVersion:{0}".format(self.obj.version.get_tag())) + if isinstance(obj, Sysroot): self.info("* Sysroot version {0}{1}{2} is installed at '{3}'" - .format(Colors.WARNING, self.target.version, Colors.ENDC, self.target.path)) + .format(Colors.WARNING, self.obj.version, Colors.ENDC, self.obj.path)) if self.format == 'parseable': - print("SysrootVersion:{0}".format(self.target.version.get_tag())) - print("SysrootPath:{0}".format(self.target.path)) - elif isinstance(target, Device): + print("SysrootVersion:{0}".format(self.obj.version.get_tag())) + print("SysrootPath:{0}".format(self.obj.path)) + elif isinstance(obj, Device): self.info("* Device has image version {0}{1}{2}" - .format(Colors.WARNING, self.target.version, Colors.ENDC)) + .format(Colors.WARNING, self.obj.version, Colors.ENDC)) if self.format == 'parseable': - print("ImageVersion:{0}".format(self.target.version.get_tag())) - elif isinstance(target, Project): - self.info("* Project: {0}{1}{2}".format(Colors.WARNING, self.target.name, Colors.ENDC)) - self.info("* BundleId: {0}".format(self.target.bundle_id)) - self.info("* Version: {0}".format(self.target.version)) + print("ImageVersion:{0}".format(self.obj.version.get_tag())) + elif isinstance(obj, Project): + self.info("* Project: {0}{1}{2}".format(Colors.WARNING, self.obj.name, Colors.ENDC)) + self.info("* BundleId: {0}".format(self.obj.bundle_id)) + self.info("* Version: {0}".format(self.obj.version)) if self.format == 'parseable': - print("ProjectName:{0}".format(self.target.name)) - print("BundleId:{0}".format(self.target.bundle_id)) - print("AppVersion:{0}".format(self.target.version)) - elif isinstance(target, Bundle): - self.info("* BundleId: {0}".format(self.target.id)) - self.info("* Version: {0}".format(self.target.version)) + print("ProjectName:{0}".format(self.obj.name)) + print("BundleId:{0}".format(self.obj.bundle_id)) + print("AppVersion:{0}".format(self.obj.version)) + elif isinstance(obj, Bundle): + self.info("* BundleId: {0}".format(self.obj.id)) + self.info("* Version: {0}".format(self.obj.version)) if self.format == 'parseable': - print("BundleId:{0}".format(self.target.id)) - print("AppVersion:{0}".format(self.target.version)) + print("BundleId:{0}".format(self.obj.id)) + print("AppVersion:{0}".format(self.obj.version)) def do_configure(self): target = self.get_target() @@ -1138,7 +1164,7 @@ class Ade: sysroot = target elif isinstance(target, Device): sdk = self.get_sdk() - version = self.target.version + version = target.version if sdk and version.is_compatible(sdk.version): sysroot = None # Native compilation; SDK version matches device image version else: @@ -1173,6 +1199,32 @@ class Ade: except Exception as e: self.die("Couldn't create bundle: {0}".format(e)) + def do_install(self): + target = self.get_target() + try: + with tempfile.TemporaryDirectory() as tmpdir: + if self.bundle: + bundle = Bundle.from_file(self.bundle) + else: + project = Project() + bundle = Bundle.from_project(project, tmpdir) + + target.install(bundle) + except InvalidBundleError as e: + self.die("Invalid bundle: {0}".format(e)) + except Exception as e: + self.die("Couldn't install application: {0}".format(e)) + + def do_uninstall(self): + target = self.get_target() + try: + if not self.bundle_id: + project = Project() + self.bundle_id = project.bundle_id + target.uninstall(self.bundle_id) + except Exception as e: + self.die("Couldn't uninstall application: {0}".format(e)) + def info(self, message): if self.format == 'friendly': print(message) @@ -1267,6 +1319,20 @@ if __name__ == '__main__': export_parser = subparsers.add_parser('export', help="Create an application bundle") export_parser.add_argument('--dest', help="Bundle destination directory") + # Install parser + install_parser = subparsers.add_parser('install', help="Install an application") + install_parser.add_argument('--bundle', help="Path to bundle to install") + group = install_parser.add_mutually_exclusive_group() + group.add_argument('--simulator', help="Use simulator as target", action='store_true') + group.add_argument('--device', help="Use device as target (e.g. user@apertis)") + + # Uninstall parser + uninstall_parser = subparsers.add_parser('uninstall', help="Uninstall an application") + uninstall_parser.add_argument('--bundle-id', help="Bundle to uninstall") + group = uninstall_parser.add_mutually_exclusive_group() + group.add_argument('--simulator', help="Use simulator as target", action='store_true') + group.add_argument('--device', help="Use device as target (e.g. user@apertis)") + argcomplete.autocomplete(root_parser) obj = Ade()