-
Notifications
You must be signed in to change notification settings - Fork 445
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(craft-application): initial support (#4560)
Signed-off-by: Callahan Kovacs <[email protected]> Co-authored-by: Callahan <[email protected]> Co-authored-by: Alex Lowe <[email protected]>
- Loading branch information
1 parent
11c1a6f
commit 9855085
Showing
40 changed files
with
887 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- | ||
# | ||
# Copyright 2023 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/>. | ||
|
||
"""Main Snapcraft Application.""" | ||
|
||
from __future__ import annotations | ||
|
||
import os | ||
import signal | ||
import sys | ||
|
||
import craft_cli | ||
from craft_application import Application, AppMetadata, util | ||
from craft_cli import emit | ||
from overrides import override | ||
|
||
from snapcraft import cli, errors, models, services | ||
from snapcraft.commands import unimplemented | ||
|
||
APP_METADATA = AppMetadata( | ||
name="snapcraft", | ||
summary="Package, distribute, and update snaps for Linux and IoT", | ||
ProjectClass=models.Project, | ||
source_ignore_patterns=["*.snap"], | ||
) | ||
|
||
|
||
class Snapcraft(Application): | ||
"""Snapcraft application definition.""" | ||
|
||
@override | ||
def _configure_services(self, platform: str | None, build_for: str | None) -> None: | ||
if build_for is None: | ||
build_for = util.get_host_architecture() | ||
|
||
self.services.set_kwargs("package", platform=platform, build_for=build_for) | ||
super()._configure_services(platform, build_for) | ||
|
||
@property | ||
def command_groups(self): | ||
"""Short-circuit the standard command groups for now.""" | ||
# TODO: Remove this once we've got lifecycle commands and version migrated. | ||
return self._command_groups | ||
|
||
def run(self) -> int: | ||
"""Fall back to the old snapcraft entrypoint.""" | ||
self._get_dispatcher() | ||
raise errors.ClassicFallback() | ||
|
||
@override | ||
def _get_dispatcher(self) -> craft_cli.Dispatcher: | ||
"""Configure this application. Should be called by the run method. | ||
Side-effect: This method may exit the process. | ||
:returns: A ready-to-run Dispatcher object | ||
""" | ||
# Set the logging level to DEBUG for all craft-libraries. This is OK even if | ||
# the specific application doesn't use a specific library, the call does not | ||
# import the package. | ||
util.setup_loggers(*self._cli_loggers) | ||
|
||
craft_cli.emit.init( | ||
mode=craft_cli.EmitterMode.BRIEF, | ||
appname=self.app.name, | ||
greeting=f"Starting {self.app.name}", | ||
log_filepath=self.log_path, | ||
streaming_brief=True, | ||
) | ||
|
||
dispatcher = craft_cli.Dispatcher( | ||
self.app.name, | ||
self.command_groups, | ||
summary=str(self.app.summary), | ||
extra_global_args=self._global_arguments, | ||
# TODO: craft-application should allow setting the default command without | ||
# overriding `_get_dispatcher()` | ||
default_command=unimplemented.Pack, | ||
) | ||
|
||
try: | ||
craft_cli.emit.trace("pre-parsing arguments...") | ||
# Workaround for the fact that craft_cli requires a command. | ||
# https://github.com/canonical/craft-cli/issues/141 | ||
if "--version" in sys.argv or "-V" in sys.argv: | ||
try: | ||
global_args = dispatcher.pre_parse_args(["pull", *sys.argv[1:]]) | ||
except craft_cli.ArgumentParsingError: | ||
global_args = dispatcher.pre_parse_args(sys.argv[1:]) | ||
else: | ||
global_args = dispatcher.pre_parse_args(sys.argv[1:]) | ||
|
||
if global_args.get("version"): | ||
craft_cli.emit.ended_ok() | ||
print(f"{self.app.name} {self.app.version}") | ||
sys.exit(0) | ||
except craft_cli.ProvideHelpException as err: | ||
print(err, file=sys.stderr) # to stderr, as argparse normally does | ||
craft_cli.emit.ended_ok() | ||
sys.exit(0) | ||
except craft_cli.ArgumentParsingError as err: | ||
print(err, file=sys.stderr) # to stderr, as argparse normally does | ||
craft_cli.emit.ended_ok() | ||
sys.exit(64) # Command line usage error from sysexits.h | ||
except KeyboardInterrupt as err: | ||
self._emit_error(craft_cli.CraftError("Interrupted."), cause=err) | ||
sys.exit(128 + signal.SIGINT) | ||
# pylint: disable-next=broad-exception-caught | ||
except Exception as err: # noqa: BLE001 | ||
self._emit_error( | ||
craft_cli.CraftError( | ||
f"Internal error while loading {self.app.name}: {err!r}" | ||
) | ||
) | ||
if os.getenv("CRAFT_DEBUG") == "1": | ||
raise | ||
sys.exit(70) # EX_SOFTWARE from sysexits.h | ||
|
||
craft_cli.emit.trace("Preparing application...") | ||
self.configure(global_args) | ||
|
||
return dispatcher | ||
|
||
|
||
def main() -> int: | ||
"""Run craft-application based snapcraft with classic fallback.""" | ||
util.setup_loggers( | ||
"craft_parts", "craft_providers", "craft_store", "snapcraft.remote" | ||
) | ||
|
||
snapcraft_services = services.SnapcraftServiceFactory(app=APP_METADATA) | ||
|
||
app = Snapcraft(app=APP_METADATA, services=snapcraft_services) | ||
|
||
app.add_command_group( | ||
"Lifecycle", | ||
[ | ||
unimplemented.Clean, | ||
unimplemented.Pull, | ||
unimplemented.Build, | ||
unimplemented.Stage, | ||
unimplemented.Prime, | ||
unimplemented.Pack, | ||
unimplemented.RemoteBuild, | ||
unimplemented.Snap, # Hidden (legacy compatibility) | ||
unimplemented.Plugins, | ||
unimplemented.ListPlugins, | ||
unimplemented.Try, | ||
], | ||
) | ||
app.add_command_group( | ||
"Extensions", | ||
[ | ||
unimplemented.ListExtensions, | ||
unimplemented.Extensions, | ||
unimplemented.ExpandExtensions, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Account", | ||
[ | ||
unimplemented.Login, | ||
unimplemented.ExportLogin, | ||
unimplemented.Logout, | ||
unimplemented.Whoami, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Snap Names", | ||
[ | ||
unimplemented.Register, | ||
unimplemented.Names, | ||
unimplemented.ListRegistered, | ||
unimplemented.List, | ||
unimplemented.Metrics, | ||
unimplemented.UploadMetadata, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Snap Release Management", | ||
[ | ||
unimplemented.Release, | ||
unimplemented.Close, | ||
unimplemented.Status, | ||
unimplemented.Upload, | ||
unimplemented.Push, | ||
unimplemented.Promote, | ||
unimplemented.ListRevisions, | ||
unimplemented.Revisions, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Snap Tracks", | ||
[ | ||
unimplemented.ListTracks, | ||
unimplemented.Tracks, | ||
unimplemented.SetDefaultTrack, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Key Management", | ||
[ | ||
unimplemented.CreateKey, | ||
unimplemented.RegisterKey, | ||
unimplemented.SignBuild, | ||
unimplemented.ListKeys, | ||
], | ||
) | ||
app.add_command_group( | ||
"Store Validation Sets", | ||
[ | ||
unimplemented.EditValidationSets, | ||
unimplemented.ListValidationSets, | ||
unimplemented.Validate, | ||
unimplemented.Gated, | ||
], | ||
) | ||
app.add_command_group( | ||
"Other", | ||
[ | ||
unimplemented.Version, | ||
unimplemented.Lint, | ||
unimplemented.Init, | ||
], | ||
) | ||
|
||
try: | ||
return app.run() | ||
except errors.ClassicFallback: | ||
emit.debug("Falling back from craft-application to snapcraft.") | ||
return cli.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.