Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changes/unreleased.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
### Changes

- gh-62 Added `donna version` command that prints the version of the tool.
- gh-60 Fixed CLI artifact extension recognition for `donna artifacts update`.
2 changes: 1 addition & 1 deletion donna/artifacts/usage/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Use the next commands to work with artifacts:
- `donna -p <protocol> artifacts view <artifact-pattern>` — get the meaningful (rendered) content of all matching artifacts. This command shows the rendered information about each artifact. Use this command when you need to read artifact content.
- `donna -p <protocol> artifacts fetch <world>:<artifact>` — download the original source of the artifact content, outputs the file path to the artifact's copy, you can change. Use this command when you need to change the content of the artifact.
- `donna -p <protocol> artifacts tmp <slug>.<extension>` — create a temporary file for artifact-related work and output its path.
- `donna -p <protocol> artifacts update <world>:<artifact> <file-path|-> [--extension <extension>]` — upload content from a file path or from stdin (`-`) as the artifact. If `--extension` is omitted, Donna infers it from the existing target artifact.
- `donna -p <protocol> artifacts update <world>:<artifact> <file-path|-> [--extension <extension>]` — upload content from a file path or from stdin (`-`) as the artifact. Donna gets an extension from three sources: `--extension`, `<file-path>`, and a stored artifact; if there are multiple extensions or no extensions at all, Donna returns an error.
- `donna -p <protocol> artifacts copy <artifact-id-from> <artifact-id-to>` — copy an artifact source to another artifact ID (can be in a different world). This overwrites the destination if it exists.
- `donna -p <protocol> artifacts move <artifact-id-from> <artifact-id-to>` — copy an artifact source to another artifact ID and remove the original. This overwrites the destination if it exists.
- `donna -p <protocol> artifacts remove <artifact-pattern>` — remove artifacts matching a pattern. Use this command when you need to delete artifacts.
Expand Down
72 changes: 57 additions & 15 deletions donna/workspaces/artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ class CanNotRemoveReadonlyWorld(ArtifactRemoveError):

class ArtifactExtensionCannotBeInferred(ArtifactUpdateError):
code: str = "donna.workspaces.artifact_extension_cannot_be_inferred"
message: str = "Cannot infer artifact extension. Provide `--extension` or update an existing artifact."
message: str = "Cannot infer artifact extension."
ways_to_fix: list[str] = [
"Pass `--extension <extension>` when updating the artifact.",
"Create/update an artifact that already exists and has a known extension.",
"Provide an input path with extension (for example `*.md`).",
"Update an artifact that already exists and has a known extension if that is applicable.",
]


Expand Down Expand Up @@ -126,28 +127,69 @@ def update_artifact( # noqa: CCR001
expected_extension = artifact_file_extension(full_id).unwrap_or(None)

requested_extension = extension.lstrip(".").lower() if extension is not None else None
inferred_extension = input.suffix.lstrip(".").lower() or None

if expected_extension is None and requested_extension is None:
return Err([ArtifactExtensionCannotBeInferred(artifact_id=full_id, path=input)])

if expected_extension is None and requested_extension is not None:
source_suffix = requested_extension
elif expected_extension is not None and requested_extension is None:
source_suffix = expected_extension
elif expected_extension != requested_extension:
def mismatch_error(a: str, b: str) -> Result[None, ErrorsList]:
return Err(
[
ArtifactExtensionMismatch(
artifact_id=full_id,
path=input,
provided_extension=requested_extension or "",
existing_extension=expected_extension or "",
provided_extension=a,
existing_extension=b,
)
]
)
else:
assert expected_extension is not None
source_suffix = expected_extension

match (expected_extension, requested_extension, inferred_extension):
case (None, None, None):
return Err([ArtifactExtensionCannotBeInferred(artifact_id=full_id, path=input)])

case (None, None, inferred):
source_suffix = inferred

case (None, requested, None):
source_suffix = requested

case (None, requested, inferred) if requested == inferred:
source_suffix = requested

case (None, requested, inferred):
assert requested is not None
assert inferred is not None
return mismatch_error(requested, inferred)

case (expected, None, None):
source_suffix = expected

case (expected, None, inferred) if expected == inferred:
source_suffix = expected

case (expected, None, inferred):
assert expected is not None
assert inferred is not None
return mismatch_error(inferred, expected)

case (expected, requested, None) if expected == requested:
source_suffix = expected

case (expected, requested, None):
assert expected is not None
assert requested is not None
return mismatch_error(requested, expected)

case (expected, requested, inferred) if expected == requested == inferred:
source_suffix = expected

case (expected, requested, inferred) if expected != requested:
assert expected is not None
assert requested is not None
return mismatch_error(requested, expected)

case (expected, requested, inferred):
assert expected is not None
assert inferred is not None
return mismatch_error(inferred, expected)

normalized_source_suffix = f".{source_suffix}"

Expand Down