Allow more than 1 screenshot.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
* New screenshot naming: branchname-N.extension (the “-N” ist new). * In JSON file: Array of strings instead of string, “screenshots” instead of “screenshot”. * Old format is still supported.
This commit is contained in:
parent
1407954ab9
commit
f23a562c1b
22
src/cgi.cpp
22
src/cgi.cpp
|
@ -15,12 +15,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cgi.hpp"
|
#include "cgi.hpp"
|
||||||
|
|
||||||
#include "files.hpp"
|
#include "files.hpp"
|
||||||
#include "fs-compat.hpp"
|
#include "fs-compat.hpp"
|
||||||
#include "time.hpp"
|
#include "time.hpp"
|
||||||
|
|
||||||
#include <cgicc/Cgicc.h>
|
#include <cgicc/Cgicc.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <fmt/core.h>
|
||||||
#include <unicode/unistr.h>
|
#include <unicode/unistr.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -39,6 +41,7 @@
|
||||||
namespace FediBlock::cgi
|
namespace FediBlock::cgi
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using fmt::format;
|
||||||
using std::back_inserter;
|
using std::back_inserter;
|
||||||
using std::getline;
|
using std::getline;
|
||||||
using std::ios;
|
using std::ios;
|
||||||
|
@ -65,24 +68,25 @@ entry_type parse_formdata()
|
||||||
entry.description = cgi("description");
|
entry.description = cgi("description");
|
||||||
entry.report_time = time::to_string(system_clock::now());
|
entry.report_time = time::to_string(system_clock::now());
|
||||||
|
|
||||||
const auto screenshot = cgi.getFile("screenshot");
|
for (const auto &screenshot : cgi.getFiles())
|
||||||
if (screenshot != cgi.getFiles().end())
|
|
||||||
{
|
{
|
||||||
constexpr size_t size_limit{1024 * 1024 * 2}; // 2 MiB.
|
constexpr size_t size_limit{1024 * 1024 * 1};
|
||||||
if (screenshot->getDataLength() > size_limit)
|
if (screenshot.getDataLength() > size_limit)
|
||||||
{
|
{
|
||||||
throw runtime_error{"The screenshot is too big. "
|
throw runtime_error{format("The screenshot “{0:s}” is too big. "
|
||||||
"The limit is 2 MiB."};
|
"The limit is {1:.1f} MiB.",
|
||||||
|
screenshot.getFilename(),
|
||||||
|
size_limit / 1024 / 1024)};
|
||||||
}
|
}
|
||||||
|
|
||||||
const string filepath{files::get_tmpdir() / screenshot->getFilename()};
|
const string filepath{files::get_tmpdir() / screenshot.getFilename()};
|
||||||
ofstream file{filepath, ios::binary};
|
ofstream file{filepath, ios::binary};
|
||||||
if (!file.good())
|
if (!file.good())
|
||||||
{
|
{
|
||||||
throw runtime_error{"Could not open temporary file: " + filepath};
|
throw runtime_error{"Could not open temporary file: " + filepath};
|
||||||
}
|
}
|
||||||
screenshot->writeToStream(file);
|
screenshot.writeToStream(file);
|
||||||
entry.screenshot_filepath = filepath;
|
entry.screenshot_filepaths.push_back(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
|
|
@ -15,12 +15,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "files.hpp"
|
#include "files.hpp"
|
||||||
|
|
||||||
#include "fs-compat.hpp"
|
#include "fs-compat.hpp"
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/ostream.h> // For compatibility with fmt 4.
|
#include <fmt/ostream.h> // For compatibility with fmt 4.
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -29,8 +32,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace FediBlock::files
|
namespace FediBlock::files
|
||||||
{
|
{
|
||||||
|
@ -184,11 +185,31 @@ vector<entry_type> read_json_files(const bool cache)
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << file.rdbuf();
|
ss << file.rdbuf();
|
||||||
auto entry{json::from_json(ss.str())};
|
auto entry{json::from_json(ss.str())};
|
||||||
if (!entry.screenshot_filepath.empty())
|
if (!entry.screenshot_filepaths.empty())
|
||||||
{
|
{
|
||||||
const fs::path sh_path{entry.screenshot_filepath};
|
std::uint8_t counter{0};
|
||||||
entry.screenshot_filepath = path.stem().string() +=
|
for (auto &screenshot : entry.screenshot_filepaths)
|
||||||
sh_path.extension();
|
{
|
||||||
|
++counter;
|
||||||
|
const fs::path sh_path{screenshot};
|
||||||
|
// clang-format off
|
||||||
|
const auto compat_path{path.parent_path() /= path.stem()
|
||||||
|
/= sh_path.extension()};
|
||||||
|
// clang-format on
|
||||||
|
if (entry.screenshot_filepaths.size() == 1
|
||||||
|
&& fs::exists(compat_path))
|
||||||
|
{
|
||||||
|
// Compatibility for old entries.
|
||||||
|
screenshot = path.stem().string() += sh_path.extension();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
screenshot = (path.stem().string() += '-')
|
||||||
|
+= to_string(counter) += sh_path.extension();
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,11 +109,16 @@ void write_html(ostream &out, const vector<entry_type> &entries)
|
||||||
<< "</a></li>\n";
|
<< "</a></li>\n";
|
||||||
}
|
}
|
||||||
out << " </ul>\n";
|
out << " </ul>\n";
|
||||||
if (!entry.screenshot_filepath.empty())
|
if (!entry.screenshot_filepaths.empty())
|
||||||
{
|
{
|
||||||
out << " <p><strong>Screenshot:</strong><br>"
|
out << " <strong>Screenshots:</strong><br>\n"
|
||||||
<< "<a href=\"" << entry.screenshot_filepath << "\"><img src=\""
|
<< " <ul>\n";
|
||||||
<< entry.screenshot_filepath << R"("></a></p>)" << '\n';
|
for (const auto &screenshot : entry.screenshot_filepaths)
|
||||||
|
{
|
||||||
|
out << " <li><a href=\"" << screenshot << "\">"
|
||||||
|
<< screenshot << "</a></li>\n";
|
||||||
|
}
|
||||||
|
out << " </ul>";
|
||||||
}
|
}
|
||||||
out << " </details>\n";
|
out << " </details>\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,13 +165,17 @@ void write_rss(ostream &out, const vector<entry_type> &entries,
|
||||||
receipt);
|
receipt);
|
||||||
}
|
}
|
||||||
tmp_item_description += "</ul>";
|
tmp_item_description += "</ul>";
|
||||||
if (!entry.screenshot_filepath.empty())
|
if (!entry.screenshot_filepaths.empty())
|
||||||
{
|
{
|
||||||
tmp_item_description += "<p><strong>Screenshot:</strong><br>";
|
tmp_item_description += "<p><strong>Screenshots:</strong><br>";
|
||||||
tmp_item_description += format("<a href=\"{0:s}{1:s}\">"
|
for (const auto &screenshot : entry.screenshot_filepaths)
|
||||||
"<img src=\"{0:s}{1:s}\" "
|
{
|
||||||
"height=\"200\"></a></p>\n",
|
tmp_item_description += format("<a href=\"{0:s}{1:s}\">"
|
||||||
baseurl, entry.screenshot_filepath);
|
"<img src=\"{0:s}{1:s}\" "
|
||||||
|
"height=\"200\"></a> ",
|
||||||
|
baseurl, screenshot);
|
||||||
|
}
|
||||||
|
tmp_item_description += "</p>";
|
||||||
}
|
}
|
||||||
auto item_description{item.append_child("description")};
|
auto item_description{item.append_child("description")};
|
||||||
item_description.append_child(pugi::node_cdata)
|
item_description.append_child(pugi::node_cdata)
|
||||||
|
|
13
src/git.cpp
13
src/git.cpp
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git.hpp"
|
#include "git.hpp"
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "files.hpp"
|
#include "files.hpp"
|
||||||
#include "fs-compat.hpp"
|
#include "fs-compat.hpp"
|
||||||
|
@ -153,10 +154,16 @@ void commit(const entry_type &entry)
|
||||||
file << json::to_json(entry);
|
file << json::to_json(entry);
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
if (!entry.screenshot_filepath.empty())
|
if (!entry.screenshot_filepaths.empty())
|
||||||
{
|
{
|
||||||
const string extension{fs::path(entry.screenshot_filepath).extension()};
|
uint8_t counter{0};
|
||||||
fs::copy(entry.screenshot_filepath, basename + extension);
|
for (const auto &screenshot : entry.screenshot_filepaths)
|
||||||
|
{
|
||||||
|
++counter;
|
||||||
|
const string extension{fs::path(screenshot).extension()};
|
||||||
|
fs::copy(screenshot,
|
||||||
|
basename + "-" += to_string(counter) += extension);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add files.
|
// Add files.
|
||||||
|
|
22
src/json.cpp
22
src/json.cpp
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
#include "fs-compat.hpp"
|
#include "fs-compat.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
|
@ -25,13 +26,17 @@ namespace FediBlock::json
|
||||||
|
|
||||||
string to_json(const entry_type &entry)
|
string to_json(const entry_type &entry)
|
||||||
{
|
{
|
||||||
const string filename{fs::path(entry.screenshot_filepath).filename()};
|
vector<string> filenames;
|
||||||
|
for (const auto &screenshot : entry.screenshot_filepaths)
|
||||||
|
{
|
||||||
|
filenames.push_back(fs::path(screenshot).filename());
|
||||||
|
}
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const nlohmann::json json{{"instance", entry.instance},
|
const nlohmann::json json{{"instance", entry.instance},
|
||||||
{"tags", entry.tags},
|
{"tags", entry.tags},
|
||||||
{"receipts", entry.receipts},
|
{"receipts", entry.receipts},
|
||||||
{"description", entry.description},
|
{"description", entry.description},
|
||||||
{"screenshot", filename},
|
{"screenshots", filenames},
|
||||||
{"report_time", entry.report_time}};
|
{"report_time", entry.report_time}};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
return json.dump(4);
|
return json.dump(4);
|
||||||
|
@ -55,7 +60,18 @@ entry_type from_json(const string_view json_string)
|
||||||
entry.receipts = json[0].at("receipts").get<vector<string>>();
|
entry.receipts = json[0].at("receipts").get<vector<string>>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
entry.screenshot_filepath = json[0].at("screenshot").get<string>();
|
if (json[0].count("screenshot") == 1)
|
||||||
|
{
|
||||||
|
// Compatibility for old entries.
|
||||||
|
entry.screenshot_filepaths.push_back(
|
||||||
|
json[0].at("screenshot").get<string>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.screenshot_filepaths = json[0]
|
||||||
|
.at("screenshots")
|
||||||
|
.get<vector<string>>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if NLOHMANN_JSON_VERSION_MAJOR >= 3
|
#if NLOHMANN_JSON_VERSION_MAJOR >= 3
|
||||||
catch (const nlohmann::detail::out_of_range &) // Ignore missing screenshot.
|
catch (const nlohmann::detail::out_of_range &) // Ignore missing screenshot.
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct entry_type
|
||||||
vector<string> tags;
|
vector<string> tags;
|
||||||
vector<string> receipts;
|
vector<string> receipts;
|
||||||
string description;
|
string description;
|
||||||
string screenshot_filepath;
|
vector<string> screenshot_filepaths;
|
||||||
string report_time;
|
string report_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in New Issue