Repository: canonical/charmcraft

Issue:
`create-lib` command breaks without a metadata.yaml file
### Bug Description

Without a `metadata.yaml` file, `charmcraft create-lib` fails. However, it only needs this to get the charm name.

### To Reproduce

`charmcraft init` (or with any explicit profile)
`charmcraft create-lib mylib`

### Environment

N/A

### charmcraft.yaml

```shell
N/A
```


### Relevant log output

```shell
(charmcraft) lengau@hyperion:~/Work/Test/charms/tmp$ charmcraft init --profile=kubernetes
Charmed operator package file and directory tree initialised.                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                 
Now edit the following package files to provide fundamental charm metadata                                                                                                                                                                                                       
and other information:                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                 
charmcraft.yaml                                                                                                                                                                                                                                                                  
src/charm.py                                                                                                                                                                                                                                                                     
README.md                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                 
(charmcraft) lengau@hyperion:~/Work/Test/charms/tmp$ charmcraft create-lib mylib
Cannot find a valid charm name in metadata.yaml. Check you are in a charm directory with metadata.yaml.                                                                                                                                                                          
Full execution log: '/home/lengau/.local/state/charmcraft/log/charmcraft-20230818-165535.506311.log'
```


Discussion:

Patch:
diff --git a/charmcraft/commands/store/__init__.py b/charmcraft/commands/store/__init__.py
index fb7c8e9c..efd9445c 100644
--- a/charmcraft/commands/store/__init__.py
+++ b/charmcraft/commands/store/__init__.py
@@ -1298,11 +1298,11 @@ class CreateLibCommand(BaseCommand):
                 "characters and underscore, starting with alpha."
             )
 
-        charm_name = get_name_from_metadata()
+        charm_name = self.config.name or get_name_from_metadata()
         if charm_name is None:
             raise CraftError(
-                "Cannot find a valid charm name in metadata.yaml. Check you are in a charm "
-                "directory with metadata.yaml."
+                "Cannot find a valid charm name in charm definition. "
+                "Check that you are using the correct project directory."
             )
 
         # '-' is valid in charm names, but not in a python import
@@ -1310,11 +1310,11 @@ class CreateLibCommand(BaseCommand):
         importable_charm_name = create_importable_name(charm_name)
 
         # all libraries born with API version 0
-        full_name = "charms.{}.v0.{}".format(importable_charm_name, lib_name)
+        full_name = f"charms.{importable_charm_name}.v0.{lib_name}"
         lib_data = get_lib_info(full_name=full_name)
         lib_path = lib_data.path
         if lib_path.exists():
-            raise CraftError("This library already exists: {!r}.".format(str(lib_path)))
+            raise CraftError(f"This library already exists: {str(lib_path)!r}.")
 
         emit.progress(f"Creating library {lib_name}.")
         store = Store(self.config.charmhub)
@@ -1323,12 +1323,12 @@ class CreateLibCommand(BaseCommand):
         # create the new library file from the template
         env = get_templates_environment("charmlibs")
         template = env.get_template("new_library.py.j2")
-        context = dict(lib_id=lib_id)
+        context = {"lib_id": lib_id}
         try:
             lib_path.parent.mkdir(parents=True, exist_ok=True)
             lib_path.write_text(template.render(context))
         except OSError as exc:
-            raise CraftError("Error writing the library in {!r}: {!r}.".format(str(lib_path), exc))
+            raise CraftError(f"Error writing the library in {str(lib_path)!r}: {exc!r}.")
 
         if parsed_args.format:
             info = {"library_id": lib_id}


Test patch:
diff --git a/tests/commands/test_store_commands.py b/tests/commands/test_store_commands.py
index 110d454d..2715f6b4 100644
--- a/tests/commands/test_store_commands.py
+++ b/tests/commands/test_store_commands.py
@@ -2757,31 +2757,36 @@ def test_status_unreleased_track(emitter, store_mock, config):
 
 @pytest.mark.skipif(sys.platform == "win32", reason="Windows not [yet] supported")
 @pytest.mark.parametrize("formatted", [None, JSON_FORMAT])
-def test_createlib_simple(emitter, store_mock, tmp_path, monkeypatch, config, formatted):
+@pytest.mark.parametrize("charmcraft_yaml_name", [None, "test-charm"])
+def test_createlib_simple(
+    emitter, store_mock, tmp_path, monkeypatch, config, formatted, charmcraft_yaml_name
+):
     """Happy path with result from the Store."""
     monkeypatch.chdir(tmp_path)
 
