diff --git a/src/client/cli/formatter/csv_formatter.cpp b/src/client/cli/formatter/csv_formatter.cpp index 53841f722f..0f32c0a1e5 100644 --- a/src/client/cli/formatter/csv_formatter.cpp +++ b/src/client/cli/formatter/csv_formatter.cpp @@ -89,7 +89,7 @@ std::string generate_snapshot_overview_report(const mp::InfoReply& reply) for (const auto& item : mp::format::sort_snapshots(reply.snapshot_overview().overview())) { const auto& snapshot = item.fundamentals(); - fmt::format_to(std::back_inserter(buf), "{},{},{},{}\n", item.instance_name(), snapshot.snapshot_name(), + fmt::format_to(std::back_inserter(buf), "{},{},{},\"{}\"\n", item.instance_name(), snapshot.snapshot_name(), snapshot.parent(), snapshot.comment()); } diff --git a/src/client/cli/formatter/table_formatter.cpp b/src/client/cli/formatter/table_formatter.cpp index bfceca58a0..ead3faebe1 100644 --- a/src/client/cli/formatter/table_formatter.cpp +++ b/src/client/cli/formatter/table_formatter.cpp @@ -28,6 +28,8 @@ namespace mp = multipass; namespace { +const std::regex newline("(\r\n|\n)"); + std::string format_images(const google::protobuf::RepeatedPtrField& images_info, std::string type) { @@ -95,7 +97,6 @@ std::string generate_snapshot_details(const mp::DetailedInfoItem& item) } // TODO@snapshots split and align string if it extends onto several lines - std::regex newline("(\r\n|\n)"); fmt::format_to(std::back_inserter(buf), "{:<16}{}\n", "Comment:", fundamentals.comment().empty() ? "--" @@ -238,7 +239,6 @@ std::string generate_snapshot_overview_report(const mp::InfoReply& reply) const auto parent_column_width = mp::format::column_width( overview.begin(), overview.end(), [](const auto& item) -> int { return item.fundamentals().parent().length(); }, parent_col_header.length()); - const auto max_comment_column_width = 50; const auto row_format = "{:<{}}{:<{}}{:<{}}{:<}\n"; @@ -247,7 +247,13 @@ std::string generate_snapshot_overview_report(const mp::InfoReply& reply) for (const auto& item : mp::format::sort_snapshots(overview)) { + size_t max_comment_column_width = 50; + std::smatch match; auto snapshot = item.fundamentals(); + + if (std::regex_search(snapshot.comment().begin(), snapshot.comment().end(), match, newline)) + max_comment_column_width = std::min((size_t)(match.position(1)) + 1, max_comment_column_width); + fmt::format_to(std::back_inserter(buf), row_format, item.instance_name(), name_column_width, snapshot.snapshot_name(), snapshot_column_width, snapshot.parent().empty() ? "--" : snapshot.parent(), parent_column_width, diff --git a/tests/test_output_formatter.cpp b/tests/test_output_formatter.cpp index 6359865db3..22a2f19bc5 100644 --- a/tests/test_output_formatter.cpp +++ b/tests/test_output_formatter.cpp @@ -521,7 +521,7 @@ auto construct_multiple_snapshot_overview_info_reply() fundamentals = snapshot_entry->mutable_fundamentals(); snapshot_entry->set_instance_name("prosperous-spadefish"); fundamentals->set_snapshot_name("snapshot2"); - fundamentals->set_comment("Before restoring snap1"); + fundamentals->set_comment("Before restoring snap1\nContains a newline that\r\nshould be truncated"); timestamp.set_seconds(1671840000); fundamentals->mutable_creation_timestamp()->CopyFrom(timestamp); @@ -985,7 +985,7 @@ const std::vector orderable_list_info_formatter_outputs{ "hale-roller pristine -- A first snapshot\n" "hale-roller rocking pristine A very long comment that should be truncated by t…\n" "hale-roller rolling pristine Loaded with stuff\n" - "prosperous-spadefish snapshot2 -- Before restoring snap1\n" + "prosperous-spadefish snapshot2 -- Before restoring snap1…\n" "prosperous-spadefish snapshot10 snapshot2 --\n", "table_snapshot_overview_multiple"}, @@ -1030,12 +1030,13 @@ const std::vector orderable_list_info_formatter_outputs{ "ab5191cc172564e7cc0eafd397312a32598823e645279c820f0935393aead509,18.04 LTS,,,,,,,\"\";,,3\n", "csv_info_multiple_instances"}, {&csv_formatter, &single_snapshot_overview_info_reply, - "Instance,Snapshot,Parent,Comment\nfoo,snapshot1,,This is a sample comment\n", "csv_snapshot_overview_single"}, + "Instance,Snapshot,Parent,Comment\nfoo,snapshot1,,\"This is a sample comment\"\n", "csv_snapshot_overview_single"}, {&csv_formatter, &multiple_snapshot_overview_info_reply, - "Instance,Snapshot,Parent,Comment\nhale-roller,pristine,,A first " - "snapshot\nhale-roller,rocking,pristine,A very long comment that should be truncated by the table " - "formatter\nhale-roller,rolling,pristine,Loaded with stuff\nprosperous-spadefish,snapshot2,,Before restoring " - "snap1\nprosperous-spadefish,snapshot10,snapshot2,\n", + "Instance,Snapshot,Parent,Comment\nhale-roller,pristine,,\"A first " + "snapshot\"\nhale-roller,rocking,pristine,\"A very long comment that should be truncated by the table " + "formatter\"\nhale-roller,rolling,pristine,\"Loaded with stuff\"\nprosperous-spadefish,snapshot2,,\"Before " + "restoring snap1\nContains a newline that\r\nshould be " + "truncated\"\nprosperous-spadefish,snapshot10,snapshot2,\"\"\n", "csv_snapshot_overview_multiple"}, {&yaml_formatter, &empty_list_reply, "\n", "yaml_list_empty"}, @@ -1194,7 +1195,7 @@ const std::vector orderable_list_info_formatter_outputs{ "prosperous-spadefish:\n" " - snapshot2:\n" " - parent: ~\n" - " comment: Before restoring snap1\n" + " comment: \"Before restoring snap1\\nContains a newline that\\r\\nshould be truncated\"\n" " - snapshot10:\n" " - parent: snapshot2\n" " comment: ~\n", @@ -1418,7 +1419,7 @@ const std::vector non_orderable_list_info_formatter_outputs{ " \"parent\": \"snapshot2\"\n" " },\n" " \"snapshot2\": {\n" - " \"comment\": \"Before restoring snap1\",\n" + " \"comment\": \"Before restoring snap1\\nContains a newline that\\r\\nshould be truncated\",\n" " \"parent\": \"\"\n" " }\n" " }\n"