|
| 1 | +defmodule Cog.Commands.Cat do |
| 2 | + use Cog.Command.GenCommand.Base, |
| 3 | + bundle: Cog.Util.Misc.embedded_bundle |
| 4 | + |
| 5 | + alias Cog.Command.Service.DataStore |
| 6 | + |
| 7 | + # Note, we use the `tee` namespace because the namespace we read from |
| 8 | + # must be the same one that data was written into. |
| 9 | + @data_namespace [ "commands", "tee" ] |
| 10 | + |
| 11 | + @description "Retrieve saved pipeline output" |
| 12 | + |
| 13 | + @long_description """ |
| 14 | + The cat command retrieves pipeline output that was previously saved using the tee command. |
| 15 | + """ |
| 16 | + |
| 17 | + @arguments "<name>" |
| 18 | + |
| 19 | + rule "when command is #{Cog.Util.Misc.embedded_bundle}:cat allow" |
| 20 | + |
| 21 | + option "merge", short: "m", type: "bool", required: false, |
| 22 | + description: "Merge current pipeline map into saved pipeline map" |
| 23 | + |
| 24 | + option "append", short: "a", type: "bool", required: false, |
| 25 | + description: "Append current pipeline output to saved pipeline data, returning an array" |
| 26 | + |
| 27 | + option "insert", short: "i", type: "string", required: false, |
| 28 | + description: "Insert current pipeline output into saved pipeline map as the field specified for this option" |
| 29 | + |
| 30 | + def handle_message(%{options: %{"merge" => true, "append" => true}} = req, state) do |
| 31 | + {:error, req.reply_to, "The append and merge options cannot be specified together", state} |
| 32 | + end |
| 33 | + |
| 34 | + def handle_message(%{args: [key], options: opts} = req, state) do |
| 35 | + case DataStore.fetch(@data_namespace, key) do |
| 36 | + {:ok, data} -> |
| 37 | + cond do |
| 38 | + opts["insert"] -> |
| 39 | + handle_transform(:insert, req, data, state) |
| 40 | + opts["append"] -> |
| 41 | + {:reply, req.reply_to, List.wrap(data) ++ List.wrap(req.cog_env), state} |
| 42 | + opts["merge"] -> |
| 43 | + handle_transform(:merge, req, data, state) |
| 44 | + true -> |
| 45 | + {:reply, req.reply_to, data, state} |
| 46 | + end |
| 47 | + {:error, reason} -> |
| 48 | + {:error, req.reply_to, "Unable to retrieve data for #{key}: #{inspect reason}", state} |
| 49 | + end |
| 50 | + end |
| 51 | + |
| 52 | + def handle_message(%{args: []} = req, state), |
| 53 | + do: {:error, req.reply_to, "#{Cog.Util.Misc.embedded_bundle}:cat requires a name to be specified", state} |
| 54 | + |
| 55 | + defp handle_transform(action, req, data, state) do |
| 56 | + case transform_map_data(action, req.cog_env, data, req.options) do |
| 57 | + {:ok, result} -> |
| 58 | + {:reply, req.reply_to, result, state} |
| 59 | + {:error, reason} -> |
| 60 | + {:error, req.reply_to, reason, state} |
| 61 | + end |
| 62 | + end |
| 63 | + |
| 64 | + defp transform_map_data(action, [prev], curr, opts), |
| 65 | + do: transform_map_data(action, prev, curr, opts) |
| 66 | + defp transform_map_data(action, prev, [curr], opts), |
| 67 | + do: transform_map_data(action, prev, curr, opts) |
| 68 | + defp transform_map_data(:merge, prev, curr, _opts) when is_map(prev) and is_map(curr) do |
| 69 | + {:ok, Map.merge(prev, curr)} |
| 70 | + end |
| 71 | + defp transform_map_data(:insert, prev, curr, opts) when is_map(prev) and is_map(curr) do |
| 72 | + {:ok, Map.put(prev, opts["insert"], curr)} |
| 73 | + end |
| 74 | + defp transform_map_data(action, _prev, _curr, _opts) do |
| 75 | + {:error, "The #{Atom.to_string(action)} option is only applicable for map values"} |
| 76 | + end |
| 77 | +end |
0 commit comments