+    config.name = charmcraft_yaml_name
+
     lib_id = "test-example-lib-id"
     store_mock.create_library_id.return_value = lib_id
 
     args = Namespace(name="testlib", format=formatted)
     with patch("charmcraft.commands.store.get_name_from_metadata") as mock:
-        mock.return_value = "testcharm"
+        mock.return_value = "test-charm"
         CreateLibCommand(config).run(args)
 
     assert store_mock.mock_calls == [
-        call.create_library_id("testcharm", "testlib"),
+        call.create_library_id("test-charm", "testlib"),
     ]
     if formatted:
         expected = {"library_id": lib_id}
         emitter.assert_json_output(expected)
     else:
         expected = [
-            "Library charms.testcharm.v0.testlib created with id test-example-lib-id.",
-            "Consider 'git add lib/charms/testcharm/v0/testlib.py'.",
+            "Library charms.test_charm.v0.testlib created with id test-example-lib-id.",
+            "Consider 'git add lib/charms/test_charm/v0/testlib.py'.",
         ]
         emitter.assert_messages(expected)
-    created_lib_file = tmp_path / "lib" / "charms" / "testcharm" / "v0" / "testlib.py"
+    created_lib_file = tmp_path / "lib" / "charms" / "test_charm" / "v0" / "testlib.py"
 
     env = get_templates_environment("charmlibs")
     expected_newlib_content = env.get_template("new_library.py.j2").render(lib_id=lib_id)
@@ -2791,13 +2796,14 @@ def test_createlib_simple(emitter, store_mock, tmp_path, monkeypatch, config, fo
 def test_createlib_name_from_metadata_problem(store_mock, config):
     """The metadata wasn't there to get the name."""
     args = Namespace(name="testlib", format=None)
+    config.name = None
     with patch("charmcraft.commands.store.get_name_from_metadata") as mock:
         mock.return_value = None
         with pytest.raises(CraftError) as cm:
             CreateLibCommand(config).run(args)
         assert str(cm.value) == (
-            "Cannot find a valid charm name in metadata.yaml. Check you are in a charm "
-            "directory with metadata.yaml."
+            "Cannot find a valid charm name in charm definition. "
+            "Check that you are using the correct project directory."
         )
 
 
@@ -2856,22 +2862,20 @@ def test_createlib_path_already_there(tmp_path, monkeypatch, config):
     """The intended-to-be-created library is already there."""
     monkeypatch.chdir(tmp_path)
 
-    factory.create_lib_filepath("test-charm-name", "testlib", api=0)
+    factory.create_lib_filepath("test-charm", "testlib", api=0)
     args = Namespace(name="testlib", format=None)
-    with patch("charmcraft.commands.store.get_name_from_metadata") as mock:
-        mock.return_value = "test-charm-name"
-        with pytest.raises(CraftError) as err:
-            CreateLibCommand(config).run(args)
+    with pytest.raises(CraftError) as err:
+        CreateLibCommand(config).run(args)
 
     assert str(err.value) == (
-        "This library already exists: 'lib/charms/test_charm_name/v0/testlib.py'."
+        "This library already exists: 'lib/charms/test_charm/v0/testlib.py'."
     )
 
 
 @pytest.mark.skipif(sys.platform == "win32", reason="Windows not [yet] supported")
 def test_createlib_path_can_not_write(tmp_path, monkeypatch, store_mock, add_cleanup, config):
     """Disk error when trying to write the new lib (bad permissions, name too long, whatever)."""
-    lib_dir = tmp_path / "lib" / "charms" / "test_charm_name" / "v0"
+    lib_dir = tmp_path / "lib" / "charms" / "test_charm" / "v0"
     lib_dir.mkdir(parents=True)
     lib_dir.chmod(0o111)
     add_cleanup(lib_dir.chmod, 0o777)
@@ -2880,10 +2884,8 @@ def test_createlib_path_can_not_write(tmp_path, monkeypatch, store_mock, add_cle
     args = Namespace(name="testlib", format=None)
     store_mock.create_library_id.return_value = "lib_id"
     expected_error = "Error writing the library in .*: PermissionError.*"
-    with patch("charmcraft.commands.store.get_name_from_metadata") as mock:
-        mock.return_value = "test-charm-name"
-        with pytest.raises(CraftError, match=expected_error):
-            CreateLibCommand(config).run(args)
+    with pytest.raises(CraftError, match=expected_error):
+        CreateLibCommand(config).run(args)
 
 
 def test_createlib_library_template_is_python(emitter, store_mock, tmp_path, monkeypatch):