29namespace seqan3::detail
42inline void call_server(std::string
const & command, std::promise<bool> prom)
63 version_checker() =
delete;
64 version_checker(version_checker
const &) =
default;
65 version_checker & operator=(version_checker
const &) =
default;
66 version_checker(version_checker &&) =
default;
67 version_checker & operator=(version_checker &&) =
default;
68 ~version_checker() =
default;
75 version_checker(std::string name_, std::string
const & version_, std::string
const & app_url = std::string{}) :
76 name{std::move(name_)}
82 message_app_update.pop_back();
83 message_app_update.append(
"[APP INFO] :: Visit " + app_url +
" for updates.\n\n");
87 timestamp_filename = cookie_path / (name +
"_usr.timestamp");
89 timestamp_filename = cookie_path / (name +
"_dev.timestamp");
91 std::smatch versionMatch;
94 if (!version_.
empty() &&
95 std::regex_search(version_, versionMatch, std::regex(
"^([[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+).*")))
97 version = versionMatch.
str(1);
128 void operator()(std::promise<bool> prom)
130 std::array<int, 3> empty_version{0, 0, 0};
131 std::array<int, 3> srv_app_version{};
132 std::array<int, 3> srv_seqan_version{};
134 std::ifstream version_file{cookie_path / (name +
".version")};
141 if (line != unregistered_app)
142 srv_app_version = get_numbers_from_version_string(line);
145 std::cerr << message_unregistered_app;
149 srv_seqan_version = get_numbers_from_version_string(line);
151 version_file.
close();
155 if (srv_seqan_version != empty_version)
159 if (seqan_version < srv_seqan_version)
160 std::cerr << message_seqan3_update;
164 if (srv_app_version != empty_version)
167 if (get_numbers_from_version_string(version) < srv_app_version)
168 std::cerr << message_app_update;
172 if (get_numbers_from_version_string(version) > srv_app_version)
173 std::cerr << message_registered_app_update;
179 std::string program = get_program();
188 std::filesystem::path out_file = cookie_path / (name +
".version");
191 std::string command = program +
192 " " + out_file.
string() +
" "
193 + std::string{
"https://seqan-update.cs.uni-tuebingen.de/check/SeqAn3_"} +
207#if __x86_64__ || __ppc64__
215 "; exit [int] -not $?}\" > nul 2>&1";
221 std::thread(call_server, command, std::move(prom)).detach();
225 static std::filesystem::path get_path()
227 using namespace std::filesystem;
231 tmp_path = std::string{
getenv(home_env_name)};
232 tmp_path /=
".config";
250 path dummy = tmp_path /
"dummy.txt";
251 std::ofstream file{dummy};
252 detail::safe_filesystem_entry file_guard{dummy};
255 bool is_good = file.
good();
257 file_guard.remove_no_throw();
259 if (!is_good || !is_open)
292 bool decide_if_check_is_performed(
update_notifications developer_approval, std::optional<bool> user_approval)
297 if (
std::getenv(
"SEQAN3_NO_VERSION_CHECK") !=
nullptr)
301 return user_approval.
value();
306 std::ifstream timestamp_file{timestamp_filename};
307 std::string cookie_line{};
313 if (get_time_diff_to_current(cookie_line) < 86400 )
320 if (cookie_line ==
"NEVER")
324 else if (cookie_line ==
"ALWAYS")
330 timestamp_file.
close();
338 if (detail::is_terminal())
341#######################################################################
342 Automatic Update Notifications
343#######################################################################
345 This app can look for updates automatically in the background,
346 do you want to do that?
348 [a] Always perform version checks for this app.
349 [n] Never perform version checks for this app.
350 [y] Yes, perform a version check now, and ask again tomorrow.
351 [s] Skip the version check now, but ask again tomorrow (the default).
353 Please enter one of [a, n, y, s] and press [RETURN].
355 For more information, see:
356 https://github.com/seqan/seqan3/wiki/Update-Notifications
358#######################################################################
373 write_cookie(std::string{
"ALWAYS"});
378 write_cookie(std::string{
"NEVER"});
390#######################################################################
391 Automatic Update Notifications
392#######################################################################
393 This app performs automatic checks for updates. For more information
394 see: https://github.com/seqan/seqan3/wiki/Update-Notifications
395#######################################################################
403 static constexpr std::string_view unregistered_app =
"UNREGISTERED_APP";
405 static constexpr std::string_view message_seqan3_update =
406 "[SEQAN3 INFO] :: A new SeqAn version is available online.\n"
407 "[SEQAN3 INFO] :: Please visit www.github.com/seqan/seqan3.git for an update\n"
408 "[SEQAN3 INFO] :: or inform the developer of this app.\n"
409 "[SEQAN3 INFO] :: If you don't wish to receive further notifications, set --version-check false.\n\n";
411 static constexpr std::string_view message_unregistered_app =
412 "[SEQAN3 INFO] :: Thank you for using SeqAn!\n"
413 "[SEQAN3 INFO] :: Do you wish to register your app for update notifications?\n"
414 "[SEQAN3 INFO] :: Just send an email to support@seqan.de with your app name and version number.\n"
415 "[SEQAN3 INFO] :: If you don't wish to receive further notifications, set --version-check false.\n\n";
417 static constexpr std::string_view message_registered_app_update =
418 "[APP INFO] :: We noticed the app version you use is newer than the one registered with us.\n"
419 "[APP INFO] :: Please send us an email with the new version so we can correct it (support@seqan.de)\n\n";
421 std::string message_app_update =
422 "[APP INFO] :: A new version of this application is now available.\n"
423 "[APP INFO] :: If you don't wish to receive further notifications, set --version-check false.\n\n";
427 static constexpr char const * home_env_name{
438 std::string version{
"0.0.0"};
440 std::regex version_regex{
"^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+$"};
442 std::filesystem::path cookie_path = get_path();
444 std::filesystem::path timestamp_filename;
448 static std::string get_program()
451 return "powershell.exe -NoLogo -NonInteractive -Command \"& {Invoke-WebRequest -erroraction 'silentlycontinue' "
454 if (!
system(
"/usr/bin/env -i wget --version > /dev/null 2>&1"))
455 return "/usr/bin/env -i wget --timeout=10 --tries=1 -q -O";
456 else if (!
system(
"/usr/bin/env -i curl --version > /dev/null 2>&1"))
457 return "/usr/bin/env -i curl --connect-timeout 10 -o";
460# if defined(__OpenBSD__)
461 return "/usr/bin/env -i ftp -w10 -Vo";
462# elif defined(__FreeBSD__)
463 return "/usr/bin/env -i fetch --timeout=10 -o";
471 double get_time_diff_to_current(std::string
const & str_time)
const
473 namespace co = std::chrono;
474 double curr = co::duration_cast<co::seconds>(co::system_clock::now().time_since_epoch()).count();
479 return curr - d_time;
485 std::array<int, 3> get_numbers_from_version_string(std::string
const & str)
const
487 std::array<int, 3> result{};
503 template <
typename msg_type>
504 void write_cookie(msg_type && msg)
507 namespace co = std::chrono;
508 auto curr = co::duration_cast<co::seconds>(co::system_clock::now().time_since_epoch()).count();
510 std::ofstream timestamp_file{timestamp_filename};
514 timestamp_file << curr <<
'\n' << msg;
515 timestamp_file.
close();
Provides auxiliary information.
The <charconv> header from C++17's standard library.
T create_directory(T... args)
Provides various utility functions.
update_notifications
Indicates whether application allows automatic update notifications by the seqan3::argument_parser.
Definition auxiliary.hpp:268
@ off
Automatic update notifications should be disabled.
Definition auxiliary.hpp:270
from_chars_result from_chars(char const *first, char const *last, floating_point_type &value, chars_format fmt=chars_format::general) noexcept
Parse a char sequence into an floating point value.
Definition charconv:252
T regex_search(T... args)
Provides seqan3::detail::safe_filesystem_entry.
T temp_directory_path(T... args)
Checks if program is run interactively and retrieves dimensions of terminal (Transferred from seqan2)...
Provides SeqAn version macros and global variables.
#define SEQAN3_VERSION_MAJOR
The major version as MACRO.
Definition version.hpp:16
#define SEQAN3_VERSION_PATCH
The patch version as MACRO.
Definition version.hpp:20
#define SEQAN3_VERSION_MINOR
The minor version as MACRO.
Definition version.hpp:18