← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/lpcraft:version-command into lpcraft:main

 

Colin Watson has proposed merging ~cjwatson/lpcraft:version-command into lpcraft:main with ~cjwatson/lpcraft:provider as a prerequisite.

Commit message:
Add a "version" command

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/lpcraft/+git/lpcraft/+merge/411418
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/lpcraft:version-command into lpcraft:main.
diff --git a/lpcraft/commands/__init__.py b/lpcraft/commands/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lpcraft/commands/__init__.py
diff --git a/lpcraft/commands/tests/__init__.py b/lpcraft/commands/tests/__init__.py
new file mode 100644
index 0000000..2f35e23
--- /dev/null
+++ b/lpcraft/commands/tests/__init__.py
@@ -0,0 +1,39 @@
+# Copyright 2021 Canonical Ltd.  This software is licensed under the
+# GNU General Public License version 3 (see the file LICENSE).
+
+from dataclasses import dataclass
+from typing import List
+
+from craft_cli import CraftError
+from fixtures import MockPatch
+from testtools import TestCase
+
+from lpcraft.main import main
+from lpcraft.tests.fixtures import EmitterFixture
+
+
+@dataclass
+class _CommandResult:
+    """The result of a command."""
+
+    exit_code: int
+    messages: List[str]
+    errors: List[CraftError]
+
+
+class CommandBaseTestCase(TestCase):
+    def run_command(self, *args, **kwargs):
+        with MockPatch("sys.argv", ["lpcraft"] + list(args)):
+            with EmitterFixture() as emitter:
+                exit_code = main()
+                return _CommandResult(
+                    exit_code,
+                    [
+                        call.args[0]
+                        for call in emitter.emit_message.call_args_list
+                    ],
+                    [
+                        call.args[0]
+                        for call in emitter.emit_error.call_args_list
+                    ],
+                )
diff --git a/lpcraft/commands/tests/test_version.py b/lpcraft/commands/tests/test_version.py
new file mode 100644
index 0000000..a50aa54
--- /dev/null
+++ b/lpcraft/commands/tests/test_version.py
@@ -0,0 +1,19 @@
+# Copyright 2021 Canonical Ltd.  This software is licensed under the
+# GNU General Public License version 3 (see the file LICENSE).
+
+from lpcraft.commands.tests import CommandBaseTestCase
+
+
+class VersionTestCase(CommandBaseTestCase):
+    def test_version_option(self):
+        result = self.run_command("--version")
+        self.assertEqual(0, result.exit_code)
+
+    def test_version_subcommand(self):
+        result = self.run_command("version")
+        self.assertEqual(0, result.exit_code)
+
+    def test_same_output(self):
+        result1 = self.run_command("version")
+        result2 = self.run_command("--version")
+        self.assertEqual(result1.messages, result2.messages)
diff --git a/lpcraft/commands/version.py b/lpcraft/commands/version.py
new file mode 100644
index 0000000..2e74e50
--- /dev/null
+++ b/lpcraft/commands/version.py
@@ -0,0 +1,11 @@
+# Copyright 2021 Canonical Ltd.  This software is licensed under the
+# GNU General Public License version 3 (see the file LICENSE).
+
+from craft_cli import emit
+
+from lpcraft._version import version_description as lpcraft_version
+
+
+def version(args):
+    """Show lpcraft's version number."""
+    emit.message(lpcraft_version)
diff --git a/lpcraft/main.py b/lpcraft/main.py
index 0f547f8..a1a872e 100644
--- a/lpcraft/main.py
+++ b/lpcraft/main.py
@@ -4,11 +4,13 @@
 """Main entry point."""
 
 import logging
+import sys
 from argparse import ArgumentParser
 
-from craft_cli import EmitterMode, emit
+from craft_cli import CraftError, EmitterMode, emit
 
 from lpcraft._version import version_description as lpcraft_version
+from lpcraft.commands.version import version
 
 
 def _configure_logger(name):
@@ -47,6 +49,11 @@ def main():
         help="Show debug information and be more verbose.",
     )
 
+    subparsers = parser.add_subparsers()
+
+    parser_version = subparsers.add_parser("version", help=version.__doc__)
+    parser_version.set_defaults(func=version)
+
     emit.init(EmitterMode.NORMAL, "lpcraft", f"Starting {lpcraft_version}")
 
     try:
@@ -62,6 +69,29 @@ def main():
 
     if args.version:
         emit.message(lpcraft_version)
+        emit.ended_ok()
+        return 0
+
+    if getattr(args, "func", None) is None:
+        parser.print_usage(file=sys.stderr)
+        emit.ended_ok()
+        return 1
+
+    try:
+        ret = args.func(args)
+    except KeyboardInterrupt as e:
+        error = CraftError("Interrupted.")
+        error.__cause__ = e
+        emit.error(error)
+        ret = 1
+    except Exception as e:
+        error = CraftError(f"lpcraft internal error: {e!r}")
+        error.__cause__ = e
+        emit.error(error)
+        ret = 1
+    else:
+        emit.ended_ok()
+        if ret is None:
+            ret = 0
 
-    emit.ended_ok()
-    return 0
+    return ret