Compare commits

...
694 Commits
Author SHA1 Message Date
Alexander Shaduri b76bb1002e Windows: Bundle missing dlls needed by CI GTK. 2024-11-26 14:59:00 +04:00
Alexander Shaduri dea940222e GitHub CI: Fixed invalid artifact names. 2024-11-26 14:57:21 +04:00
Alexander Shaduri 4a075cc187 Bumped version to 2.0.1. 2024-11-26 14:04:37 +04:00
Alexander Shaduri e17c10c965 Windows: Bundle glib schemas to avoid native file dialog crash. 2024-11-26 13:59:52 +04:00
Alexander Shaduri 8c96c02468 Add a note about DPI awareness limitations. 2024-11-26 13:43:45 +04:00
Alexander Shaduri 4260f94ce7 Minor style issue in documentation. 2024-11-21 16:17:50 +04:00
Alexander Shaduri 21f73e4eae Add a note about SCSI / SAS support. 2024-11-21 16:14:13 +04:00
Alexander Shaduri 743173df81 Merge remote-tracking branch 'origin/main' 2024-11-19 18:22:46 +04:00
Alexander Shaduri 17b6ea23b4 Clarify device support in documentation. 2024-11-19 18:21:34 +04:00
Alexander Shaduri 840398c073 Fix potential crash in attribute description database. 2024-11-19 12:58:45 +04:00
Alexander Shaduri 93384e4c37 Fix compiler warning. 2024-11-19 12:39:01 +04:00
Alexander Shaduri 566b11026e Fix "Show SMART capable only" checkbox not having effect. 2024-11-07 14:48:18 +04:00
Alexander Shaduri 8fd2986a92 Update SECURITY.md for 2.0.0. 2024-11-07 14:00:47 +04:00
Alexander Shaduri e7dd2cf434 Recommend a 64-bit installer on Windows due to more testing. 2024-11-07 13:57:27 +04:00
Alexander Shaduri cdfbf8795a Update the Downloads page for 2.0.0. 2024-11-07 13:51:46 +04:00
Alexander Shaduri d110ddad10 Update NEWS.txt and other files in preparation for 2.0.0. 2024-11-07 13:09:59 +04:00
Alexander Shaduri 36cecf3acc Bumped version to 2.0.0. 2024-11-06 14:55:23 +04:00
Alexander Shaduri 066eaec993 Windows: Use Adwaita theme by default, win32 theme has too many problems (with Classic theme and with fractional dpi scaling). 2024-11-06 14:11:08 +04:00
Alexander Shaduri 746ebf9b02 Windows: Re-enable dpi awareness and scale up the font in case of fractional scaling. 2024-11-06 13:57:59 +04:00
Alexander Shaduri 1deffe6a98 Don't require gettext - we don't need it yet. 2024-11-06 12:38:04 +04:00
Alexander Shaduri 7ac61f1cac Fix crash on startup in Windows. 2024-11-06 12:37:48 +04:00
Alexander Shaduri e386c86316 Merge remote-tracking branch 'origin/main' 2024-11-05 17:28:48 +04:00
Alexander Shaduri da84eb027f Disable LTO in mingw due to CI errors. 2024-11-05 17:28:25 +04:00
Alexander Shaduri 1d9f2a2744 Fix win32 toolchain files for release builds. 2024-11-05 16:52:26 +04:00
Alexander Shaduri c1d0f46366 Make sure NSIS installer works. 2024-11-05 15:33:33 +04:00
Alexander Shaduri 99bf00d27c Fixed running "Update smartctl database" on Windows; use argv on all platforms so it is more secure. 2024-11-05 14:53:19 +04:00
Alexander Shaduri 7fd43bba2c Info window: Don't use Gtk::Stock for icons. 2024-11-05 14:15:19 +04:00
Alexander Shaduri 48f14267e5 Hide too noisy clang-tidy warning. 2024-11-05 14:00:50 +04:00
Alexander Shaduri b785a4fbec Replace bundled icons with the ones from Oxygen project; bundle removable drive icon; update copyrights accordingly. 2024-11-05 14:00:33 +04:00
Alexander Shaduri 3aa5ddfc32 Test results are presented in a more obvious manner now. 2024-11-04 20:38:47 +04:00
Alexander Shaduri c2277edb56 Show smartctl database version in basic properties. 2024-11-04 17:07:20 +04:00
Alexander Shaduri d82ec219f6 Refactoring: Split out property description code for ATA Attribute and ATA Statistic into separate files.
Added descriptions and warnings to NVMe Attributes.
Storage Property: Rely less on reported name (not as useful with JSON parser), more on generic name.
2024-11-04 16:56:10 +04:00
Alexander Shaduri dc007c84ab Fix ATA testing with when JSON parser is used. 2024-11-04 13:11:19 +04:00
Alexander Shaduri ccd04b86d3 Page tweaks. 2024-10-31 19:09:43 +04:00
Alexander Shaduri 0531a37133 Update pages remote theme (the old one was deleted). 2024-10-31 19:02:11 +04:00
Alexander Shaduri 566cff8ded Update pages remote theme (the old one was deleted). 2024-10-31 18:57:24 +04:00
Alexander Shaduri 74c5e92d4b Do not remove NVMe devices namespaces if a device has more than one namespace. 2024-10-31 16:21:43 +04:00
Alexander Shaduri aaa374c8ed Fix self-test status execution returning error. 2024-10-31 16:21:15 +04:00
Alexander Shaduri 2a6902dbb5 Support self-tests on WD NVMe with smartctl < 7.5. 2024-10-31 16:05:07 +04:00
Alexander Shaduri 02206a8967 Minor code cleanups. 2024-10-31 15:56:23 +04:00
Alexander Shaduri af2a5a18b3 "Perform Tests" menu item is correctly disabled now if self-tests are not supported; if support is unknown, an appropriate message is shown after the Info window is displayed. 2024-10-31 15:47:42 +04:00
Alexander Shaduri 1d0e325813 JSON Basic Parser: Make sure the health property is in the health section (fixes GUI not displaying health after first scan). 2024-10-31 15:21:02 +04:00
Alexander Shaduri f4e22a5c96 Windows: Add a note about why hidpi is disabled. 2024-10-31 15:18:01 +04:00
Alexander Shaduri fb468f8594 Windows: Fixed auto-detection issues, minor refactoring of the detection code. 2024-10-31 14:26:20 +04:00
Alexander Shaduri 4ff0aaad9c Hide self-test tab if NVMe does not support self-tests. 2024-06-11 13:53:23 +04:00
Alexander Shaduri c0eb5e2087 Renamed bundled icon files. 2024-06-11 13:48:41 +04:00
Alexander Shaduri c795635469 Improve device type detection. 2024-06-11 13:47:11 +04:00
Alexander Shaduri e844b9949d Detection of NVMe self-test support. 2024-06-11 13:46:57 +04:00
Alexander Shaduri 5c807e1859 Fix missing include. 2024-06-11 13:29:35 +04:00
Alexander Shaduri b2edaf69c1 Fix data member naming convention. 2024-06-11 13:29:25 +04:00
Alexander Shaduri dfa6d043b3 Improve per-drive-type icon selection. 2024-06-11 13:16:24 +04:00
Alexander Shaduri 5e3f01f350 Fixed function naming convention. 2024-06-11 13:15:40 +04:00
Alexander Shaduri f9a098d67b Merge pull request #62 from skitt/package-name
Add the package name to the icons and ui paths
2024-06-11 12:22:18 +04:00
Stephen Kitt 3324e27dee Add the package name to the icons and ui paths
CMAKE_INSTALL_FULL_DATADIR gives the read-only
architecture-independent data root without the package name, so
BuildEnv::package_pkgdata_dir() only returns that ("/usr/share" or
equivalent). This adds the package name to the appropriate search
paths in app_init_and_loop().

Signed-off-by: Stephen Kitt <steve@sk2.org>
2024-06-05 16:01:47 +02:00
Alexander Shaduri 25f1c62d2c Support NVMe behind USB bridges. 2024-05-31 12:50:03 +04:00
Alexander Shaduri afd6ce0a1f Fix CI. 2024-05-29 13:36:00 +04:00
Alexander Shaduri fb62473b0b Fix CI. 2024-05-29 12:49:04 +04:00
Alexander Shaduri 9b1bc82353 Extract smartmontools before running cmake. 2024-05-29 12:23:51 +04:00
Alexander Shaduri d1f0b517e4 More debug messages. 2024-05-29 11:24:22 +04:00
Alexander Shaduri ec50159a15 Add listing of files for debugging. 2024-05-29 11:06:38 +04:00
Alexander Shaduri a7f513fd7c Fix CPack rules. 2024-05-28 14:07:20 +04:00
Alexander Shaduri 698024d47d Fix CPack rules. 2024-05-28 13:44:00 +04:00
Alexander Shaduri eb8d91470b Fix CPack rules. 2024-05-28 13:34:50 +04:00
Alexander Shaduri 780f22818e CPack improvements for Windows. 2024-05-28 11:59:49 +04:00
Alexander Shaduri fdcf9f7099 Fix security warning. 2024-05-28 11:25:59 +04:00
Alexander Shaduri ec0445ec54 Merge remote-tracking branch 'origin/main' 2024-05-28 11:21:13 +04:00
Alexander Shaduri 75f50cd5bb Update workflows with latest permissions. 2024-05-28 11:19:51 +04:00
Alexander Shaduri 4d1af3ce9c Merge pull request #61 from skitt/canonical-nlohmann-json
Use the canonical nlohmann json include path.
2024-05-28 10:53:52 +04:00
Stephen Kitt 7b6aa046f4 Use the canonical nlohmann json include path
As documented in https://github.com/nlohmann/json, the canonical
include path for json.hpp is nlohmann/json.hpp. Tihs updated the
vendored dependency to match, so that gsmartcontrol can more easily be
built using a system-installed copy of nlohmann json as well as the
vendored copy.

Signed-off-by: Stephen Kitt <steve@sk2.org>
2024-05-27 13:31:27 +02:00
Alexander Shaduri 844f6ed86f Add workflow for creating Windows Release packages. 2024-05-22 13:44:06 +04:00
Alexander Shaduri 7a8cbe202e Use llvm17 in FreeBSD. 2024-05-22 13:34:56 +04:00
Alexander Shaduri ec2a4648e1 Upgrade freebsd build to latest version of action. 2024-05-22 12:59:23 +04:00
Alexander Shaduri 186682b6d4 Updated NEWS.txt to include information about 1.1.4. 2024-05-22 12:01:55 +04:00
Alexander Shaduri db6811450e Remove local_glibmm.h workaround for broken libintl.h. 2024-05-22 11:51:41 +04:00
Alexander Shaduri 1c19b51fda Moved application GUI source files to gui subdirectory. 2024-05-22 11:46:02 +04:00
Alexander Shaduri 28cad446b7 Packaging fixes. 2024-05-21 20:33:04 +04:00
Alexander Shaduri 84867cc474 Create and use cmake toolchains for msys2. 2024-05-21 16:46:53 +04:00
Alexander Shaduri 13c644efdc List msys2 files for debugging. 2024-05-21 14:47:26 +04:00
Alexander Shaduri 5085c35269 List msys2 files for debugging. 2024-05-21 14:46:30 +04:00
Alexander Shaduri 7682f1285e Merge remote-tracking branch 'origin/main' 2024-05-20 17:41:41 +04:00
Alexander Shaduri 74a0cf012b Refactored so that executor options are given as a vector, not as a string; this improves reliability as the string does not have to be shell-parsed. 2024-05-20 17:41:29 +04:00
Alexander Shaduri d356e2e79f Add nvme as a type option in GUI. 2024-05-20 17:40:41 +04:00
Alexander Shaduri fe027b7fc7 Update windows packaging. 2024-05-17 17:09:22 +04:00
Alexander Shaduri 501134c2fd Use double-quoting of commands in Windows. 2024-05-17 16:56:44 +04:00
Alexander Shaduri debe2e63cb Github issue template tweaks. 2024-05-17 14:38:52 +04:00
Alexander Shaduri 4452ec50fb Updated OBS workflow repositories. 2024-05-17 14:38:21 +04:00
Alexander Shaduri f034f45b93 Packaging fixes. 2024-05-17 14:10:19 +04:00
Alexander Shaduri 5160486dcd Packaging fixes. 2024-05-17 14:04:24 +04:00
Alexander Shaduri 876c586620 Packaging fixes. 2024-05-17 13:59:47 +04:00
Alexander Shaduri 85ef6faf7d Packaging fixes. 2024-05-17 13:40:46 +04:00
Alexander Shaduri 6004a76884 Packaging fixes. 2024-05-17 13:39:54 +04:00
Alexander Shaduri 944829a6be Packaging fixes. 2024-05-17 13:34:29 +04:00
Alexander Shaduri 9b75a426c5 Packaging fixes. 2024-05-17 13:26:32 +04:00
Alexander Shaduri d6d63b7f88 Packaging fixes. 2024-05-17 13:14:01 +04:00
Alexander Shaduri d9adde161c Packaging fixes. 2024-05-17 13:12:03 +04:00
Alexander Shaduri 3d45bbe12a Packaging fixes. 2024-05-17 13:09:13 +04:00
Alexander Shaduri 90be761780 Updated packaging. 2024-05-17 12:49:47 +04:00
Alexander Shaduri 22c5cfdffd Updated packaging. 2024-05-17 12:46:06 +04:00
Alexander Shaduri 7834f61662 Updated packaging. 2024-05-17 12:43:04 +04:00
Alexander Shaduri cafb1ef28d Updated packaging. 2024-05-17 12:29:44 +04:00
Alexander Shaduri 4211374126 Updated documentation to indicate NVMe support. 2024-05-17 11:38:57 +04:00
Alexander Shaduri cfa50198ee Removed unused cmake file. 2024-05-17 11:37:35 +04:00
Alexander Shaduri f4c1cebfd0 Update cron script to use json. 2024-05-17 11:24:52 +04:00
Alexander Shaduri 7cef499e67 Use ubuntu-24.04 for Actions as ubuntu-latest does not have gcc13 as of now. 2024-05-16 17:04:37 +04:00
Alexander Shaduri e40da83827 Merge pull request #60 from ashaduri/stdregex
PCRE to std::regex port
2024-05-16 16:49:27 +04:00
Alexander Shaduri d916dc4a9d Removed mention of any pcre dependency. 2024-05-16 16:47:44 +04:00
Alexander Shaduri 791cc93f5f Fixed std::regex-based parsing. 2024-05-16 16:41:39 +04:00
Alexander Shaduri 1df72dc2e0 Initial port from pcre to std::regex (not working yet). 2024-05-16 16:27:18 +04:00
Alexander Shaduri cf3a9f6ae3 Partial port from pcre to std::regex. 2024-05-16 15:13:34 +04:00
Alexander Shaduri 946f4b4339 Fix test failure under Arm architecture. 2024-05-15 13:48:48 +04:00
Alexander Shaduri e88a0b5ca3 Limit the VM memory. 2024-05-15 13:42:50 +04:00
Alexander Shaduri 6d23e01a82 Fixed running tests under Arm. 2024-05-15 13:42:38 +04:00
Alexander Shaduri 0f8c6039ce Update GitHub actions. 2024-05-15 13:12:49 +04:00
Alexander Shaduri 2abae1c673 Update GitHub actions. 2024-05-15 13:07:05 +04:00
Alexander Shaduri 1e16d7b521 Update GitHub actions. 2024-05-15 12:26:40 +04:00
Alexander Shaduri 55dade8b51 Install clang. 2024-05-15 12:18:42 +04:00
Alexander Shaduri 2e53d3e4c9 Try AppleClang 16. 2024-05-15 12:09:52 +04:00
Alexander Shaduri 4a0ce23184 Compile with AppleClang 15. 2024-05-15 12:00:33 +04:00
Alexander Shaduri 02535eeeb2 Update GitHub actions. 2024-05-14 18:35:42 +04:00
Alexander Shaduri 6d49968a59 Fix make_format_args() calls. 2024-05-14 18:30:46 +04:00
Alexander Shaduri 84ae416c2c Removed AODC feature, it's been deprecated for a while. 2024-05-14 17:42:46 +04:00
Alexander Shaduri dd4fd4d187 Fixed loading text files as virtual devices (size parsing, ATA detection). 2024-05-14 17:26:51 +04:00
Alexander Shaduri ade001359b Implemented loading virtual drives from JSON. 2024-05-14 16:57:01 +04:00
Alexander Shaduri ac2d3d6b33 Implement proper SMART on/off switch support detection. 2024-05-14 15:55:12 +04:00
Alexander Shaduri 537ea258ca NVMe: Full support for self-testing. 2024-05-14 15:41:27 +04:00
Alexander Shaduri 32302c6a80 Info Window: Fixed refresh not working with treeviews. 2024-05-14 15:11:06 +04:00
Alexander Shaduri 5ba969c561 NVMe: Support self-test log and running self-tests (untested). 2024-05-14 14:27:24 +04:00
Alexander Shaduri 5a4e60f645 Format LBA in locale-aware way. 2024-05-14 14:26:37 +04:00
Alexander Shaduri 456feb645a NVMe: Show Error Log. 2024-05-14 11:50:27 +04:00
Alexander Shaduri 556a82e42b NVMe: Show attributes in Info window. 2024-05-13 18:11:06 +04:00
Alexander Shaduri 57f7b6d000 Make Info window display tabs only if properties with appropriate sections are available. 2024-05-13 17:17:24 +04:00
Alexander Shaduri 67a0b128f7 Display info properly for flash drives. 2024-05-13 16:49:07 +04:00
Alexander Shaduri f60f08327c Info Window: Adapt to ATA JSON parser. 2024-05-13 16:48:48 +04:00
Alexander Shaduri 72c01bebba NVMe: Parse error log. 2024-05-13 16:48:26 +04:00
Alexander Shaduri dede4695e9 ATA JSON parser is on par with Text parser now, feature-wise. 2024-05-13 16:48:01 +04:00
Alexander Shaduri 5efefd3576 Implemented NVMe self-test log parsing.
Refactoring AtaStorageProperty -> StorageProperty.
2024-05-07 19:36:40 +04:00
Alexander Shaduri 516eaa2086 Basic NVMe parser implemented. 2024-05-02 15:20:16 +04:00
Alexander Shaduri c3a6f0b624 Implemented detection of device type. 2024-05-02 14:38:31 +04:00
Alexander Shaduri 6594cddb65 Refactored drive data fetch and parsing, and drive types. 2024-05-02 13:47:20 +04:00
Alexander Shaduri bf2343015e Avoid unnecessary exceptions when reading config file. 2024-05-02 13:47:14 +04:00
Alexander Shaduri 228bcf5014 Fixed enum_helper.h errors. 2024-05-02 13:46:49 +04:00
Alexander Shaduri 589263e902 etc... -> etc. 2024-04-25 16:53:30 +04:00
Alexander Shaduri 02bdf755a3 Fixed crash on reload; tables still to be fixed. 2024-04-25 16:44:25 +04:00
Alexander Shaduri 61fe92e201 ATA JSON parser improvements. 2024-04-24 15:58:45 +04:00
Alexander Shaduri 1b7264793e ATA JSON parser improvements. 2024-04-24 15:51:01 +04:00
Alexander Shaduri 13fc56c24a Updated visible copyright years. 2024-04-23 17:18:08 +04:00
Alexander Shaduri 18a6628d0e Support parsing more of ATA output in JSON. 2024-04-23 17:03:52 +04:00
Alexander Shaduri 5746ab5ed9 GitHub actions: Fix conflicting artifact names. 2024-04-23 16:32:59 +04:00
Alexander Shaduri ac90991a27 GitHub actions: Support smartmontools 7.4 installer directory structure when extracting. 2024-04-23 14:11:31 +04:00
Alexander Shaduri 531d39d888 Smartmontools in Windows uses update-smart-drivedb.ps1 now, so use that. 2024-04-23 13:51:51 +04:00
Alexander Shaduri 68576e9a95 Use smartmontools 7.4 in CI. 2024-04-23 13:31:01 +04:00
Alexander Shaduri f7d9956665 Support parsing ATA Self-test Log in JSON.
UI fixes.
2024-04-23 12:55:23 +04:00
Alexander Shaduri aa0c2e520f Updated GitHub actions to use Node20 versions. 2024-04-22 22:19:14 +04:00
Alexander Shaduri 9ea48c7298 Fix win32 compilation. 2024-04-22 22:05:36 +04:00
Alexander Shaduri c065e55ca1 GH Actions: Use GCC 13, that is the minimum required now. 2024-04-22 18:08:34 +04:00
Alexander Shaduri 2c163503d9 GH Actions: Use GCC 12. 2024-04-22 17:48:34 +04:00
Alexander Shaduri 212b6bfe4f Fix compilation. 2024-04-22 17:22:14 +04:00
Alexander Shaduri ea6998dcad Support parsing ATA Directory Log in JSON. 2024-04-22 17:17:00 +04:00
Alexander Shaduri d6ec442945 Support parsing ATA Attributes in JSON. 2024-04-19 14:21:06 +04:00
Alexander Shaduri 6da27f7e86 Support parsing ATA Capabilities from JSON. 2024-04-19 11:47:48 +04:00
Alexander Shaduri 50d605b5b4 Updated .clang-tidy to ignore library headers. 2024-04-19 11:47:25 +04:00
Alexander Shaduri b147a3db3e Ported some more of string_algo.h to string_view. 2024-04-19 11:46:51 +04:00
Alexander Shaduri 6018f35598 Disable std::filesystem TR support, we require C++20 anyway. 2024-04-16 12:40:10 +04:00
Alexander Shaduri fccf448b3a Bundle and use tl::expected instead of std::expected to support C++20 compilers. 2024-04-16 12:39:22 +04:00
Alexander Shaduri 0cd846728c Fixed compiler warnings. 2024-04-15 17:15:00 +04:00
Alexander Shaduri 876e29973c Simplified AtaStorageProperty by mergin Section and SubSection. 2024-04-15 16:29:51 +04:00
Alexander Shaduri 351f5edaa9 Switched most of message-based error handling to std::expected.
Refactored enum class naming to use ThisCase.
Decorated most getters with [[nodiscard]].
2024-03-22 18:21:08 +04:00
Alexander Shaduri 6edcf19694 Implemented Basic Output JSON parser.
Switched all devices to JSON by default.
2024-03-20 23:11:50 +04:00
Alexander Shaduri 73463e5c23 Cleanup of output format / device type handling. 2024-03-20 20:57:16 +04:00
Alexander Shaduri 21267acb8c Separate out basic text parser from StorageDevice.
Store all properties in StoragePropertyRepository.
2024-03-20 20:29:19 +04:00
Alexander Shaduri 9889f8792f Initial work on JSON parser. 2024-03-19 16:16:36 +04:00
Alexander Shaduri ae5a327116 Initial work on JSON parser. 2024-03-15 17:33:24 +04:00
Alexander Shaduri 8b12bb45c3 Initial work on JSON parser. 2024-03-15 16:59:14 +04:00
Alexander Shaduri a32b9fb8a9 Initial work on JSON parser. 2024-03-14 16:06:16 +04:00
Alexander Shaduri eb44ed1bc5 Some code modernization. 2024-03-14 13:52:46 +04:00
Alexander Shaduri 5fe252934c Disabled false positive. 2024-03-11 15:25:38 +04:00
Alexander Shaduri 3c4a740759 Improved constness of local variables. 2024-03-11 15:25:14 +04:00
Alexander Shaduri 29555ed584 Ported away from deprecated u8path(). 2024-03-11 14:53:05 +04:00
Alexander Shaduri f454b9df2d Disabled noisy warnings. 2024-03-11 14:50:21 +04:00
Alexander Shaduri 6266ce3c6c Ported SmartctlParser to std::expected, added hz::ErrorContainer as a helper. 2024-03-11 14:50:08 +04:00
Alexander Shaduri d0cfd73fab Removed leaf, porting to std::expected. 2024-03-07 14:39:08 +04:00
Alexander Shaduri 985700c79d Moved to C++23, making the code compatible with it (u8string / u8path incompatibilities). 2024-03-07 14:38:44 +04:00
Alexander Shaduri e650fa4d8b Fixed a typo. 2024-02-29 18:28:35 +04:00
Alexander Shaduri 72b2173dfc Make sure to require Gtkmm. 2024-02-29 18:28:16 +04:00
Alexander Shaduri 7f688e0fa4 Initial work on JSON parser. 2023-03-06 19:18:48 +04:00
Alexander Shaduri c8f79c36b4 Minor cleanups. 2023-03-06 19:18:16 +04:00
Alexander Shaduri 396ea3daf3 Fixed some clang-tidy warnings. 2023-03-03 23:00:52 +04:00
Alexander Shaduri c4b2c1d760 Merge pull request #41 from ferdnyc/no-warn-printf
FindFilesystem: Eliminate Win32 warning
2023-01-16 13:32:31 +04:00
FeRD (Frank Dana) 0bf4ef711e FindFilesystem: Eliminate Win32 warning
Using `printf("%s")` with a `std::filesystem::path` on Win32 will
cause a compile warning, because `std::filesystem::path::value_type`
is technically `wchar_t`.

The warning is harmless, but by using iostream to print the value
on `std::cout` instead, the code compiles without warnings.
2023-01-15 12:54:17 -05:00
Alexander Shaduri affdd497ec Updated GitHub actions to use Node16 (try 2). 2023-01-09 18:18:29 +04:00
Alexander Shaduri 6b6bd2e369 GitHub action: Fix codeql. 2023-01-09 17:44:05 +04:00
Alexander Shaduri 466b4f9a0f GitHub action: Install pcre in msys2. 2023-01-09 17:43:02 +04:00
Alexander Shaduri e90aad5994 Updated GitHub actions to use Node16. 2023-01-09 17:41:21 +04:00
Alexander Shaduri 338c8a8eee Merge remote-tracking branch 'origin/main' 2023-01-09 17:28:04 +04:00
Alexander Shaduri a390c3daa6 Updated Catch2 to 2.13.10. 2023-01-09 17:27:52 +04:00
Alexander Shaduri 9e0dbe67e6 Ignore doxygen_doc in git. 2023-01-09 17:14:03 +04:00
Alexander Shaduri 6b02bf5df0 Update _config.yml 2022-09-14 12:38:20 +04:00
Alexander Shaduri 029f519005 Update SECURITY.md 2022-06-17 12:35:41 +04:00
Alexander Shaduri b6248459be Update issue templates 2022-06-17 12:34:08 +04:00
Alexander Shaduri 51e3b2a1f7 Update issue templates 2022-06-17 12:33:50 +04:00
Alexander Shaduri b2504e9477 Update issue templates 2022-06-17 12:32:35 +04:00
Alexander Shaduri ec6ddd1c5c Update SECURITY.md 2022-06-17 12:30:44 +04:00
Alexander Shaduri 60705fe93b Update issue templates 2022-06-17 12:29:37 +04:00
Alexander Shaduri cf407da41b Update issue templates 2022-06-17 12:27:01 +04:00
Alexander Shaduri 5435feb932 Windows: Make sure we consider non-fixed drives as well, when detecting "Drive letters" for a drive. 2022-05-20 13:04:26 +04:00
Alexander Shaduri 02e4f8e536 GitHub Actions: Use github.workspace instead of runner.workspace. 2022-03-15 14:12:30 +04:00
Alexander Shaduri db090f9164 Updated github pages: Document NSIS options. 2022-02-18 12:12:40 +04:00
Alexander Shaduri 70967beebf Implemented smartctl output format detection function, along with its test. 2022-02-16 17:33:05 +04:00
Alexander Shaduri 5b7c2f6dbb Added helper for testing leaf-created errors. 2022-02-16 17:32:20 +04:00
Alexander Shaduri 2d7a3a4dd9 Updated clang-tidy configuration to exclude noisy warnings. 2022-02-16 17:30:06 +04:00
Alexander Shaduri 01d699fc74 Make sure the third-party libraries are always included as "system". 2022-02-15 16:30:27 +04:00
Alexander Shaduri 6ed82f821f Added a Boost LEAF library copy. 2022-02-15 16:29:45 +04:00
Alexander Shaduri c59fa32efe Added a Boost LEAF library copy. 2022-02-15 16:22:41 +04:00
Alexander Shaduri dbdb0e4686 Fixed compilation. 2022-02-15 16:22:00 +04:00
Alexander Shaduri fc0df14992 Refactored smartctl output parser for better API, support for different formats. 2022-02-15 15:56:42 +04:00
Alexander Shaduri a5771f1af9 Updated OBS workflows. 2022-02-15 14:03:35 +04:00
Alexander Shaduri 4db097b0b0 Update cmake requirement to 3.14. 2022-02-15 14:03:24 +04:00
Alexander Shaduri 65e4c4f7ac Revert "Fixed test link errors on Debian 10."
This reverts commit 5009fbfbe4.
2022-02-15 14:01:51 +04:00
Alexander Shaduri d1df4b2fad Updated OBS workflows. 2022-02-15 13:44:01 +04:00
Alexander Shaduri 5009fbfbe4 Fixed test link errors on Debian 10. 2022-02-15 13:42:43 +04:00
Alexander Shaduri cbfcf2bb3c Updated OBS workflows. 2022-02-15 12:58:32 +04:00
Alexander Shaduri 63e16d0bac Updated OBS workflows. 2022-02-14 17:27:51 +04:00
Alexander Shaduri cd58c6ce90 Updated OBS workflows. 2022-02-14 15:29:41 +04:00
Alexander Shaduri 6787b3c1fe Updated OBS workflows. 2022-02-14 15:27:04 +04:00
Alexander Shaduri 980ff6f150 Updated OBS workflows. 2022-02-14 15:25:16 +04:00
Alexander Shaduri ef5f97ad88 Updated OBS workflows. 2022-02-14 15:20:21 +04:00
Alexander Shaduri 9ad97c8390 Added OBS workflow integration. 2022-02-14 14:33:12 +04:00
Alexander Shaduri 8256ea2115 Fixed CodeQL workflow. 2022-02-14 14:32:51 +04:00
Alexander Shaduri b6f97ba0a4 Updated github actions. 2022-02-14 13:46:42 +04:00
Alexander Shaduri 88a36c6f57 Changed internal property names to match smartctl's json paths. 2022-02-14 13:21:23 +04:00
Alexander Shaduri 8932460b8c Updated github pages. 2022-02-13 13:43:21 +04:00
Alexander Shaduri 7e570cea45 Refactored parse_byte_size out of SmartctlAtaTextParser. 2022-02-11 18:04:54 +04:00
Alexander Shaduri 1d781d3d54 Code cleanups. 2022-02-11 16:01:10 +04:00
Alexander Shaduri c1070e375f Added initial work for selecting smartctl parser type.
Refactored smartctl version parsing, added tests.
2022-02-11 16:00:21 +04:00
Alexander Shaduri 582d4ad5cd Converted hz string algorithms example into a test. 2022-02-11 14:08:57 +04:00
Alexander Shaduri 907c9ac423 Refactored example_string_num.cpp into a test.
Fixed underflow detection for unsigned types in hz::string_is_numeric().
2022-02-11 13:43:22 +04:00
Alexander Shaduri f9c805648a Converted hz unit formatting example into a test. 2022-02-10 17:17:06 +04:00
Alexander Shaduri 94e3e864bc Merge remote-tracking branch 'origin/main' into main 2022-02-10 16:45:45 +04:00
Alexander Shaduri 53acbd9594 libdebug: Removed C-style debug_print*() functions, ported everything to debug_out_*(). 2022-02-10 16:45:33 +04:00
Alexander Shaduri 085f066958 rconfig: A safer way to pass data to a C callback. 2022-02-10 16:44:08 +04:00
Alexander Shaduri 594f177160 Merge pull request #27 from skitt/lcall
Set LC_ALL to control the locale of other processes.
2022-02-10 12:18:23 +04:00
Stephen Kitt c53166f630 Set LC_ALL to control the locale
LANG specifies the default locale, LC_NUMERIC specifies the locale for
that particular category, but LC_ALL overrides all the locale
settings. Thus any user with LC_ALL set can still run into
locale-related problems.

Setting LC_ALL to C avoids any such issue.

See locale(7) for details.

Signed-off-by: Stephen Kitt <steve@sk2.org>
2022-02-10 08:26:34 +01:00
Alexander Shaduri 64f4a8077e Updated links to the new gsmartcontrol.shaduri.dev site. 2022-02-09 17:51:09 +04:00
Alexander Shaduri a4bfdcefa8 Updated github pages. 2022-02-09 17:33:20 +04:00
Alexander Shaduri e6b83c7473 Updated links to online documentation. 2022-02-08 19:21:45 +04:00
Alexander Shaduri 107292a328 Updated github pages. 2022-02-08 19:16:25 +04:00
Alexander Shaduri 9f31c845ee Updated github pages. 2022-02-08 18:39:26 +04:00
Alexander Shaduri 3acee26d05 Updated github pages. 2022-02-08 18:36:44 +04:00
Alexander Shaduri 1b260fd745 Updated github pages. 2022-02-08 18:35:32 +04:00
Alexander Shaduri 02dd6176d7 Updated github pages. 2022-02-08 18:32:33 +04:00
Alexander Shaduri d19c6acadd Updated github pages. 2022-02-08 18:26:53 +04:00
Alexander Shaduri 911ec96207 Updated github pages. 2022-02-08 18:10:21 +04:00
Alexander Shaduri 1cefc9d9ba Updated github pages. 2022-02-08 17:27:56 +04:00
Alexander Shaduri da1b73feee Updated github pages. 2022-02-08 17:22:10 +04:00
Alexander Shaduri 8ce7d781a4 Updated github pages. 2022-02-08 17:16:55 +04:00
Alexander Shaduri 3db5941757 Updated github pages. 2022-02-08 16:56:15 +04:00
Alexander Shaduri 8b925ae0c4 Updated github pages. 2022-02-08 15:31:34 +04:00
Alexander Shaduri ea7f65725e Updated github pages and README.md. 2022-02-08 15:28:13 +04:00
Alexander Shaduri 137736d6eb Updated github pages. 2022-02-08 13:05:27 +04:00
Alexander Shaduri d0136e6a71 Updated github pages. 2022-02-07 19:05:35 +04:00
Alexander Shaduri 9abb0ff3a9 Update README.md 2022-02-04 15:42:05 +04:00
Alexander Shaduri b706b114b3 Use ubuntu-latest in github action. 2022-02-04 14:33:41 +04:00
Alexander Shaduri 3085c037ba Bumped Debian package compatibility level to 9. 2022-02-04 14:29:43 +04:00
Alexander Shaduri c34ddd32a5 Split github tier2 builds into standard and flaky actions. 2022-02-04 14:29:26 +04:00
Alexander Shaduri 3c10a1e12a Fix syntax errors in cs.po. 2022-02-04 14:24:19 +04:00
Alexander Shaduri a154a813ad Use Catch2 v2 instead of v3 due to build errors with latest compilers. 2022-02-04 14:24:01 +04:00
Alexander Shaduri 3b5c7365a1 Windows: Embed exe manifest in the resource; don't handle the manifest in NSIS. 2022-02-04 12:02:44 +04:00
Alexander Shaduri 0f78b7e91c Windows: Set GTK_CSD=0 only if no GTK_CSD is set. 2022-02-04 12:02:04 +04:00
Alexander Shaduri cf93bf008f Updated Catch2 to git devel branch 2022-02-02. 2022-02-02 23:42:47 +04:00
Alexander Shaduri 2bbe7788f1 Ubuntu package: Fixed support for Ubuntu 21.10 on OBS. 2022-02-02 23:37:21 +04:00
Alexander Shaduri 025348bfe3 Remove trailing slash from homepage URL. 2022-02-02 23:14:15 +04:00
Alexander Shaduri 4cf809b579 Debian package: Fixed support for Debian Testing and Debian Unstable on OBS. 2022-02-02 23:13:53 +04:00
Alexander Shaduri 9e1d92a7bc Debian package: Build tests and examples, this should fix OBS build failures. 2022-02-02 23:09:20 +04:00
Alexander Shaduri ef94137edc Info Window: Make the text views with output texts use monospace font with the new GTK versions. 2022-02-01 13:46:43 +04:00
Alexander Shaduri 910f71ec9e Info Window: Align and monospace table cells where applicable to improve readability. 2022-02-01 13:31:18 +04:00
Alexander Shaduri f4973cdb4b Handle all tree view styling in per-table cell renderers; this fixes conflicts between renderer styles and markup. 2022-02-01 12:51:48 +04:00
Alexander Shaduri 4dcc8e23e7 List all gtkmm deprecation macros for future reference. 2022-02-01 12:45:41 +04:00
Alexander Shaduri 044193c7ed Command execution popup windows: Use "dialog" type of window instead of "notifications"; this should fix #17 (the popup is floating above all the other applications). 2022-01-31 15:29:14 +04:00
Alexander Shaduri 29b2bb6635 Merge remote-tracking branch 'origin/main' into main 2022-01-31 15:11:12 +04:00
Alexander Shaduri d9f0314655 Code cleanup - reduce std::wcslen usage. 2022-01-31 15:11:04 +04:00
Alexander Shaduri af6c230edc Update devskim-analysis.yml 2022-01-31 15:09:50 +04:00
Alexander Shaduri 01746ab16d Ported some win32_tools.h code to std::filesystem. 2022-01-31 14:38:31 +04:00
Alexander Shaduri 5865134b29 Code cleanup - reduce std::strlen usage. 2022-01-29 22:27:12 +04:00
Alexander Shaduri 39d033c50d Fixed Codacy note in shell script. 2022-01-29 21:48:35 +04:00
Alexander Shaduri f64b3bc82d Added license badge to README.md 2022-01-29 21:45:01 +04:00
Alexander Shaduri 3f2353cc57 Updated README.md for style. 2022-01-29 21:29:49 +04:00
Alexander Shaduri bc20a790da Merge remote-tracking branch 'origin/main' into main 2022-01-29 21:27:48 +04:00
Alexander Shaduri a238770418 Update style. 2022-01-29 21:25:47 +04:00
Alexander Shaduri 90eb339a05 Fixed Codacy warnings in shell scripts. 2022-01-29 21:12:36 +04:00
Alexander Shaduri fa16ff964e Merge remote-tracking branch 'origin/main' into main 2022-01-29 11:57:08 +04:00
Alexander Shaduri ebb864f234 Add nullptr check to on_cell_data_render(), just in case. 2022-01-29 11:56:54 +04:00
Alexander Shaduri 01a33b97a7 Merge pull request #25 from codacy-badger/codacy-badge
Add a Codacy badge to README.md
2022-01-27 23:07:22 +04:00
Alexander Shaduri 8b05464444 Delete msvc-analysis.yml 2022-01-27 23:04:16 +04:00
The Codacy Badger 977396e852 Add Codacy badge 2022-01-27 18:33:50 +00:00
Alexander Shaduri 84b6e84c49 Update devskim-analysis.yml 2022-01-27 22:19:55 +04:00
Alexander Shaduri 33b96b459e Update msvc-analysis.yml 2022-01-27 22:18:08 +04:00
Alexander Shaduri a095f9f6bd Delete scorecards-analysis.yml 2022-01-27 22:01:48 +04:00
Alexander Shaduri 828558bfcc Update devskim-analysis.yml 2022-01-27 21:57:52 +04:00
Alexander Shaduri e49b0cbf8c Update codeql-analysis.yml 2022-01-27 21:49:28 +04:00
Alexander Shaduri 39fc4b2997 Create CODE_OF_CONDUCT.md 2022-01-25 17:14:04 +04:00
Alexander Shaduri 5d2925fd94 Create SECURITY.md 2022-01-25 17:08:56 +04:00
Alexander Shaduri f6a2a1cab5 Create scorecards-analysis.yml 2022-01-25 17:05:30 +04:00
Alexander Shaduri 661bcfe56e Create msvc-analysis.yml 2022-01-25 17:04:03 +04:00
Alexander Shaduri 821da2ce29 Create devskim-analysis.yml 2022-01-25 17:03:11 +04:00
Alexander Shaduri 38ee3fabd9 Create codacy-analysis.yml 2022-01-25 17:02:01 +04:00
Alexander Shaduri ac54d29f66 Create codeql-analysis.yml 2022-01-25 17:00:46 +04:00
Alexander Shaduri b27b04ebf0 Fixed building under Windows. 2022-01-25 16:54:42 +04:00
Alexander Shaduri 055438e740 Place less code in #ifdef _WIN32 to make platform-specific compilation less error-prone. 2022-01-25 16:42:10 +04:00
Alexander Shaduri 5f11e9a7ce Fixed building under Windows. 2022-01-18 16:31:13 +04:00
Alexander Shaduri f128de2b30 Fixed building non-debug builds. 2022-01-18 15:53:48 +04:00
Alexander Shaduri 88e9e8c2f7 Implemented most build settings as constexpr functions and ported most of macro-based conditional compilation to if constexpr(); this significantly improves code quality and the chance of build success on different platforms and build configurations.
More code modernization.
2022-01-18 15:30:55 +04:00
Alexander Shaduri 235fba8a04 Convert relative smartctl-nc path to absolute before running it. 2022-01-15 15:24:11 +04:00
Alexander Shaduri 0183626c73 Change current path to gsmartcontrol directory before running smartctl - this should fix not being able to find "smartctl-nc" when CWD differs from gsmartcontrol installation directory, as it may happen when running gsmartcontrol from cmd. 2022-01-15 15:07:10 +04:00
Alexander Shaduri bcc36f260d Fixed finding data files in non-debug builds when running from build directory. 2022-01-15 15:01:39 +04:00
Alexander Shaduri ad796dad9e Automatically handle running from source/build directory and from package, using whereami library; this should fix not being able to run the application from non-standard build directories. 2022-01-15 14:35:06 +04:00
Alexander Shaduri 0ca482bc5d Include whereami library as a third-party dependency. 2022-01-15 14:33:12 +04:00
Alexander Shaduri c72b746d0a Escape all text wherever it may be interpreted as markup, even if not coming from external source. 2022-01-14 19:17:15 +04:00
Alexander Shaduri b4b6980a0c Fixed a GTK warning related to markup in Info window's attributes tab. 2022-01-14 18:53:16 +04:00
Alexander Shaduri 534dcd129e Code modernization and cleanups. 2022-01-14 15:06:07 +04:00
Alexander Shaduri 3e4cefb04f Fixed a crash when trying to render main window icons which have incomplete data; fixes #13 in main branch. 2022-01-12 18:04:42 +04:00
Alexander Shaduri dd392845a6 Fixed cmake build for the last commit. 2022-01-10 21:09:03 +04:00
Alexander Shaduri 7f2fb32735 Refactored InstanceManager (now WindowInstanceManager) to manage all window instances, keep them alive and have the ability to destroy them; this avoids any manual "delete" calls, and fixes a (newly introduced) crash on exit. 2022-01-10 19:13:11 +04:00
Alexander Shaduri f3247ec13b Merge remote-tracking branch 'origin/main' into main 2022-01-10 17:02:12 +04:00
Alexander Shaduri ad014517b9 Set LC_NUMERIC=C for smartctl process to avoid locale-dependent number formatting. 2022-01-10 17:01:56 +04:00
Alexander Shaduri e3de5aa3fe Merge pull request #21 from hjudt/fix-barely-readable-info-cell-texts
Device Information window: Fix barely readable table cell text on some systems
2021-12-21 18:03:12 +04:00
Harald Judt 6adac797d3 Fix barely readable info cell texts
By simply resetting values, the rendered cell text colors are barely
readable. Setting Pango::WEIGHT_NORMAL instead of resetting seems to fix this
nicely without any negative consequences.

Signed-off-by: Harald Judt <h.judt@gmx.at>
2021-12-21 14:25:06 +01:00
Alexander Shaduri 99c9d393c2 Merge pull request #15 from davoper/improvements
Add time to default filename in save dialog
2021-12-01 18:07:07 +04:00
dpc 17f54a8848 Add time (%H%M) to default filename in save dialog 2021-10-08 20:24:02 +02:00
Alexander Shaduri f9c5ad470c Merge pull request #11 from Translate-SW/patch-4
Update LINGUAS list
2021-08-11 18:32:23 +04:00
Alexander Shaduri da539e57a4 Merge pull request #12 from Translate-SW/patch-3
Czech translations for GSmartControl (cs.po)
2021-08-11 18:31:59 +04:00
CZ-Translator 37d86b2914 Update LINGUAS 2021-08-09 18:00:39 +02:00
CZ-Translator acc84385b5 Create cs.po 2021-08-09 17:59:07 +02:00
Alexander Shaduri 701ce81aab Merge pull request #5 from pinotree/legacy-pixmaps-location
Stop installing application icons to the legacy pixmaps location
2021-05-17 13:19:34 +04:00
Pino Toscano 71bcfe80e3 Stop installing app icon in pixmaps location
The /usr/share/pixmaps location is considered a legacy location for
application icons; since the application icons are already installed in
the global XDG hicolor theme, then simply stop installing the 48px one
in the legacy pixmaps location.
2021-05-16 17:57:52 +02:00
Pino Toscano b53bbe5a97 Drop the XPM version of the app icon
The application icon is already provided as PNG in different sizes, and
installed in the global XDG hicolor icon theme. Hence, the XPM version
of it can be dropped, as it is redundant.
2021-05-16 17:54:01 +02:00
Pino Toscano ccc9cd1a32 debian: drop old Debian menu file
Debian officially deprecated the old Debian menu system more than 5
years ago [1]. Hence, drop the old menu file, as not much of use
anymore.

[1] https://lists.debian.org/debian-devel-announce/2015/09/msg00000.html
2021-05-16 17:50:38 +02:00
Alexander Shaduri b78f8573b5 Implemented smartctl process environment changes without changing the main program's environment.
Removed ScopedEnv class - it's not thread-safe and very easy to misuse.
2021-04-21 16:48:46 +04:00
Alexander Shaduri 3b7576d95c Catch2: Treat catch2 headers as system. 2021-03-22 16:48:42 +04:00
Alexander Shaduri cdb9a4c603 Renamed SmartctlTextParser to SmartctlAtaTextParser. 2021-03-19 14:51:32 +04:00
Alexander Shaduri 9a2606d96f Disable compiler warnings when compiling third-party dependencies. 2021-03-19 14:50:08 +04:00
Alexander Shaduri b1ebc88a3c GitHub actions: Use msys2 shell when running tests in msys. 2021-03-19 14:49:18 +04:00
Alexander Shaduri a33d4109d1 Fix cross-compiling (test discovery doesn't work when cross-compiling). 2021-03-17 14:26:13 +04:00
Alexander Shaduri 15ab09063b Minor cleanups. 2021-03-17 14:25:30 +04:00
Alexander Shaduri 3f0b7c1681 Fixed catch2 compiling under mingw. 2021-03-17 14:24:52 +04:00
Alexander Shaduri b1150d8e86 Implemented app_pcre_get_options() tests. 2021-03-16 18:10:35 +04:00
Alexander Shaduri b84f3d9218 Register libdebug domains in test_all. 2021-03-16 18:10:19 +04:00
Alexander Shaduri 9db25f3907 Add Catch2 testing framework and integrate it into the build system and CI; moved json to subdirectory. 2021-03-16 17:57:01 +04:00
Alexander Shaduri 812bd2191e Fixed non-linux builds. 2021-03-16 16:27:06 +04:00
Alexander Shaduri 788a4760b8 Refactored storage property classes (better naming, documentation), removed app_gtkmm_features.h. 2021-03-16 16:06:28 +04:00
Alexander Shaduri d74da816a1 Refactored command executors (better naming, documentation). 2021-03-16 15:24:08 +04:00
Alexander Shaduri cfc11bef6e Refactored app_pcrecpp.h structure. 2021-03-15 19:00:50 +04:00
Alexander Shaduri bedd8f362b Refactored gtkmm utils and app builder to simply the code and document it better. 2021-03-15 17:55:22 +04:00
Alexander Shaduri 7855ce9dfb Fixed cmake warnings. 2021-03-15 16:40:25 +04:00
Alexander Shaduri 81d6656f13 Github actions: Add Linux binary package generation. 2021-03-12 18:36:59 +04:00
Alexander Shaduri 6fad220e7e Change version to 1.1.99. 2021-03-12 18:36:18 +04:00
Alexander Shaduri 2a0f32b2c7 Try to fix msys2 packaging. 2021-03-12 18:13:31 +04:00
Alexander Shaduri 212bdb80f8 Try to fix msys2 packaging. 2021-03-12 17:54:37 +04:00
Alexander Shaduri 6039667556 Try to fix msys2 packaging. 2021-03-12 16:25:00 +04:00
Alexander Shaduri 4960be8cd1 Try to fix msys2 packaging. 2021-03-12 16:03:16 +04:00
Alexander Shaduri 89b1a5a6bd Try to fix msys2 packaging. 2021-03-12 15:09:36 +04:00
Alexander Shaduri 173f379111 OBS Debian fixes. 2021-03-12 15:09:29 +04:00
Alexander Shaduri 14288cbd1a OBS Debian fixes. 2021-03-12 15:08:30 +04:00
Alexander Shaduri 4b72bd3824 Fixed compilation under Debian 10. 2021-03-12 10:58:31 +00:00
Alexander Shaduri 902e06b893 Try to fix msys2 packaging. 2021-03-12 14:48:19 +04:00
Alexander Shaduri ca9e83ce9b OBS fixes for Debian, SLE15. 2021-03-12 14:34:51 +04:00
Alexander Shaduri 58919f3dae Implement Windows zip and NSIS packaging in GitHub actions. 2021-03-12 14:34:25 +04:00
Alexander Shaduri b042e8ad19 Merge remote-tracking branch 'origin/main' into main 2021-03-12 14:33:13 +04:00
Alexander Shaduri b188fab4df Improved Windows packaging. 2021-03-12 14:09:10 +04:00
Alexander Shaduri 5f9801328f Merge remote-tracking branch 'origin/main' into main 2021-03-11 18:06:36 +04:00
Alexander Shaduri d7978e759d Support Windows zip and NSIS package generation in MSYS2. 2021-03-11 18:06:06 +04:00
Alexander Shaduri 2d83424510 Another fix for cmake 3.12. 2021-03-11 18:05:23 +04:00
Alexander Shaduri 78391d236b Support cmake 3.12. 2021-03-11 17:09:42 +04:00
Alexander Shaduri 7934433100 Make GitHub treat header files as C++. 2021-03-11 16:44:31 +04:00
Alexander Shaduri 692fb1c7ca Fixed "drive is testing" message on startup. 2021-03-10 14:28:22 +04:00
Alexander Shaduri a6fa512e46 Updated OBS rpm rules. 2021-03-10 14:14:35 +04:00
Alexander Shaduri 4809173feb Updated OBS rpm/debian rules. 2021-03-10 13:57:22 +04:00
Alexander Shaduri 2e49c6b7ed Support compilation under gcc 7. 2021-03-10 13:44:28 +04:00
Alexander Shaduri 72064d2324 Add naive deb package support (incomplete). 2021-03-10 13:31:22 +04:00
Alexander Shaduri ce309529c5 Update OBS rpm and deb builds (deb not really supported yet). 2021-03-10 13:13:19 +04:00
Alexander Shaduri cb1abab75f Support Finnish decimal separator (backported from Debian package). 2021-03-10 13:05:47 +04:00
Alexander Shaduri 9c97f463c9 Fixed a few typos (backported from debian package). 2021-03-10 13:05:21 +04:00
Alexander Shaduri c6d910ec21 GitHub actions: Moved macos to tier2 platform list. 2021-03-10 12:39:42 +04:00
Alexander Shaduri 9574a6df20 Fixed a warning from OBS. 2021-03-09 22:01:19 +04:00
Alexander Shaduri 39c57564a6 Fixed a warning in rpm SPEC file. 2021-03-09 22:00:42 +04:00
Alexander Shaduri c0686dd234 Fixed a typo in rpm spec file. 2021-03-09 21:33:15 +04:00
Alexander Shaduri 134633e7ac Updated RPM spec to support CentOS with EPEL. 2021-03-09 21:32:39 +04:00
Alexander Shaduri c1a1aca7ec GitHub actions: Add cpack test to Ubuntu build. 2021-03-09 21:12:18 +04:00
Alexander Shaduri 57f9605f70 Split github build actions into 2 tiers (tier 1 and 2 supported platforms); tier 1 platforms are build automatically, tier 2 are built on demand. 2021-03-09 21:11:54 +04:00
Alexander Shaduri 4a658d8f43 Require proper cmake version in spec file. 2021-03-09 21:10:43 +04:00
Alexander Shaduri e4e438b579 Fixed rpm spec file for opensuse. 2021-03-09 20:58:23 +04:00
Alexander Shaduri 3080aa7f87 Updated rpm spec file's build requirements. 2021-03-09 18:00:29 +04:00
Alexander Shaduri 3e19e3e5cb Updated rpm spec file to support cmake. 2021-03-09 17:57:46 +04:00
Alexander Shaduri 09e9e7d380 Fixed cmake install target, support cpack windows binary zip / NSIS, support package_source target; removed cpack RPM and DEB support. 2021-03-09 17:14:51 +04:00
Alexander Shaduri cbd45a27fb Removed autotools-related files from gitignore. 2021-03-09 17:12:08 +04:00
Alexander Shaduri b0b9c4169e Initial refactoring to support cpack-based packaging and OBS builds. 2021-03-09 15:17:25 +04:00
Alexander Shaduri 8d6b75057e GitHub action: Fix passing correct cmake flags in freebsd build. 2021-03-09 15:16:19 +04:00
Alexander Shaduri 1ddcbc224e Fixed compilation under FreeBSD and QNX. 2021-03-09 13:08:27 +04:00
Alexander Shaduri 8dd21e2b82 Re-enable freebsd in github workflow. 2021-03-09 12:18:28 +04:00
Alexander Shaduri 2de5360ac8 Updated github workflow. 2021-03-08 18:46:13 +04:00
Alexander Shaduri 28bc0fc826 Updated github workflow. 2021-03-08 18:36:14 +04:00
Alexander Shaduri 98b96cdeb2 Updated github workflow. 2021-03-08 18:06:30 +04:00
Alexander Shaduri 98798a3e57 Updated configure-dev script with cmake support. 2021-03-08 17:24:31 +04:00
Alexander Shaduri 4d04cd5089 Updated github workflow. 2021-03-08 17:16:59 +04:00
Alexander Shaduri 0b8c94bf6f Updated configure-dev script with cmake support. 2021-03-08 17:12:04 +04:00
Alexander Shaduri 2f900bf3a2 Updated github workflow. 2021-03-08 17:11:37 +04:00
Alexander Shaduri 71a34549ab Updated github workflow. 2021-03-08 17:00:35 +04:00
Alexander Shaduri a1c7855a63 Updated github workflow. 2021-03-08 16:53:16 +04:00
Alexander Shaduri d101a92750 Support old Glibmm only with libstdc++. 2021-03-08 16:51:42 +04:00
Alexander Shaduri fce77dc7d7 Fixed building under macosx. 2021-03-08 16:51:12 +04:00
Alexander Shaduri 14a7e26e09 Updated github workflow. 2021-03-08 16:38:37 +04:00
Alexander Shaduri 700ada0b5b Updated github workflow to include macos. 2021-03-08 16:06:16 +04:00
Alexander Shaduri 740b544615 Fixed syntax error in cmake.yml. 2021-03-08 15:58:14 +04:00
Alexander Shaduri ad64427126 Don't use $GITHUB_WORKSPACE in msys2 build. 2021-03-08 15:57:13 +04:00
Alexander Shaduri 4463726d51 Disabled freebsd build for now (it's broken), 2021-03-08 15:52:46 +04:00
Alexander Shaduri 95cb1abab8 Use matrix msystem for msys builds. 2021-03-08 14:55:04 +04:00
Alexander Shaduri 10af1ab1f2 Use msys shell for msys builds. 2021-03-08 14:45:51 +04:00
Alexander Shaduri 824827ff26 Added new experimental GitHub workflows for ubuntu, windows-msys2, freebsd. 2021-03-08 14:38:29 +04:00
Alexander Shaduri 60d9bf1922 Add separate toolchain with clang-tidy support. 2021-03-05 14:19:45 +04:00
Alexander Shaduri cb42040a8d Add .vs (VS with CMake support) to gitignore. 2021-03-05 14:19:26 +04:00
Alexander Shaduri d9d681db5e Refactored libdebug's bitset-related types. 2021-03-05 14:19:01 +04:00
Alexander Shaduri 1d5e8822e6 Fixed compilation under MSYS2. 2021-03-04 14:35:05 +04:00
Alexander Shaduri 53a3f73156 Modernized Windows code, fixed compiler warnings under mingw. 2021-03-03 19:40:02 +04:00
Alexander Shaduri 28dacf4d74 Fixed all remaining clang-tidy warnings. 2021-03-03 18:15:23 +04:00
Alexander Shaduri 2859666708 Make all examples use main_tools.h exception wrapper. 2021-03-03 18:15:05 +04:00
Alexander Shaduri f861918789 Fixed compilation error in hz/main_tools.h. 2021-03-03 17:40:46 +04:00
Alexander Shaduri 8e2cf08be1 Cleaned up libdebug for clang-tidy warnings. 2021-03-03 17:40:21 +04:00
Alexander Shaduri 4f6f0ce9f6 Minor cleanup. 2021-03-03 16:54:59 +04:00
Alexander Shaduri 3032bbc4e7 Added new hz/main_tools.h header to cmake. 2021-03-03 16:54:37 +04:00
Alexander Shaduri 6f1dd37818 Fixed a few clang-tidy warnings in hz. 2021-03-03 16:54:16 +04:00
Alexander Shaduri f8369fe436 Fixed a few clang-tidy warnings in libdebug. 2021-03-03 16:53:50 +04:00
Alexander Shaduri ff3b07a086 Fixed a few clang-tidy warnings in applib. 2021-03-03 16:53:22 +04:00
Alexander Shaduri e329946213 Ported some main() functions to new main_tools. 2021-03-03 16:43:04 +04:00
Alexander Shaduri 5572421eca New hz::main_tools component to handle exceptions in main(). 2021-03-03 16:42:26 +04:00
Alexander Shaduri ef0803cb4d Redirect github page to old sourceforge page for now. 2021-03-03 12:22:21 +04:00
Alexander Shaduri 60ba6078c2 Fixed some problems reported by clang-tidy. 2021-03-02 19:12:18 +04:00
Alexander Shaduri 8d66596995 New .clang-tidy configuration to catch code problems. 2021-03-02 19:11:56 +04:00
Alexander Shaduri 07b6a27dc0 Fixed libintl conflicts causing compilation errors in Windows. 2021-03-02 18:25:16 +04:00
Alexander Shaduri 6e93516a4b Fixed copying .ico file in Windows. 2021-03-02 18:24:19 +04:00
Alexander Shaduri 5ce4a3aeb8 Implement toolchain support for cross-compilation and development. 2021-03-02 18:23:49 +04:00
Alexander Shaduri 2e3d8e72b6 Fixed a memory leak in utf8-to-utf16 conversion and a gcc warning. 2021-03-02 18:22:46 +04:00
Alexander Shaduri 0be08399a0 Fixed Win32 compiler errors related to paths. 2021-03-02 18:21:55 +04:00
Alexander Shaduri 0cd5202e74 Hide binary symbols by default. 2021-03-02 18:20:13 +04:00
Alexander Shaduri 1479256575 Update "JSON for Modern C++" to version 3.9.1. 2021-03-02 18:19:42 +04:00
Alexander Shaduri 306fbd503b Write debian and rpm scripts to "data" directory, not build directory. 2021-03-02 18:19:12 +04:00
Alexander Shaduri a5aff22d34 Link Win32 manifest into the gsmartcontrol binary. 2021-03-02 16:44:50 +04:00
Alexander Shaduri 3a8d75fbf0 Link Win32 manifest into the gsmartcontrol binary. 2021-03-02 16:44:23 +04:00
Alexander Shaduri 1d0762e756 Disable format-security warnings in Clang. 2021-03-02 16:43:25 +04:00
Alexander Shaduri d017f425d0 Use "example_" prefix instead of "_example" suffix for example sources and binaries. 2021-03-02 16:42:24 +04:00
Alexander Shaduri 56dec521c5 Updated Doxyfile with latest doxygen template. 2021-03-01 23:19:14 +04:00
Alexander Shaduri fdce91471e Fixed clang warning. 2021-03-01 22:45:19 +04:00
Alexander Shaduri 2986bb4893 Ported hz::scoped_ptr to std::unique_ptr and removed it. 2021-03-01 22:43:22 +04:00
Alexander Shaduri 8f82cd5c8a Removed unnecessary line in github action. 2021-03-01 22:42:49 +04:00
Alexander Shaduri 11bbbe1155 Removed TODO file. 2021-03-01 18:12:23 +04:00
Alexander Shaduri 80cc4c9515 Disable glibmm throw(...) workaround with newer glibmm. 2021-03-01 16:47:02 +04:00
Alexander Shaduri c6f506781b Make flags size_t. 2021-03-01 16:26:51 +04:00
Alexander Shaduri be22e3b999 Re-enable checkout action. 2021-03-01 16:26:34 +04:00
Alexander Shaduri 8cc7fb1e17 Disable compiler warnings unless explicitly enabled, to avoid compilation failures on older systems without specific warning flags. 2021-03-01 16:21:42 +04:00
Alexander Shaduri 28c86de4c9 Fixed compiler warning in libdebug. 2021-03-01 16:20:54 +04:00
Alexander Shaduri dac585c01b Fixed building examples. 2021-03-01 16:20:40 +04:00
Alexander Shaduri 357207c6a8 Added gettext as debian package dependency. 2021-03-01 16:20:21 +04:00
Alexander Shaduri 4e1db889c0 Disable github checkout action, it's unnecessary. 2021-03-01 16:19:59 +04:00
Alexander Shaduri 8d4f4d26f7 Added Ubuntu dependencies. 2021-03-01 15:19:59 +04:00
Alexander Shaduri 6e4766149f Fixed github action matrix. 2021-03-01 15:08:22 +04:00
Alexander Shaduri d4bc3f01bf Added github action (Ubuntu). 2021-03-01 15:04:52 +04:00
Alexander Shaduri d5785606a0 Updated homepage URLs and some copyright notices. 2021-03-01 14:53:00 +04:00
Alexander Shaduri d760a3d0f2 Map gtk log levels to libdebug log levels. 2021-03-01 14:44:30 +04:00
Alexander Shaduri b013cbd65c Updated copyright notices in .glade files. 2021-03-01 14:04:46 +04:00
Alexander Shaduri 698500fd3e Refactored the build config header and macros; Added OS- and compiler-specific options and macros to cmake. 2021-03-01 14:04:35 +04:00
Alexander Shaduri f0dfeaf8c0 Updated / added copyright headers. 2021-02-26 14:36:27 +04:00
Alexander Shaduri fed79c7de0 Updated .in files to use cmake variables. 2021-02-26 14:01:09 +04:00
Alexander Shaduri 8eaef139e9 Merge remote-tracking branch 'origin/master' 2021-02-24 17:58:02 +04:00
Alexander Shaduri c6ebf9feb1 Initial version of complete port to cmake; removed all autotools files. 2021-02-24 17:57:51 +04:00
Alexander Shaduri 9ec1e52b5a Create CNAME 2021-02-23 20:37:50 +04:00
Alexander Shaduri d0db433bc8 Added sample github pages. 2021-02-23 20:33:46 +04:00
Alexander Shaduri b7be12c7aa Removed old IDE files. 2021-02-23 20:33:28 +04:00
Alexander Shaduri 7b1217100b Updated license files and some file license headers. 2021-02-23 20:33:17 +04:00
Alexander Shaduri b24e0ef6f2 Moved files out of doc directory and updated them. 2021-02-23 20:32:40 +04:00
Alexander Shaduri dc6bd27d22 Added .gitignore, removed SVN ignore files. 2021-02-23 20:29:29 +04:00
Alexander Shaduri 0f6ff2a4cb Moved files out of gsmartcontrol directory after import from SVN. 2021-02-23 20:24:01 +04:00
Alexander Shaduri 7075a4f4d5 More work on cmake support. 2021-02-23 11:54:56 +00:00
Alexander Shaduri f4ed97d5ea Fixed a crash when system locale is set to invalid locale. 2021-01-05 12:25:21 +00:00
Alexander Shaduri 6d3a097f20 Started marking texts as translatable.
Fixed a few minor bugs.
2019-07-23 10:45:17 +00:00
Alexander Shaduri 5265ebb939 Implemented gettext integration.
Marked all window texts for translation (library texts still to go).
Switched glade files to use gtk 3.20, added copyright information.
2018-02-05 17:52:41 +00:00
Alexander Shaduri 9e783a5afc Drive settings are now serialized to config as json objects.
Removed bin2ascii_encoder.
2018-02-02 20:21:35 +00:00
Alexander Shaduri 0feb3b4aaa Data files are no longer compiled-in, but loaded at runtime.
Moved licenses and other documentation to "docs".
Simplified some GtkBuilder code.
2018-02-01 22:26:31 +00:00
Alexander Shaduri 6c624de79c Ported all filesystem code to C++17 std::filesystem.
Removed hz/fs_*.
Added new hz/fs.h and hz/fs_ns.h files with some filesystem utility functions.
Removed hz/string_wcmatch.h, it's no longer needed.
Removed hz/i18n.h, it never worked.
2018-01-31 20:17:03 +00:00
Alexander Shaduri b48bd99f70 More C++17 modernization. 2018-01-27 21:09:14 +00:00
Alexander Shaduri cbd0d94d90 Removed some autoconf checks, they're detected using macros now.
Use config.h only for CONFIG_* macros; for everything else - define them on
the command-line, or detect using feature checks.
Removed hz_config.h - moved all of its checks to respective files.
More C++17 modernization.
Split GscInfoWindow::fill_ui_with_info() into tab-specific functions.
2018-01-27 20:44:55 +00:00
Alexander Shaduri ee3adb70d4 Info window: Fixed attribute values not being rendered properly.
Fixed examples.
2018-01-15 21:16:53 +00:00
Alexander Shaduri d8af6a9af1 Got rid of intrusive_ptr. 2018-01-15 20:11:55 +00:00
Alexander Shaduri e20b4326a8 switch on type -> static map. 2018-01-15 17:28:04 +00:00
Alexander Shaduri 77e0278f93 enum -> enum class where applicable. 2018-01-15 16:55:03 +00:00
Alexander Shaduri 32623afb9b Use std::variant in StorageProperty. 2018-01-15 15:00:46 +00:00
Alexander Shaduri e83abacffd Ported to std::chrono.
Fixed lots of build warnings.
2018-01-14 21:39:55 +00:00
Alexander Shaduri 52eb101aeb GSmartControl is GPL3 only now.
Updated copyrights to 2018.
2018-01-13 20:31:43 +00:00
Alexander Shaduri 59b3a8a8e4 Don't use picojson (it has problems), use Lohmann's JSON for Modern C++. 2018-01-13 20:09:04 +00:00
Alexander Shaduri f87003b192 Removed rmn.
Added picojson.
Ported rconfig to picojson.
Ported rconfig's "/runtime" to GscStartupSettings.
2018-01-12 21:16:36 +00:00
Alexander Shaduri 89fb954223 Removed errno_string. 2018-01-05 21:30:13 +00:00
Alexander Shaduri ecea03b271 Fixed string_num.
Renamed tests to examples.
2018-01-02 19:47:15 +00:00
Alexander Shaduri f127fb9afd Further porting to C++17 (string_num, ...). 2018-01-01 22:58:42 +00:00
Alexander Shaduri c77d23be7a Moar porting. 2018-01-01 00:29:24 +00:00
Alexander Shaduri 72343e1067 Futher porting to C++17. 2017-12-31 23:09:29 +00:00
Alexander Shaduri 0902345808 Removed all thread stuff. 2017-12-31 16:56:17 +00:00
Alexander Shaduri 2ae1a561d7 Further removal of old code and porting to C++17. 2017-12-30 22:52:39 +00:00
Alexander Shaduri d4c06f61d6 Ported from hz::any_type to std::any. 2017-12-30 21:35:28 +00:00
Alexander Shaduri 02cfa33907 First round of porting to C++17 and removing old code. 2017-12-30 20:27:07 +00:00
Alexander Shaduri 6e8628b1df Fixed gsmartcontrol-root not launching if no GDK_* variables are set.
Increased version to 1.1.3.
2017-11-12 09:55:27 +00:00
Alexander Shaduri 2b19afe66d Fixed not picking up GDK_DPI_SCALE=-1 by command-line. 2017-11-11 20:49:09 +00:00
Alexander Shaduri 7236841d64 Fixed compilation under gcc 4.7. 2017-11-11 19:10:11 +00:00
Alexander Shaduri 49fb65ce71 Updated NEWS file. 2017-11-11 18:52:51 +00:00
Alexander Shaduri ad87baee70 Windows: Show volume names beside drives letters in tooltips. 2017-11-11 18:19:57 +00:00
Alexander Shaduri 5e8fef98ec Fixed compilation with gtkmm < 3.10 and gcc 4.7. 2017-11-11 11:32:19 +00:00
Alexander Shaduri 83baafa615 Force C++11 mode since gtkmm3 requires it, but fails to enable it on Centos7. 2017-11-11 10:44:49 +00:00
Alexander Shaduri 9f39db9517 Tweak default window size. 2017-10-06 10:26:43 +00:00
Alexander Shaduri 19f2bcf286 Fixed a crash when icon theme doesn't contain a specified icon. 2017-10-05 20:14:23 +00:00
Alexander Shaduri 02e8876acc Bumped version to 1.1.2. 2017-10-05 19:55:56 +00:00
Alexander Shaduri 4f78e3dd90 Removed unused function. 2017-10-04 21:10:34 +00:00
Alexander Shaduri 6888d0862d Increased iconview icon size to 64.
Increased iconview icon widths to correspond to 2 icons per row for default window size; the text
will less likely get wrapped in this case.
Changed bundled icons to size 64.
Fixed iconview icon blurriness with GDK_SCALE=2.
Use XDG-style icon names, as per GTK >= 3.10; fallback to old names and bundled icons if needed.
Removed all mention of .glade files from comments; don't use non-standard gnome names anymore.
Don't show empty "()" for drive letters in Linux.
Show "not mounted" for drive letters when no drive letters are present.
Added new "--gdk-scale" and "--gdk-dpi-scale" parameters, since pkexec discards user environment;
pass $GDK_SCALE and $GDK_DPI_SCALE to these from gsmartcontrol-root.
2017-10-04 21:09:32 +00:00
Alexander Shaduri a95be84eac Fixed make dist. 2017-09-25 15:00:50 +00:00
Alexander Shaduri b76b5f2227 Removed Help window.
Moved most of the documentation to website.
The Help menu items now open the website pages.
2017-09-25 14:58:58 +00:00
Alexander Shaduri 7a12c0880f Don't package gtkrc in Windows (it's unused).
Added French translations to desktop file.
2017-09-23 17:14:45 +00:00
Alexander Shaduri 58b0b1fab2 Windows: Changed GTK+ theme changing to use gtkmm functions.
Added some special cases to SCT parser.
2017-09-23 16:06:09 +00:00
Alexander Shaduri 16b5c322d5 Bumped version to 1.1.1.
Windows: Default to Adwaita theme for Windows 7 and Windows Server, since
"Classic" theme is broken in GTK+3 with win32 theme.
Format Statistics entry values with commas for readability.
2017-09-15 12:26:45 +00:00
Alexander Shaduri 16d5b82ac8 Fixed compilation under C++98.
Fixed smartmontools URLs.
2017-09-07 13:51:26 +00:00
Alexander Shaduri be66a8749c Bumped version to 1.1.0.
Updated NEWS file.
Clarified a message for self-test log entry count.
2017-09-07 12:43:38 +00:00
Alexander Shaduri 5192a9d447 Implemented ability to copy rows from Attribute, Statistics and Self-Test Log
tables.
2017-09-06 20:11:39 +00:00
Alexander Shaduri b9160ec173 Improved parser so that all the "-x" test data is parsed. 2017-09-05 20:53:19 +00:00
Alexander Shaduri 675fad3fc1 Documented RAID support. 2017-09-05 17:27:31 +00:00
Alexander Shaduri f7c01d6c7b Implemented "Update Drive Database" item in main window menu. 2017-09-05 16:12:19 +00:00
Alexander Shaduri 5bc6318dcd Implemented parsing of "==> Warning" in Info section. 2017-09-05 15:45:21 +00:00
Alexander Shaduri 3d8b0c94df Allow loading multiple virtual drives from one Open dialog. 2017-09-05 15:14:02 +00:00
Alexander Shaduri 73fec7fa3f Rate individual error log entries for error severity. 2017-09-05 14:53:47 +00:00
Alexander Shaduri 22971e8567 Show scan time on virtual drive icons.
Show windows drive letters if "device name under icon" is enabled.
2017-09-04 18:52:41 +00:00
Alexander Shaduri 3df4cdae56 Implemented devstat warnings. 2017-09-04 18:12:27 +00:00
Alexander Shaduri 062096a0b4 Improve GtkNotebook appearances in Windows.
Don't show Info window tabs if only one tab is present.
2017-09-04 16:57:08 +00:00
Alexander Shaduri 978e7d41b7 Added filters to file chooser dialogs.
Add .txt when saving files if it's not present (fixes a Windows bug when the
default drive name is cleared by typing something else).
2017-09-04 14:38:10 +00:00
Alexander Shaduri 33028f81d9 Fixed a few parser issues.
SCT temperature overrides all others now.
2017-09-04 13:43:40 +00:00
Alexander Shaduri 4cb12c5e0c Show temperature (from sct, devstat, or attributes) in Temperature Log tab,
including warnings.
Don't warn if SCT is unsupported.
2017-09-01 19:21:15 +00:00
Alexander Shaduri b01acfeef3 Added entry descriptions to Statistics table. 2017-09-01 17:53:09 +00:00
Alexander Shaduri b7676aaba8 Added Page,Offset column to Statistics.
Enabled multiple selection in treeviews.
Renamed ERC tab to Error Recovery.
2017-09-01 14:20:34 +00:00
Alexander Shaduri e0a13c6867 Implemented parsing of devstat section.
Implemented Statistics tab.
Increased borders in some tabs.
Some code style changes.
2017-09-01 13:42:51 +00:00
Alexander Shaduri 9f5db6d034 Visual improvements in Error Log tab. 2017-08-31 20:50:41 +00:00
Alexander Shaduri 5c3bfe8db0 Fixed not detecting the number of errors in extended error log. 2017-08-31 20:44:00 +00:00
Alexander Shaduri 5926e43bc5 Refactored Info Window tabs (again).
Implemented support for Temperature Log, ERC, Physical, Directory tabs.
Added detection of a few "not supported" messages.
Added some more --get=all output lines.
Smartctl invocation now corresponds to -x, and -x output can be loaded as
a virtual drive (parsed fully except for devstat).
2017-08-31 20:03:04 +00:00
Alexander Shaduri f21f076386 Refactored Info window UI (added tabs for various logs).
Hid annoying gcc warning.
2017-08-29 19:06:46 +00:00
Alexander Shaduri da403b28c9 Require smartmontools version 5.43 at runtime. 2017-08-29 15:13:13 +00:00
Alexander Shaduri faba9270a0 Use --format=brief attribute format by default.
Removed "Updated" column from attributes; advanced users can look at flags to
get that information.
2017-08-29 13:41:38 +00:00
Alexander Shaduri 9ca87eb296 Use -l xerror,error and -l xselftest,selftest by default.
Implemented parsing of xerror, xselftest sections.
2017-08-29 13:26:25 +00:00
Alexander Shaduri b2b97f2c9a Added more info output detection (APM feature is...).
Enable -v by default on Windows (makes debugging easier).
2017-08-29 11:47:14 +00:00
Alexander Shaduri 8494880943 Fixes in spec file.
Fixes with polkit's pkexec invocation.
2017-08-28 12:29:54 +00:00
Alexander Shaduri 0f8f38f0e1 Fixed compilation. 2017-08-28 10:12:39 +00:00
Alexander Shaduri 8544163c46 Make sure we bundle the polkit file on make dist. 2017-08-28 09:59:42 +00:00
Alexander Shaduri fdcd190592 Added --get=all information to General section.
Made General section scrollable
Changed all smartctl invocation parameters to full versions (very old smartctl
versions didn't support these, but we can drop their support from now on).
2017-08-27 20:00:43 +00:00
Alexander Shaduri 40e08796d1 Use pkexec --disable-internal-agent for polkit.
Don't warn on Unknown property "Form Factor".
2017-08-27 19:07:52 +00:00
Alexander Shaduri 1e72729056 Implemented PolKit support.
Install gsmartcontrol binary to /usr/sbin.
Removed Fedora consolehelper support from spec file (in favor of PolKit).
2017-08-27 17:33:09 +00:00
Alexander Shaduri 731122e891 Bumped version number to 1.0.3. 2017-08-26 17:23:43 +00:00
Alexander Shaduri ebb3ab6017 Removed local copy of pcrecpp, always use system-installed one (it's not a
rarity anymore).
2017-08-26 17:23:14 +00:00
Alexander Shaduri 3d2fe7fd50 Windows: Show drive letters for each device. 2017-08-26 16:47:11 +00:00
Alexander Shaduri 9a70345f4a Format large numbers according to locale (usually with commas).
Save Open/Save paths across windows and program restarts.
2017-08-26 13:18:32 +00:00
Alexander Shaduri 897a4efa96 Save / load default window size and position (both for main window, size only
for info window).
2017-08-26 12:09:51 +00:00
Alexander Shaduri 6ab53c5436 Updated site URLs to https://gsmartcontrol.sourceforge.io/ . 2017-08-18 09:33:55 +00:00
Alexander Shaduri 6b5110e0b9 Updated NEWS file. 2017-07-21 10:08:04 +00:00
Alexander Shaduri 687c0bfe08 Fixed being able to turn on AODC even if unsupported. 2017-07-20 19:15:22 +00:00
Alexander Shaduri 48b069fef4 Added missing icon dialog-information under Windows.
Don't use gtk-stock icons (they're deprecated).
2017-07-19 14:41:12 +00:00
Alexander Shaduri ab48307235 Bump version to 1.0.2.
Bundle missing icons during make-win-dist so that the sorting
indicators are displayed properly.
2017-07-19 14:09:34 +00:00
Alexander Shaduri 93c43d8612 Make sure we capture the full output of smartctl under Windows. 2017-07-19 13:53:06 +00:00
Alexander Shaduri bf9889cb0c Fixed compilation under macOS.
Fixed compilation under Fedora Rawhide.
Don't use -mtune=generic for all targets.
Don't use common compiler options by default.
2017-06-19 14:29:12 +00:00
Alexander Shaduri 6e7d67aa61 Updated news file for 1.0.0. 2017-06-16 16:55:58 +00:00
Alexander Shaduri 16f60c678b Fixed build under older gtk3. 2017-06-16 10:49:59 +00:00
Alexander Shaduri 1b8f7bd886 About dialog: Fixed mailto: links not working under Windows. 2017-06-16 10:26:21 +00:00
Alexander Shaduri 31278654a0 Fixed Help menu items not scolling to right locations. 2017-06-16 10:01:45 +00:00
Alexander Shaduri 80e87d7868 Tweaked default window sizes. 2017-06-16 09:58:13 +00:00
Alexander Shaduri e21ccb9671 Fixed NSIS installer issues. 2017-06-15 21:09:27 +00:00
Alexander Shaduri e6cdcc9ee2 Fixed win64 zip packaging. 2017-06-15 20:07:23 +00:00
Alexander Shaduri 4a579b5141 Fixed "Use system-installed smartctl" not working with newer smartmontools. 2017-06-15 19:54:11 +00:00
Alexander Shaduri dc166364de Implemented native file chooser dialogs (Windows). 2017-06-15 19:37:09 +00:00
Alexander Shaduri 4564fd2948 Disable client-side window decorations under Windows. 2017-06-15 18:16:00 +00:00
Alexander Shaduri c591823c3e Disable dpi-aware for now; it has some artifacts (titlebar, checkboxes, font
size) under 250%.
Make main window a bit larger.
2017-06-15 12:34:38 +00:00
Alexander Shaduri 7a1904c1ef Get rid of "More", make its children direct parts of the GUI. 2017-06-14 21:53:16 +00:00
Alexander Shaduri 5c5466d6b2 Fixed "More" button to show horizontal layout.
Fixed win-dist target not picking up glib-2.0 schemas and Adwaita icons.
2017-06-14 21:30:05 +00:00
Alexander Shaduri 6aaf467950 Don't require library packages in spec - they are auto-computed by OBS. 2017-05-19 21:24:39 +00:00
Alexander Shaduri 428abcb3e7 Fixed syntax error in spec file. 2017-05-19 21:13:01 +00:00
Alexander Shaduri 9dea31e3d7 Don't generate tar.gz distribution files.
Compatibility with gtk3 <= 3.8.
Updated spec file to avoid errors on Fedora.
2017-05-19 21:10:39 +00:00
Alexander Shaduri 154b609576 Removed logo from About dialog (it wasn't working).
Changed back to Windows 2000 compatibility - apparently gtk3 in cross/mingw supports XP.
Updated svn ignore flags for new autotools-generated files.
Updated debian and spec files to reflect new gtk3 requirements.
Enabled dpiAware flag for Windows - gtk3 should support it properly.
Rewrote win32/win64 packaging to pick proper files (including gtk3).
Removed nogtk distribution generation code (it doesn't make sense without gtk installer).
Changed configure-dev to support msys- and cross-based mingw (win32 and win64).
2017-05-19 20:33:43 +00:00
Alexander Shaduri 7bfb502aa0 Added msys configuration to configure-dev. 2017-05-19 16:16:05 +00:00
Alexander Shaduri ded7d3bc86 Properly expand menubar. 2017-05-18 16:42:34 +00:00
Alexander Shaduri 526c1f6a69 Make sure menubar is expanded horizontally. 2017-05-18 16:35:03 +00:00
Alexander Shaduri 6fd501d553 Fixed launching URLs in About dialog under Windows. 2017-05-18 15:57:39 +00:00
Alexander Shaduri 11aa08354e Fixed an error in process_signa.h (win32). 2017-05-18 15:44:31 +00:00
Alexander Shaduri 0bfbebeb8b Avoid unhandled exception Gtk::IconThemeError. 2017-05-18 15:35:14 +00:00
Alexander Shaduri 413ba1c1a9 Fixed autogen warnings about AR. 2017-05-18 15:34:23 +00:00
Alexander Shaduri fdec3e8151 Fixed "empty iconview" text displaying.
Disabled no-deprecation flags to avoid future incompatibilities.
Info window: Renamed "Identity" tab to "General".
2017-05-17 18:28:49 +00:00
Alexander Shaduri 0012f831a8 Fixed a crash on exit. 2017-05-17 17:35:48 +00:00
Alexander Shaduri c8962a4e67 Fix Info Identity tab to look like the gtk2 version. 2017-05-17 17:10:57 +00:00
Alexander Shaduri 74d09cf879 Initial (incomplete) port to GTK 3.4. 2017-05-17 16:49:20 +00:00
Alexander Shaduri afdb516386 Updated copyright years. 2017-05-11 08:42:23 +00:00
Alexander Shaduri 9a1f28fe9a Fixed some win32 installer issues. 2017-05-10 21:26:56 +00:00
Alexander Shaduri b4583a7cc6 Bumped version to 0.9.0. 2017-05-10 20:08:20 +00:00
Alexander Shaduri 9918b13214 Updated drive descriptions to drivedb.h r4430, 2017-05-03.
Fixed selective self-test section parsing (if it's unsupported).
2017-05-10 20:06:44 +00:00
Alexander Shaduri 3f9d830294 Added appdata metainfo file. 2017-05-08 17:54:25 +00:00
Alexander Shaduri 7b2627b236 Clear the drives and show "please rescan" message after the preferences are
updated; this ensures that no old settings are used.
2017-05-08 17:16:27 +00:00
Alexander Shaduri c40d87b3ae Require gtk2 2.6.0 until we move to 2.24.0.
Win32 drive detection: stop scanning only after 3 not-found drives, so that
we detect drives after old removed drives.
2017-05-08 16:47:52 +00:00
Alexander Shaduri 99f707b6c6 Require gtk2 2.24.0, for future compatibility with gtk3. 2017-05-08 10:51:27 +00:00
Alexander Shaduri a561d5fef6 Changed the license field in spec file to conform to OBS requirements. 2016-06-04 16:14:12 +00:00
Alexander Shaduri 1d305e7626 Fixed time formatting with VS. 2015-07-01 12:10:23 +00:00
Alexander Shaduri 194fb51f75 Disable dpiAware flag in win32 manifest since it's not supported that well. 2014-05-29 18:00:49 +00:00
Alexander Shaduri e2dc39bff2 Don't show the info window if there's nothing to show. 2014-05-05 10:37:24 +00:00
Alexander Shaduri 836aa73430 Avoid scientific notation when displaying the drive size. 2014-05-05 10:16:38 +00:00
Alexander Shaduri 63f5b885a3 Fixed glib 2.32 warnings. 2014-05-05 09:36:10 +00:00
Alexander Shaduri c68d017475 Updated to latest libhz. 2014-05-05 09:20:18 +00:00
Alexander Shaduri bbe3bac923 Make sure we write some data from the Info window on Save Output if only basic
data is available.
Fixed a harmless "Number of written bytes doesn't match the data size" warning.
Added support for SSD-only and HDD-only vendor attributes.
Added the latest (r3897 / 2014-04-28) attributes from smartmontools.
Increased the Info window size a bit.
2014-05-05 08:59:13 +00:00
Alexander Shaduri 2293e357f4 Increased main window size a bit to avoid the iconview shift down each time an
icon is selected.
Added some scsi-output properties to full parser to avoid console warnings.
Devices having only basic info can be displayed now in the info window.
2014-04-30 10:38:48 +00:00
Alexander Shaduri 85dbceb14d Fixed a crash at scan time (bad parsing of empty smartctl output sections).
Updated program descriptions to include SSD.
2014-04-16 20:04:04 +00:00
Alexander Shaduri 45cba39be7 RAID volumes which report having SMART are now detected and explicitly set to
not having SMART.
2013-10-17 10:26:53 +00:00
Alexander Shaduri a0b235dd8a Increased timeouts when executing commands before the "Cancel" dialog is
shown; this helps with constant focus stealing from other windows when
smartctl is too slow (usually under Windows).
2013-02-25 20:27:18 +00:00
Alexander Shaduri 7e3db9ec30 Implemented detection for some new "not supported" smartctl messages. 2013-02-24 20:07:51 +00:00
Alexander Shaduri 6cc8770599 Implemented Linux support for Areca controllers with enclosures (untested).
Implemented Windows support for Areca controllers (thanks to Richard Kagerer);
untested so far.
2013-02-24 20:02:30 +00:00
Alexander Shaduri 462d465f3a Modified all glade files to use gtk 2.8 compatibility (not sure if it works).
Removed "tooltip_text" properties from all glade files, "tooltip" should be
enough.
Set the "activates_default" property on all relevant entries in glade files;
this will make the Enter key activate the default dialog action when these
entries are focused.
Added some clarifying text to Add Device dialog.
Clarified the per-drive parameters section (what it does) in Preferences.
Added a confirmation dialog in case the user doesn't set the Parameters field
in one of the Per-Drive Parameters entries.
Added a "Smartctl Options" section to README/Help.
Clarified the difference between smartctl.exe and smartctl-nc.exe in a
tooltip.
Improved some other tooltips.
2013-02-11 11:09:00 +00:00
Alexander Shaduri 6ac62cd0de Device detection is a lot more verbose now.
The read /proc files are now cached to avoid needless re-reading.
Some other minor changes.
2013-02-10 20:55:58 +00:00
Alexander Shaduri 1174b62b8f Bumped version number to 0.8.8. 2012-12-23 19:27:47 +00:00
Alexander Shaduri ef713900a0 Implemented support for HP controllers behind cciss and hpsa/hpahcisr drivers. 2012-12-23 19:25:20 +00:00
Alexander Shaduri c60f6815fa Fixed BDRW drive detection (it was detected as a HDD).
Added support for recent smartctl -i changes.
2012-09-28 08:52:10 +00:00
Alexander Shaduri 7ca709fcbb Fixed a comment. 2012-08-11 14:24:58 +00:00
Alexander Shaduri c3ce878376 Don't require libglademm in debian control file, it confuses newer Ubuntus. 2012-08-11 14:19:58 +00:00
Alexander Shaduri a06ac42eff Don't limit Fedora versions. 2012-08-11 13:30:55 +00:00
Alexander Shaduri 444eb6c211 Fixed spec file problems with Fedora.
Updated NEWS file.
2012-08-11 11:43:39 +00:00
Alexander Shaduri eb6cbe1ee0 Fixed make dist error. 2012-08-10 16:47:11 +00:00
Alexander Shaduri bcae9a2c37 Increased application version to 0.8.7.
Added Fedora consolehelper support to the spec file.
2012-08-10 16:33:29 +00:00
Alexander Shaduri d411b34dae Updated smartctl attributes from r3515 to r3587.
Added warnings for SSD lifetime attributes.
2012-08-10 15:49:28 +00:00
Alexander Shaduri a0fad4375a Added options to show device name and serial number under drive icons.
Added serial number to drive icon tooltip.
Fixed compiler error introduced in previous revision.
Removed some useless tooltips from UI.
2012-08-10 09:44:06 +00:00
Alexander Shaduri ffb02984fe Documented the rest of the code (rconfig, rmn, libdebug).
Fixed up the doxygen documentation, should be in usable state now.
2012-08-08 17:33:26 +00:00
Alexander Shaduri b400df2565 Completely documented hz, gsc and applib.
Fixed some compiler warnings.
Removed some unused files.
Added hz/initialized.h as part of hz.
2012-08-05 20:18:22 +00:00
Alexander Shaduri b06607cc37 Added a missing #include statement that caused build errors on SLES SP2.
Updated .spec and .desktop file to fix some warnings.
2012-04-28 15:17:44 +00:00
Alexander Shaduri 8881f42470 Fixed the detection of 3ware 9750 (twl) devices.
Implemented support for systems with several different 3ware controllers
(twa/twe/twl).
2012-03-12 20:06:33 +00:00
Alexander Shaduri 6558d31680 Support Areca RAID controller detection under Linux (untested).
Support 3ware 3w-sas-supported RAID controller detection under Linux (untested).
2012-03-03 18:03:15 +00:00
Alexander Shaduri 6e949677ec Don't open \\.\PhysicalDriveN needlessly if it was filtered out by --scan-open. 2012-02-26 19:19:34 +00:00
Alexander Shaduri 72f2d166b6 Updated the man page to reflect the new gsmartcontrol-root syntax.
The previous commit also contained the following changes:
The gsmartcontrol-root wrapper script now properly escapes the arguments
before passing them to gsmartcontrol.
gsmartcontrol-root has a new argument "--desktop=..." which replaces the old
positional argument; compatibility with the old invokation syntax has been
retained.
2012-02-19 15:09:26 +00:00
Alexander Shaduri 7b13cdf7b3 GSmartControl now prints an error message and a help text if an invalid
command-line options was specified.
2012-02-19 15:04:47 +00:00
Alexander Shaduri c7bdaad30a Fixed invalid parsing of tw_cli output which caused non-detection of drives
and controllers with controller or port numbers greater than 9 (3ware linux,
windows).
The same-brand controllers with identical SCSI host numbers are collapsed into
one controller now (the others are for LUNs and only pollute the drive list).
The drives are sorted during detection, not when adding them to the GUI.
The drive sorting algorithm has been slightly changed.
2012-02-19 13:10:05 +00:00
Alexander Shaduri fd9fce25fc Implemented support for Adaptec RAID 5805 controller and possibly other
Adaptec models as well.
2012-02-19 10:28:52 +00:00
Alexander Shaduri 5ba7add5b5 Fixed a few VS /analyze warnings in win32_tools.h. 2012-01-16 16:28:52 +00:00
Alexander Shaduri 68889d3804 Updated copyright headers for year 2012.
Updated the command line option descriptions in the man page and README.txt.
2012-01-11 17:26:34 +00:00
Alexander Shaduri 8ab18d433a The manifest now indicates that GSmartControl is dpi-aware (no more blurring
in high-dpi situations under Windows).
2012-01-09 16:52:29 +00:00
Alexander Shaduri 13d83949c4 Fix possibly invalid utf-8 data before showing it to the user (GscTextWindow,
GscExecutorLogWindow).
2011-12-15 16:58:06 +00:00
Alexander Shaduri daf98009d4 Added description for Multi_Zone_Error_Rate. 2011-12-15 15:57:58 +00:00
Alexander Shaduri 0cf5848772 Merged FreeBSD patches (fix in gsmartcontrol-root, /dev/ada* detection. 2011-11-19 18:08:58 +00:00
Alexander Shaduri 0ecc4bd8d3 Fixed compilation under Glib 2.31.x. 2011-11-02 16:00:39 +00:00
Alexander Shaduri 388a195794 Fixed compilation error.
Fixed parsing 'smartctl -v 194,raw8 -a' output (the attribute line).
2011-10-15 17:56:55 +00:00
Alexander Shaduri 0f89010225 Documented some more of hz. 2011-08-17 20:15:58 +00:00
Alexander Shaduri 42da49c5c1 Documented parts of hz library using doxygen tags. 2011-08-16 20:05:39 +00:00
Alexander Shaduri 0ffba26b1f Added (untested) Doxyfile.
Documented a few more hz files.
Added clang detection to the build system, use it when setting flags, etc...
Added some clang-specific flags to avoid excessive and unneeded warnings.
Fixed compilation under clang.
Fixed some clang-reported warnings.
2011-08-15 20:08:11 +00:00
Alexander Shaduri b19b094aaa Fixed a bug that issued SIGTERM to the child process instead of SIGKILL.
Documented applib completely.
Some minor member visibility adjustments.
2011-07-30 19:57:28 +00:00
Alexander Shaduri 5cc1e898b9 Use model name as well when detecting S/N duplicates. 2011-07-30 16:16:21 +00:00
Alexander Shaduri a4aa68a085 Very minor documentation changes.
NSIS: Don't strip update-smart-database.exe (it breaks if stripped) and
smartctl* (no reason to do it).
NSIS: Delete gtk installer on uninstall, sometimes it's not deleted during
installation.
2011-06-20 20:59:36 +00:00
Alexander Shaduri c954101bd9 Updated attribute database to smartmontools 5.41. 2011-06-11 17:27:28 +00:00
Alexander Shaduri d20aeb4121 Updated attribute DB.
Support older smartctl when filtering out 3ware sd* devices.
2011-06-07 17:08:57 +00:00
Alexander Shaduri 9440de5ca9 Updated some docs.
Proper filtering of /dev/sd* devices with older smartctl and 3ware.
Added missing file to Makefile.am.
2011-06-01 07:44:43 +00:00
Alexander Shaduri c2955b508c Fixed compilation under non-Linux/Windows platforms. 2011-05-28 12:49:56 +00:00
Alexander Shaduri fbf70814f0 Fixed make dist. 2011-05-28 12:22:54 +00:00
Alexander Shaduri a823790926 Updated NEWS file. 2011-05-28 12:18:05 +00:00
Alexander Shaduri 14838b82ae Updated readme. 2011-05-28 10:11:21 +00:00
Alexander Shaduri e11347c005 Support brief format of attributes, parse them to populate known columns. 2011-05-11 09:22:43 +00:00
Alexander Shaduri 98842f238e Windows: SUpport tw_cli/cx/px variant of smartctl device if --scan-open fails
and tw_cli is installed.
2011-05-01 14:41:58 +00:00
Alexander Shaduri 5ffc87ad9b Set tooltips wherever we have "No description available". 2011-05-01 13:03:36 +00:00
Alexander Shaduri fb5d139443 The detection now executes smartctl on the drives directly.
Don't execute smartctl --info if it was already executed during drive detection.
Made number of scanned ports configurable.
2011-05-01 12:16:26 +00:00
Alexander Shaduri 9d6ee05660 Add debian/ubuntu's su-to-root support to gsmartcontrol-root. 2011-04-30 18:41:36 +00:00
Alexander Shaduri 1ee97606aa Confirm operations (quit, rescan) when tests are running, don't just deny them. 2011-04-28 18:42:03 +00:00
Alexander Shaduri b6f721c167 Detect scsi number for 3ware and use that for tw_cli controller (Linux). 2011-04-20 12:23:54 +00:00
Alexander Shaduri ede4933819 Display device type argument along with device name everywhere. 2011-04-20 10:38:41 +00:00
Alexander Shaduri 70ce4a6d06 Fixed detecting usb flash drive names under winxp (smartctl would return a cli
parse error, which is incorrect).
Fixed parsing smartctl --scan-open output under windows.
2011-04-20 10:19:20 +00:00
Alexander Shaduri 213c26db3f Don't add sd* device if it's 3ware controller.
Properly add devices detected through 3ware scan (linux).
Limit smartctl sequential scans to 24 drives (it takes too long without it).
2011-04-19 17:59:44 +00:00
Alexander Shaduri 8ae3c42100 Added tooltips to both the labels and the entries in Add Device and Preferences
dialogs.
Changed the tooltips to avoid showing unsupported values for that OS.
Fixed usb drive re-detection with scsi (regression from previous commit).
Fixed invalid regexps in tw_cli output parsing (fixes 3ware in windows).
Added support for "Product" field of USB drives (used instead of Device in
newer smartctl).
2011-04-18 12:14:20 +00:00
Alexander Shaduri ff466a1d2d Add a note that we probably support Intel Matrix controllers as well. 2011-04-17 20:55:50 +00:00
Alexander Shaduri 5e46ed7cb6 Added support for devices detected by "smartctl --scan-open" under win32 (this
includes 3ware).
2011-04-17 20:36:54 +00:00
Alexander Shaduri c197ba76fa Support detecting drives behind 3ware controllers.
Add ExecutorFactory - now detectors can create their own gui or non-gui
executors, depending on who called them.
2011-04-17 18:47:43 +00:00
Alexander Shaduri fa2b10f3ce Show drive WWN and sector size. 2011-04-17 09:28:59 +00:00
Alexander Shaduri 7b523aa075 Updated to latest drivedb.h.
Made the type entry in Add Device window an editable combo, added sample types.
2011-04-16 20:38:39 +00:00
Alexander Shaduri 0ca9971460 Some more UI tweaks.
A new "Add Device" dialog - allows specifying type and additional smartctl
parameters.
Drive properties in preferences - allow specifying device type.
2011-04-16 19:25:06 +00:00
Alexander Shaduri b3f23abec0 Made the user interface more GNOME HIG-compliant. 2011-04-16 11:29:46 +00:00
Alexander Shaduri a2d735fee5 Added support for specifying -d option and extra parameters via command line
and preferences dialog. StorageDevice will use the specified type and
arguments when executing smartctl. This change effectively adds support for
multiple drives behind a single device name.
The preferences dialog can distinguish between various device types now (when
supplying smartctl arguments).
2011-04-04 20:02:41 +00:00
Alexander Shaduri fb801d8ebb Documented, reorganized StorageDevice source code.
Added "type argument" and "extra arguments" fields to StorageDevice.
2011-04-04 18:22:18 +00:00
Alexander Shaduri 9a92bfec45 Renamed "type" field (and all related stuff) of StorageDevice to detected_type. 2011-04-04 16:46:28 +00:00
Alexander Shaduri 6d50abb3cf Detect one more "smart unsupported" string in the latest version of smartctl
output.
Add a hint about "pd0" for Windows version in Preferences dialog.
2011-04-04 16:26:10 +00:00
Alexander Shaduri 778872363a New and improved attribute database (including SSD attributes).
Attributes are now matched according to smartctl names, and only then by ids.
Attribute notices are set by their generic names, not ids.
Improved displaying of attributes when they're unknown to us but known to
smartctl.
Set descriptions on all known capabilities.
Disabled tooltips on self-test log and error log entries (they always showed
"description unavailable" anyway).
2011-03-12 21:06:15 +00:00
Alexander Shaduri 6c404d57c9 Use -include only when using pch.
Document OptionalValue.
Use spaces when formatting date/time.
Capitalize some property names for consistency.
2011-03-09 11:26:52 +00:00
Alexander Shaduri 449b645278 Split storage detector to per-platform files. 2011-03-06 21:12:18 +00:00
Alexander Shaduri 02428a26c0 Show Error Log and Self-Test Log support.
Support attributes with undefined values like "---".
2011-03-06 20:31:39 +00:00
Alexander Shaduri 90bbc19923 Fixed inability to parse some error types in error log. 2011-03-06 19:04:13 +00:00
Alexander Shaduri 4f5690c89b Added ability to show smartctl output for devices whose info could not be
parsed fully.
2011-03-06 18:06:14 +00:00
Alexander Shaduri 4000fa1a2e Added the ability to configure default smartctl info save filename through
config file.
Use model-serial-date.txt for default save filename.
2011-03-06 17:15:56 +00:00
Alexander Shaduri ba7ffafa7f Updated copyrights to 2011.
Adjust Makefile.am for dist-files.
Added configure-dev script for easy developer-build configuration.
2011-03-06 10:43:38 +00:00
Alexander Shaduri 33b59d5723 Updated copyrights to 2010.
Reimplement locale stuff in hz (adding different controls for C and C++
locales), also take the recent locale-related changes in gtkmm into account.
Cleanups in snprintf-related code, portable_snprintf().
Added doxygen-style comments to some hz headers.
Better console redirection handling for win32.
Blacklisted linux device mapper devices (annoying in LVM setups).
Added beesu support and generally improved gsmartcontrol-root script (this is
needed for Fedora 14 which doesn't have any old supported su mechanisms).
Added "menu" dependency for deb packages.
Added kdev4 project.
2010-12-26 20:35:24 +00:00
Alexander Shaduri 28551a9666 Note: This revision was used to build 0.8.5-4 Windows package.
Set C++ locale as well, when setting C locale.
Improved windows installer.
2010-12-26 20:12:08 +00:00
Alexander Shaduri c5478d6a0e Note:This revision was used to build 0.8.5-3 Windows package.
Previous test result is cleared in GUI when running new tests now.
Windows: Vastly improved installer, supports built-in GTK+ now.
Windows: A proper method of privilege escalation is used for Vista/7.
Windows: GSmartControl works on Windows 7 now.
Updated copyright for files with Whatever License to use Unlicense.
2010-12-26 20:07:02 +00:00
596 changed files with 98192 additions and 53877 deletions
+109
View File
@@ -0,0 +1,109 @@
---
# Exceptions:
# bugprone-branch-clone is too noisy in parsing code.
# bugprone-easily-swappable-parameters is too noisy.
# cert-dcl50-cpp is triggered by hz::string_sprintf()'s C style.
# clang-analyzer-deadcode.DeadStores is too noisy.
# clang-analyzer-cplusplus.NewDeleteLeaks doesn't understand Gtkmm memory management.
# cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers is triggered by attribute database.
# cppcoreguidelines-avoid-do-while is triggered in DBG macros.
# cppcoreguidelines-owning-memory doesn't support deleting Gtkmm objects.
# cppcoreguidelines-pro-type-cstyle-cast needed by GTK C casts.
# cppcoreguidelines-pro-type-reinterpret-cast is needed by WinAPI-facing functions
# cppcoreguidelines-pro-type-vararg is triggered by hz::string_sprintf().
# cppcoreguidelines-pro-bounds-array-to-pointer-decay is triggered by va_start in hz::string_sprintf().
# cppcoreguidelines-pro-bounds-pointer-arithmetic is useless (triggered by argv) until we have std::span.
# misc-include-cleaner does not really work.
# misc-no-recursion is too noisy.
# modernize-raw-string-literal is very noisy.
# modernize-use-trailing-return-type is contrary to our style.
# performance-enum-size is too noisy.
# readability-avoid-unconditional-preprocessor-if is triggered on platform-specific code
# readability-convert-member-functions-to-static is triggered for many callbacks.
# readability-function-cognitive-complexity needed by UI constructors.
# readability-isolate-declaration is noisy.
# readability-identifier-length is too noisy.
Checks: >
-abseil-*,
-altera-*,
-android-*,
-boost-*,
bugprone-*,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
cert-*,
-cert-dcl50-cpp,
clang-analyzer-*,
-clang-analyzer-deadcode.DeadStores,
-clang-analyzer-cplusplus.NewDeleteLeaks,
concurrency-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-darwin-*,
-fuchsia-*,
google-*
hicpp-*,
-linuxkernel-*,
-llvm-*,
-llvmlibc-*,
misc-*,
-misc-include-cleaner,
-misc-no-recursion,
modernize-*,
-modernize-use-trailing-return-type,
-modernize-raw-string-literal,
-mpi-*,
-objc-*,
openmp-*,
performance-*,
-performance-enum-size,
portability-*,
readability-*,
-readability-avoid-unconditional-preprocessor-if,
-readability-convert-member-functions-to-static,
-readability-function-cognitive-complexity,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-identifier-length,
-zircon-*
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none
CheckOptions:
- key: bugprone-exception-escape.CheckCapsOnly
value: '1'
- key: cppcoreguidelines-macro-usage.CheckCapsOnly
value: '1'
- key: cppcoreguidelines-owning-memory.LegacyResourceConsumers
value: '::free;::realloc;::freopen;::fclose;Gtk::manage'
- key: misc-assert-side-effect.AssertMacros
value: assert,DBG_ASSERT
- key: misc-assert-side-effect.CheckFunctionCalls
value: '0'
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: misc-include-cleaner.IgnoreHeaders
value: 'libdebug/*;local_glibmm.h;glib/*;gtk/*;gtkmm/*;glibmm/*'
- key: performance-unnecessary-value-param.AllowedTypes
value: 'RefPtr;Ptr$'
- key: readability-braces-around-statements.ShortStatementLines
value: '2'
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: '1'
- key: readability-implicit-bool-cast.AllowConditionalPointerCasts
value: '1'
...
+3
View File
@@ -0,0 +1,3 @@
# Make sure github recognizes header files as C++, not C.
*.h linguist-language=C++
+28
View File
@@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug, enhancement
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Describe the Bug**
[A clear and concise description of what the bug is].
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Screenshots**
[If applicable, add screenshots to help explain your problem].
**Additional Context**
[Add any other context about the problem here (GTK+ version, etc.)]
+24
View File
@@ -0,0 +1,24 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+15
View File
@@ -0,0 +1,15 @@
---
name: Other issue
about: Issues other than bugs and enhancements
title: ''
labels: ''
assignees: ashaduri
---
**Version and Environment**
- GSmartControl version: [Are you using the latest released version or git?]
- OS: [e.g. openSUSE Linux 15.5]
**Describe the Issue**
[A clear and concise description of what the issue is].
+186
View File
@@ -0,0 +1,186 @@
name: Build (Tier 1 platforms)
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
jobs:
linux-ubuntu:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Update Package Database
run: sudo apt-get update
- name: Install Dependencies
run: sudo apt-get install libgtkmm-3.0-dev gettext
- name: Create Build Directory
run: cmake -E make_directory build
- name: Configure CMake
shell: bash
working-directory: ${{github.workspace}}/build
env:
CC: gcc-13
CXX: g++-13
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/linux-dev.cmake"
- name: Build
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Pack (cmake install and make binary package)
shell: bash
working-directory: ${{github.workspace}}/build
run: cpack -G TBZ2
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: Linux Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-Linux*.*
windows-msys2:
runs-on: windows-latest
strategy:
matrix:
include: [
{ msystem: MINGW64, arch: x86_64, platform: win64 },
{ msystem: MINGW32, arch: i686, platform: win32 }
]
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
# p7zip is needed to extract smartmontools
# fontconfig owns /etc/fonts
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
mingw-w64-${{ matrix.arch }}-gtkmm3
mingw-w64-${{ matrix.arch }}-pkg-config
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-fontconfig
make
p7zip
- name: Download Package Requirements
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: |
mkdir -p build/smartmontools
cd build/smartmontools
wget $SMARTMONTOOLS_URL
- name: Extract Package Requirements (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin/smartctl.exe
bin/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: Extract Package Requirements (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin32/smartctl.exe
bin32/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: List installed files
shell: msys2 {0}
run: |
ls -1R /mingw64
ls -1R /mingw32
- name: List Files in Workspace
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: ls -1R .
- name: Configure CMake
shell: msys2 {0}
run: >
cmake -B build -S "$GITHUB_WORKSPACE"
-G "MSYS Makefiles"
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
- name: Build
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: msys2 {0}
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Package ZIP
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G ZIP
- name: Package NSIS (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS64
- name: Package NSIS (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW64' }}
uses: actions/upload-artifact@v4
with:
name: Windows 32-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW32' }}
uses: actions/upload-artifact@v4
with:
name: Windows 64-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
+46
View File
@@ -0,0 +1,46 @@
name: Build (Tier 2 platforms with flaky builds)
# FreeBSD build via vmactions/freebsd-vm is known to fail randomly,
# so we don't want it to be triggered on every commit.
# Manually triggered
on: [workflow_dispatch]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
CXX: clang++-17
jobs:
freebsd:
runs-on: ubuntu-latest
# env:
# variables to pass to VM
# MYTOKEN : ${{ secrets.MYTOKEN }}
steps:
- uses: actions/checkout@v4
- name: Build and test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
envs: 'BUILD_TYPE CXX'
usesh: true
sync: rsync
# release: "14.0"
prepare: >
pkg install -y cmake pkgconf gtkmm30 gettext libiconv llvm17
run: >
mkdir build && cd build
cmake ..
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
cmake --build . --config $BUILD_TYPE
ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
+75
View File
@@ -0,0 +1,75 @@
name: Build (Tier 2 platforms)
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
jobs:
macos-homebrew:
runs-on: macos-latest
strategy:
matrix:
include: [
# We need AppleClang 16, but GitHub only has 14 for now.
# { compiler: apple-clang },
{ compiler: clang }
]
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: brew install pkg-config gtkmm3 cmake
- name: Install Clang Compiler
if: ${{ matrix.compiler == 'clang' }}
run: brew install llvm@17
- name: Create Build Directory
run: cmake -E make_directory build
- name: Configure CMake (Apple Clang)
if: ${{ matrix.compiler == 'apple-clang' }}
shell: bash
working-directory: ${{github.workspace}}/build
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
- name: Configure CMake
if: ${{ matrix.compiler == 'clang' }}
shell: bash
working-directory: ${{github.workspace}}/build
run: >
cmake $GITHUB_WORKSPACE
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DAPP_BUILD_EXAMPLES=ON
-DAPP_BUILD_TESTS=ON
-DAPP_COMPILER_ENABLE_WARNINGS=ON
-DCMAKE_CXX_COMPILER=$(brew --prefix llvm@17)/bin/clang++
- name: Build
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
+61
View File
@@ -0,0 +1,61 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '27 22 * * 1'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-24.04
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
+85
View File
@@ -0,0 +1,85 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '24 10 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-24.04
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
#packages: read
# only required for workflows in private repositories
#actions: read
#contents: read
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update Package Database
run: sudo apt-get update
- name: Install Dependencies
run: sudo apt-get install libgtkmm-3.0-dev gettext
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
env:
CC: gcc-13
CXX: g++-13
uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
+36
View File
@@ -0,0 +1,36 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: DevSkim
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '25 22 * * 0'
jobs:
lint:
name: DevSkim
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run DevSkim scanner
uses: microsoft/DevSkim-Action@v1
with:
ignore-globs: dummy_to_avoid_action_error,**/.git/**,*.txt,**/dependencies/**,env_tools.h,app_gtkmm_tools.cpp
- name: Upload DevSkim scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: devskim-results.sarif
+128
View File
@@ -0,0 +1,128 @@
name: Windows Release
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
SMARTMONTOOLS_INSTALLER: smartmontools-7.4-1.win32-setup.exe
SMARTMONTOOLS_URL: https://downloads.sourceforge.net/project/smartmontools/smartmontools/7.4/smartmontools-7.4-1.win32-setup.exe
jobs:
windows-msys2:
runs-on: windows-latest
strategy:
matrix:
include: [
{ msystem: MINGW64, arch: x86_64, platform: win64 },
{ msystem: MINGW32, arch: i686, platform: win32 }
]
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
# p7zip is needed to extract smartmontools
# fontconfig owns /etc/fonts
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
mingw-w64-${{ matrix.arch }}-gtkmm3
mingw-w64-${{ matrix.arch }}-pkg-config
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-fontconfig
make
p7zip
- name: Download Package Requirements
shell: msys2 {0}
working-directory: ${{github.workspace}}
run: |
mkdir -p build/smartmontools
cd build/smartmontools
wget $SMARTMONTOOLS_URL
- name: Extract Package Requirements (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin/smartctl.exe
bin/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: Extract Package Requirements (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build/smartmontools
run: >
7z -bb1 e $SMARTMONTOOLS_INSTALLER
bin32/smartctl.exe
bin32/smartctl-nc.exe
bin/update-smart-drivedb.ps1
bin/drivedb.h
- name: List installed files
shell: msys2 {0}
run: |
ls -1R /mingw64
ls -1R /mingw32
- name: Configure CMake
shell: msys2 {0}
run: >
cmake -B build -S "$GITHUB_WORKSPACE"
-G "MSYS Makefiles"
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
-DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/toolchains/${{ matrix.platform }}-mingw-msys2.cmake"
- name: Build
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build
shell: msys2 {0}
run: ctest -C $BUILD_TYPE --rerun-failed --output-on-failure
- name: Package ZIP
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G ZIP
- name: Package NSIS (64-bit)
if: ${{ matrix.msystem == 'MINGW64' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS64
- name: Package NSIS (32-bit)
if: ${{ matrix.msystem == 'MINGW32' }}
shell: msys2 {0}
working-directory: ${{github.workspace}}/build
run: cpack -G NSIS
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW64' }}
uses: actions/upload-artifact@v4
with:
name: Windows 64-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
- name: Upload artifacts
if: ${{ matrix.msystem == 'MINGW32' }}
uses: actions/upload-artifact@v4
with:
name: Windows 32-Bit Packages
path: ${{github.workspace}}/build/gsmartcontrol-*-win*.*
+41
View File
@@ -0,0 +1,41 @@
# Builds
/0*
/win32*
/win64*
/cmake-build-*
# Non-project files
/TODO
# Doxygen generated
/doxygen_doc
# OS-generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
# IDE
/.vs
/*.pcs
/.idea
/CMakeLists.txt.user
# Translations
/po/boldquot.sed
/po/en@boldquot.header
/po/en@quot.header
/po/insert-header.sin
/po/Makevars.template
/po/quot.sed
/po/remove-potcdate.sin
/po/Rules-quot
/po/gsmartcontrol.pot
/po/*.gmo
+179
View File
@@ -0,0 +1,179 @@
# This file describes OBS workflows:
# https://openbuildservice.org/help/manuals/obs-user-guide/cha.obs.scm_ci_workflow_integration.html
# Workflow for pull requests
#build_pull_request_workflow:
# steps:
# - branch_package:
# source_project: home:alex_sh:gsmartcontrol:github_ci:main
# source_package: gsmartcontrol
# target_project: home:alex_sh:gsmartcontrol:github_ci:main
#
# - configure_repositories:
# project: home:alex_sh:gsmartcontrol:github_ci:main
# repositories:
# - name: openSUSE_Tumbleweed
# paths:
# - target_project: openSUSE:Factory
# target_repository: snapshot
# architectures:
# - x86_64
# - i586
#
# - set_flags:
# flags:
# - type: publish
# status: disable
# project: home:alex_sh:gsmartcontrol:github_ci:main
#
# filters:
# event: pull_request
# branches:
# only:
# - main
# Workflow for pushes
# Note: This adds new repositories to the project if they do not exist.
build_main_workflow:
steps:
- configure_repositories:
project: home:alex_sh:gsmartcontrol:github_ci:main
repositories:
- name: openSUSE_Tumbleweed
paths:
- target_project: openSUSE:Factory
target_repository: snapshot
architectures:
- x86_64
- name: openSUSE_Slowroll
paths:
- target_project: openSUSE:Slowroll
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Leap_15.6
paths:
# - target_project: devel:gcc
# target_repository: openSUSE_Leap_15.6
- target_project: openSUSE:Leap:15.6
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Leap_15.5
paths:
- target_project: devel:gcc
target_repository: openSUSE_Leap_15.5
- target_project: openSUSE:Leap:15.5
target_repository: standard
architectures:
- x86_64
- name: openSUSE_Factory_ARM
paths:
- target_project: openSUSE:Factory:ARM
target_repository: standard
architectures:
- aarch64
- armv7l
- name: SUSE_SLE-15-SP6
paths:
- target_project: devel:gcc
target_repository: SLE-15
- target_project: SUSE:SLE-15-SP6:GA
target_repository: standard
architectures:
- x86_64
- name: Ubuntu_24.04
paths:
- target_project: openSUSE:Tools
target_repository: xUbuntu_24.04
- target_project: Ubuntu:21.10
target_repository: universe
architectures:
- x86_64
- name: Ubuntu_23.10
paths:
- target_project: openSUSE:Tools
target_repository: xUbuntu_23.10
- target_project: Ubuntu:20.04
target_repository: universe
architectures:
- x86_64
- name: Fedora_Rawhide
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_Rawhide
- target_project: Fedora:Rawhide
target_repository: standard
architectures:
- x86_64
- name: Fedora_40
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_40
- target_project: Fedora:40
target_repository: standard
architectures:
- x86_64
- aarch64
- name: Fedora_39
paths:
- target_project: openSUSE:Tools
target_repository: Fedora_39
- target_project: Fedora:39
target_repository: standard
architectures:
- x86_64
- aarch64
- name: Debian_Unstable
paths:
- target_project: openSUSE:Tools
target_repository: Debian_Unstable
- target_project: Debian:Next
target_repository: standard
architectures:
- x86_64
- name: Debian_Testing
paths:
- target_project: openSUSE:Tools
target_repository: Debian_Testing
- target_project: Debian:Testing
target_repository: update
architectures:
- x86_64
- i586
- set_flags:
flags:
- type: publish
status: enable
project: home:alex_sh:gsmartcontrol:github_ci:main
- type: debuginfo
status: enable
project: home:alex_sh:gsmartcontrol:github_ci:main
- rebuild_package:
project: home:alex_sh:gsmartcontrol:github_ci:main
package: gsmartcontrol
filters:
event: push
branches:
only:
- main
+81
View File
@@ -0,0 +1,81 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# 3.14 for proper object library support (wrt linking)
cmake_minimum_required(VERSION 3.14)
# Use new policy for option() to supress warnings.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
include(${CMAKE_SOURCE_DIR}/version.txt)
project(gsmartcontrol
VERSION ${CMAKE_PROJECT_VERSION}
DESCRIPTION "Hard Disk Drive and SSD Health Inspection Tool"
HOMEPAGE_URL "https://gsmartcontrol.shaduri.dev"
LANGUAGES CXX
)
# Provide DATADIR, etc.
include(GNUInstallDirs)
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
include(src/build_config/compiler_options.cmake)
# Disable RPATH manipulation, we don't have shared libraries
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
# Write the binaries to project root (avoids conflicts with manifests, also it's more convenient this way)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
# User-controlled build options
option(APP_BUILD_EXAMPLES "Build examples" OFF)
option(APP_BUILD_TESTS "Build tests" OFF)
# Install documentation
set(DOC_FILES
LICENSE.LGPL3.txt
LICENSE.txt
NEWS.txt
README.md
)
if (WIN32)
install(FILES ${DOC_FILES} DESTINATION doc/)
install(DIRECTORY docs DESTINATION doc/
PATTERN "*.yml" EXCLUDE
PATTERN "CNAME" EXCLUDE
)
else()
install(FILES ${DOC_FILES} TYPE DOC)
install(DIRECTORY docs TYPE DOC
PATTERN "*.yml" EXCLUDE
PATTERN "CNAME" EXCLUDE
)
endif()
# CTest support
include(CTest)
#include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/extras/Catch.cmake)
include(${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/contrib/Catch.cmake)
add_subdirectory(contrib)
add_subdirectory(data)
add_subdirectory(dependencies)
add_subdirectory(packaging)
add_subdirectory(src)
# Packaging support
include(packaging/cpack_options.cmake)
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
ashaduri@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+2524
View File
File diff suppressed because it is too large Load Diff
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+278
View File
@@ -0,0 +1,278 @@
Version 2.0.1, released on 2024-11-26
Windows: Fixed a crash when opening a native file dialog (#67).
Version 2.0.0, released on 2024-11-07
New JSON-based parser for smartctl output (requires smartctl 7.3+) (#4).
Support for NVMe drives (self-tests require smartctl 7.4+) (#4).
New "Basic" JSON parser for SCSI, flash, and other non-ATA/NVMe drives.
PCRE library is no longer required (the code has been ported to
std::regex) (#40).
A lot of code has been refactored and modernized using C++17 and C++20
features, removing much of the custom library code.
The build process requires a C++20-compliant compiler now (GCC 13+,
Clang 17+, Apple Clang 15+).
CMake (3.14+) is now used as a build system instead of autotools.
GSmartControl is now licensed under GNU GPL 3 only.
Icons come from Oxygen project now (LGPL 3+) instead of Crystal project.
Documentation in md format comes with the source code ("docs" directory).
Support new versions and prereleases of smartctl (#46, #42).
Better detection of drive types thanks to the JSON parser.
Removed ATA AODC feature, it has been deprecated for a while now.
Information window: Some values are aligned and monospaced to improve
readability.
Fixed command execution popup dialog being on top of all windows (#17).
Other minor UI improvements and fixes.
Windows: Better support for HiDPI (including fractional scaling).
Windows: NSIS package is generated by CPack now.
Windows: Packages are built using GitHub CI now.
Version 1.1.4, released on 2022-02-04
Fixed a crash when trying to render main window icons which have
incomplete data; this fixes a rare crash when scanning devices (#13).
Fixed rendering compatibility issues with newer GTK3 versions.
Fixed build system conflict with C++20 version header (#14).
Fixed "Running command ..." dialog floating above windows of other
applications (#17).
Fixed a crash when system locale is set to invalid locale.
Support Finnish decimal separator (backported from the Debian package)
(#23).
Set LC_NUMERIC=C for smartctl process to avoid locale-dependent number
formatting (#23).
Fixed printing all GTK messages as warnings; the messages are sorted by
severity now.
Add current time to default filename in Save Output dialog.
Support macos stat command in file2csource.sh.
Fixed a few typos (backported from the Debian package).
Windows port now uses Adwaita theme due to issues with win32 theme.
Windows port is dpi-aware now.
Version 1.1.3, released on 2017-11-12
Fixed gsmartcontrol-root not launching if GDK_* variables are not set.
Version 1.1.2, released on 2017-11-11
Fixed gsmartcontrol-root not passing GDK_SCALE and GDK_DPI_SCALE variables
to gsmartcontrol when using PolKit.
Fixed blurriness of icons in the main window with GDK_SCALE=2.
Tweaked the main window interface.
Windows: Show volume labels beside drive letters in icon tooltips.
Version 1.1.1, released on 2017-09-25
Windows: Use Adwaita GTK+ theme for systems which support Classic Windows
theme, since the default win32 GTK+ theme is broken in it; this
includes Windows 7 and Windows Server.
Statistics entry values are formatted with commas for readability.
Moved help information to website.
Version 1.1.0, released on 2017-09-07
New Statistics, Temperature Log, Error Recovery, Physical and Directory
tabs.
General tab shows non-SMART device settings as well.
Attributes tab shows entries in "brief" format.
Error Log tab shows Extended error log by default (if supported).
Self-Test Log tab now shows Extended self-test log by default (if
supported).
GSmartControl now uses "-x" equivalent for retrieving data (as upposed to
"-a"); loading "-x" outputs as virtual drives is also supported.
Implemented ability to copy rows in CSV format from Attribute, Statistics
and Self-Test Log tables.
Implemented "Update Drive Database" functionality.
Windows: Drive letters are shown for each drive.
Scan time is shown under virtual drive icons.
Polkit is supported with gsmartcontrol-root script now.
Pcrecpp is no longer bundled, use system-installed one instead.
Smartmontools version 5.43 is required at runtime.
Other minor improvements and fixes.
Version 1.0.2, released on 2017-07-21
Fixed incomplete capturing of smartctl output under Windows.
Added missing icons under Windows.
Fixed being able to turn on AODC even if unsupported.
Version 1.0.1, released on 2017-06-19
Fixed compilation under macOS.
Fixed compilation under Fedora Rawhide.
Don't use -mtune=generic for all targets.
Version 1.0.0, released on 2017-06-16
Ported to GTK+ 3.
Tweaked the user interface a bit.
Dropped support for Windows XP, 2000 and 2003 (they are no longer
supported by GTK+).
Fixed detection of newer system-installed smartmontools under Windows.
Version 0.9.0, released on 2017-05-11
Implemented (untested) support for Linux-based Areca controllers with
enclosures.
Implemented (untested) support for Windows-based Areca controllers (thanks
to Richard Kagerer).
Implemented (untested) support for Linux-based HP controllers with cciss
and hpsa/hpahcisr drivers (thanks to Fabrice Bacchella).
Changes in Preferences no longer fail silently until rescan/restart.
Better drive detection under Windows after removable drives are detached.
Windows version is no longer marked as "dpi aware" since it's not
supported that well.
Drive attribute descriptions have been updated (including clarifications
for SSDs).
Added support for SSD-only and HDD-only vendor attributes.
Devices having only basic info can be displayed now in the info window.
Fixed BDRW drive detection (it was detected as a HDD).
Other minor improvements.
A number of issues have been fixed (including a crash).
Version 0.8.7, released on 2012-08-11
Implemented support for Adaptec RAID 5805 controller and possibly other
Adaptec models as well (Linux).
Implemented support for Areca RAID controller detection under Linux
(untested).
Implemented support for 3ware 3w-sas-supported (twl) RAID controller
detection under Linux (untested).
Implemented support for systems with several different 3ware controllers
(twa/twe/twl).
Fixed invalid parsing of tw_cli output which caused non-detection of
drives and controllers with controller or port numbers greater than 9
if tw_cli was found (3ware linux, windows).
The duplicate drives are no longer shown for some Intel matrix controllers
under Windows; Intel RAID controllers are fully supported under
Windows now.
Added options to show device name and serial number under drive icons.
Updated SMART attribute definitions and added warnings for SSD lifetime
attributes.
gsmartcontrol-root has a new argument "--desktop=..." which replaces the
old positional argument; compatibility with the old invocation syntax
has been retained.
Completely documented the source using doxygen tags.
Added support for Fedora's consolehelper.
Made GSmartControl DPI-aware under Windows.
Fixed compilation issues with clang and gcc 4.7, as well as glib 2.31.x
and newer.
Fixed minor issues in NSIS installer.
Fixed other minor bugs and made minor improvements.
Version 0.8.6, released on 2011-06-12
Support detecting drives behind 3ware controllers (Linux, Windows),
including tw_cli/cx/px mode in Windows. Having tw_cli is recommended
but not required.
Added support for specifying -d option and extra parameters via command
line, "Add Device" and "Preferences" dialogs. This change effectively
adds full support for multiple drives behind a single device name.
Beesu and su-to-root are supported by gsmartcontrol-root script now.
Completely revamped the attribute database and its handling, should be a
lot more usable and forward-compatible now; SSD attributes are also
included.
In-program help has been expanded considerably.
General improvements to user interface have been implemented (better GNOME
HIG compliance, better tooltips, dialogs, etc.).
Added ability to show smartctl output for devices whose info could not be
parsed fully.
Attributes in "brief" format are supported now.
The parser has been updated to reflect the recent changes in smartctl.
Quit and rescan operations are no longer denied without confirmation when
tests are running.
The Windows NSIS installer has been vastly improved.
Better support for Windows Vista and 7.
Changed copyright notices for files with Whatever License to use Unlicense.
Added other minor features and fixed quite a few bugs.
Version 0.8.5, released on 2009-09-05
GSmartControl now uses XDG config directory for per-user configuration on
UNIX and CSIDL_PROFILE directory on Windows. Existing configuration is
migrated automatically.
The names are shown correctly for unsupported devices even with the latest
smartctl snapshots now.
Smartctl SVN revision is shown (if available).
The progress bars update properly when parallel tests are run.
Windows: GSmartControl should be able to operate on any valid filesystem
path (not just locale-representable ones).
Windows: GSmartControl is now officially compilable on x86_64 via mingw64.
Fixed compilation under very old gtkmm/libglademm, and with gcc 4.4.
Fixed parsing of multiple error types in SMART error log.
Added minor features and fixed miscellaneous bugs.
Version 0.8.4, released on 2009-03-23
Linux Software RAID devices are blacklisted now. (backported from Debian).
Attributes tab is before the capabilities tab now.
A man page has been generously contributed by Giuseppe Iuculano
<giuseppe@iuculano.it>.
Smartctl version now includes the CVS snapshot date (if available).
Windows: Look for "smartctl-nc.exe" instead of "smartctl.exe" by default.
Windows: Use smartmontools-supplied smartctl-nc.exe by default (if found).
Other minor changes (mainly Debian backports).
Version 0.8.3, released on 2008-12-27
A random "Smartctl returned an empty output" error on Windows was fixed.
Thanks to Zurab Khetsuriani for testing.
Fixed a parser issue which prevented running self-tests in Windows.
The supplied icon (hopefully) shows correctly in Windows 2000 now.
This release adds an official support for Windows 2000 SP4.
Added scripts to allow GSmartControl to read smartctl data from
cron-generated files. This allows users to read somewhat recent
smartctl information without having to run GSmartControl as root.
Generously contributed by Alex Butcher <alex dot butcher 'at'
assursys.co.uk>.
Configure script correctly aborts instead of printing a warning if gtkmm
or libglademm (if needed) is not found.
Configure script now accepts --enable-windows-console,
--disable-abort-if-no-gtkmm, --disable-abort-if-no-glade-reader,
as well as Windows-supporting "auto" for --enable-nsis-wine and
--with-nsis.
Configure's --with-win32-env has been renamed to --with-windows-dlls.
The "About" dialog shows version information now.
Minor bugs were fixed.
Version 0.8.2, released on 2008-12-10
Fixed gsmartcontrol_root.sh script to support distributions with no
/usr/sbin in their users' paths (thanks to Erwan Velu).
Added desktop auto-detection to gsmartcontrol_root.sh script. This allows
us to use only one desktop file (thanks to Erwan Velu).
Added Debian package directory (named "debian.dist" for now to avoid
control file conflicts with Build Service).
Renamed gsmartcontrol_root.sh to gsmartcontrol-root, to make Debian happy.
Added make targets for Windows packages (zip and NSIS).
Fixed Windows-related issues (Vista is fully supported now).
Fixed minor bugs:
Smartctl parser is win32-locale-aware now.
No more unnecessary parsing.
No segfault on exit under Windows and Solaris.
A friendlier message is displayed if smartctl was not found.
No highlighted labels when switching tabs in Information window.
Version 0.8.1, released on 2008-11-11
Disabled Linux "by-id" drive detection - it's unreliable on some broken
systems.
Added some more attribute descriptions.
Our names for attributes override smartctls' now.
Added a proper "Add Device" dialog for Windows.
Added an icon and resource file for Windows.
Fixed minor bugs.
Version 0.8.0rc4, released on 2008-10-20
FreeBSD support (tested with DesktopBSD 1.6 (FreeBSD 6.3) / x86).
NetBSD support (tested with NetBSD 4.0.1 / x86).
OpenBSD support (tested with OpenBSD 4.3 / x86-64 / gcc-3.3.5).
Solaris/gcc support (tested with Solaris 10 / x86 / gcc-3.4.3 / blastwave).
Solaris/sunstudio support (tested with Solaris 10 / x86 / sunstudio12 /
sunfreeware).
Code to support Windows, Mac OS X, QNX.
Support of older pcre versions (at least 4.5, maybe older too).
Added gsmartcontrol_root.sh script to easily run gsmartcontrol as root.
Improved .desktop files.
License for tests and examples is legally more correct now.
Minor bugfixes.
Version 0.8.0rc3, released on 2008-10-08
Added support for udevless Linux distributions by providing a fallback
/proc/partitions-based drive detection method. The new method adds
support for Linux 2.4 and older systems. Thanks to Paul Marwick for
reporting and testing.
Fixed invalid error messages with directory-related operations.
Fixed invalid verbosity levels of console output of debug messages in
non-debug builds.
Improved rpm spec file - now supports building on OpenSUSE build
service with various distributions as targets.
Version 0.8.0rc2, released on 2008-10-05
Fixed compilation under gcc 4.3. Thanks to Peter Linnell for reporting.
Removed test data (there's a lot of it and it's unnecessary).
Version 0.8.0rc1, released on 2008-10-01
Initial public release.
+76
View File
@@ -0,0 +1,76 @@
# GSmartControl
***Hard disk drive and SSD health inspection tool***
[![Generic badge](https://img.shields.io/badge/Homepage-gsmartcontrol.shaduri.dev-brightgreen.svg)](https://gsmartcontrol.shaduri.dev)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/ashaduri/gsmartcontrol?label=Version)](https://gsmartcontrol.shaduri.dev/downloads)
[![license: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Platforms](https://img.shields.io/badge/Platforms-linux%20%7C%20windows%20%7C%20macos%20%7C%20*bsd-blue)](https://gsmartcontrol.shaduri.dev/software-requirements)
[![Packaging status](https://repology.org/badge/tiny-repos/gsmartcontrol.svg?header=Software%20distributions%20and%20repositories)](https://repology.org/project/gsmartcontrol/versions)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/528f4f7aaf0e446abf7e55d2affc7bec)](https://app.codacy.com/gh/ashaduri/gsmartcontrol?utm_source=github.com&utm_medium=referral&utm_content=ashaduri/gsmartcontrol&utm_campaign=Badge_Grade_Settings)
---
[GSmartControl](https://gsmartcontrol.shaduri.dev)
is a graphical user interface for smartctl (from [smartmontools](https://www.smartmontools.org/)
package), which is a tool for
querying and controlling [SMART](https://en.wikipedia.org/wiki/S.M.A.R.T.)
(Self-Monitoring, Analysis, and Reporting
Technology) data on modern hard disk and solid-state drives. It allows you to
inspect the drive's SMART data to determine its health, as well as run various
tests on it.
## Downloads
The [Downloads](https://gsmartcontrol.shaduri.dev/downloads) page contains
all the available packages of GSmartControl.
## Features
- automatically reports and highlights any anomalies;
- allows enabling/disabling SMART;
- supports configuration of global and per-drive options for smartctl;
- performs SMART self-tests;
- displays drive identity information, capabilities, attributes, device statistics, etc.;
- can read in smartctl output from a saved file, interpreting it as a read-only virtual device;
- works on most smartctl-supported operating systems;
- has extensive help information.
### Supported Hardware
GSmartControl supports SATA, PATA, and NVMe drives, as well as drives
behind some USB bridges and RAID controllers.
Please see the
[Supported Hardware](https://gsmartcontrol.shaduri.dev/supported-hardware) page
for more information.
### Supported Platforms
GSmartControl supports all major desktop operating systems, including
Linux, Windows, macOS, FreeBSD, and other BSD-style operating systems.
Please see the
[Software Requirements](https://gsmartcontrol.shaduri.dev/software-requirements) page
for more information.
## Copyright and Licensing
GSmartControl is Copyright (C) 2008 - 2024 Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com) and contributors.
GSmartControl is licensed under the terms of
[GNU General Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html).
This program is free software: you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published by the
Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public Licenses for more details.
This product includes icons from Oxygen Icons copyright [KDE](https://kde.org)
and licenced under the [GNU LGPL version 3](https://www.gnu.org/licenses/lgpl-3.0.en.html) or later.
+16
View File
@@ -0,0 +1,16 @@
# Security Policy
## Supported Versions
The following versions are supported with security updates:
| Version | Supported |
|----------| ------------------ |
| git main | :white_check_mark: |
| 2.0.x | :white_check_mark: |
| < 2.0.0 | :x: |
## Reporting a Vulnerability
Please report security vulnerabilities privately to
Alexander Shaduri [ashaduri@gmail.com](mailto:ashaduri@gmail.com).
Executable
+160
View File
@@ -0,0 +1,160 @@
#!/bin/bash
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2012 - 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Configure a build directory for development
function print_usage() {
echo -e "Usage:"
echo -e " ${0} [-t <toolchain_name>] [-c <compiler>] [-b <build_type>]"
echo -e " [-s <source_dir>] [-g <generator>] [-o <cmake_options>]"
echo -e "\nDetails:"
echo -e "-t <toolchain_name> - toolchain_name can be e.g. \"win32-mingw64\"."
echo -e " A toolchain file \"toolchains/<toolchain_name>.cmake\" will be used."
echo -e "-c <compiler> - compiler is one of:"
echo -e " gcc, gcc-<version>, clang, intel."
echo -e " The gcc version is the suffix of gcc and g++ executables, e.g. \"4.8\" in"
echo -e " \"gcc-4.8\"."
echo -e " If unspecified, CC and CXX environment variables are used."
echo -e "-b <build_type> - build_type is one of:"
echo -e " Debug, Release, RelWithDebInfo, MinSizeRel, none. The default is Debug."
echo -e "-s <source_dir> - source_dir is \"..\" by default."
echo -e "-g <cmake_generator> - cmake uses \"Unix Makefiles\" by default."
echo -e "-o <cmake_options> - options to pass directly to cmake."
}
compiler=""
build_type="";
source_dir=".."
toolchain_name=""
generator=""
cmake_options=""
while getopts "t:c:b:s:g:o:h:" opt; do
case $opt in
t)
echo "Requested toolchain: $OPTARG"
toolchain_name="$OPTARG";
;;
c)
echo "Requested compiler: $OPTARG"
compiler="$OPTARG";
;;
b)
echo "Requested build type: $OPTARG"
build_type="$OPTARG";
;;
s)
echo "Requested source directory type: $OPTARG"
source_dir="$OPTARG";
;;
g)
echo "Requested generator: $OPTARG"
generator="$OPTARG";
;;
o)
echo "Requested cmake options: $OPTARG"
cmake_options="$OPTARG";
;;
h)
print_usage;
exit 1;
;;
\?)
echo "Invalid option: $opt";
print_usage;
exit 1;
;;
esac
done
if [ "$compiler" != "" ] && [ "$toolchain_name" != "" ]; then
echo "Error: Conflicting options -c and -t specified."
exit 1;
fi
cmake_flags="-Wdev";
if [ "$build_type" = "none" ]; then
build_type="";
fi
if [ "$build_type" != "" ]; then
cmake_flags="$cmake_flags -DCMAKE_BUILD_TYPE=$build_type";
fi
if [ "$generator" != "" ]; then
cmake_flags="$cmake_flags -G${generator}";
fi
status=1
# Toolchain mode
if [ "$toolchain_name" != "" ]; then
cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE='${source_dir}/data/cmake/toolchains/${toolchain_name}.cmake'"
echo "Running:"
echo "cmake $cmake_flags $source_dir";
cmake $cmake_flags $cmake_options $source_dir
status=$?
else # Compiler mode
c_compiler="";
cxx_compiler="";
# Detect gcc suffix like "-4.7"
if [ "${compiler:0:4}" = "gcc-" ]; then
suffix=${compiler:4};
c_compiler="gcc-${suffix}";
cxx_compiler="g++-${suffix}";
compiler="gcc";
fi
case $compiler in
gcc)
if [ "$c_compiler" = "" ]; then
c_compiler="gcc${machine_bits_switch}";
cxx_compiler="g++${machine_bits_switch}";
fi
;;
intel)
if [ $machine_bits_precise = "64" ]; then
c_compiler="icc64";
cxx_compiler="icpc64";
else
c_compiler="icc32";
cxx_compiler="icpc32";
fi
;;
clang)
c_compiler="clang${machine_bits_switch}";
cxx_compiler="clang++${machine_bits_switch}";
;;
"")
c_compiler="$CC"
cxx_compiler="$CXX"
;;
*)
echo "Unsupported compiler given; use CC and CXX instead."
exit 1;
;;
esac
echo "Running:"
echo "CC=\"$c_compiler\" CXX=\"$cxx_compiler\" cmake $cmake_flags $source_dir";
CC="$c_compiler" CXX="$cxx_compiler" cmake $cmake_flags $cmake_options $source_dir
status=$?
fi
exit $status
+10
View File
@@ -0,0 +1,10 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
if (NOT WIN32)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/contrib" TYPE DOC
PATTERN "CMakeLists.txt" EXCLUDE)
endif()
@@ -1,10 +1,10 @@
#!/bin/bash
############################################################################
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2009 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2009 Alexander Shaduri <ashaduri 'at' gmail.com>
# License: See LICENSE_whatever.txt file
############################################################################
# (C) 2008 - 2024 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
device="$1";
@@ -13,10 +13,10 @@ if [ "$device" = "" ]; then
exit 1;
fi
dev_base="`basename \"$device\"`"
dev_base=$(basename "$device")
out_file=/var/run/smart-"$dev_base"
# Change the path to smartctl if necessary.
smartctl -a "$device" 2>&1 > "$out_file"
smartctl -x --json=o "$device" > "$out_file" 2>&1
chmod 644 "$out_file"
@@ -0,0 +1,9 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2021 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
*/10 * * * * root /usr/local/bin/cron-smart.sh /dev/sda
*/10 * * * * root /usr/local/bin/cron-smart.sh /dev/sdb
@@ -1,10 +1,10 @@
#!/bin/bash
############################################################################
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2009 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2009 Alexander Shaduri <ashaduri 'at' gmail.com>
# License: See LICENSE_whatever.txt file
############################################################################
# (C) 2008 - 2022 Alex Butcher <alex dot butcher 'at' assursys.co.uk>
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
if [ "$1" = "-V" ]; then
smartctl -V 2>&1
@@ -21,7 +21,7 @@ if [ "$device" = "" ]; then
exit 1;
fi
dev_base="`basename \"$device\"`"
dev_base=$(basename "$device")
out_file=/var/run/smart-"$dev_base"
cat "$out_file"
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

+63
View File
@@ -0,0 +1,63 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Generate files
configure_file("gsmartcontrol.appdata.in.xml" "gsmartcontrol.appdata.xml" ESCAPE_QUOTES @ONLY)
configure_file("gsmartcontrol.in.desktop" "gsmartcontrol.desktop" ESCAPE_QUOTES @ONLY)
configure_file("gsmartcontrol-root.in.sh" "gsmartcontrol-root.sh" ESCAPE_QUOTES @ONLY)
configure_file("org.gsmartcontrol.in.policy" "org.gsmartcontrol.policy" ESCAPE_QUOTES @ONLY)
# Install app icons
if (NOT WIN32)
foreach(dir 16 22 24 32 48 64 128 256)
install(FILES "${dir}/gsmartcontrol.png"
DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/${dir}x${dir}/apps/")
endforeach()
# Don't run update-icon-cache, cpack is mostly for packaging.
# install(CODE "execute_process (COMMAND gtk-update-icon-cache-3.0 -t -f \"@CMAKE_INSTALL_DATADIR@/icons/hicolor\")")
endif()
if (WIN32)
# .ico file
install(FILES gsmartcontrol.ico DESTINATION .)
endif()
set (DATA_ICONS
icons/drive-optical.png
icons/drive-harddisk.png
icons/drive-removable-media-usb.png
)
# Install internal icons
if (WIN32)
install(FILES ${DATA_ICONS} DESTINATION icons)
else()
install(FILES ${DATA_ICONS}
DESTINATION "${CMAKE_INSTALL_DATADIR}/gsmartcontrol/icons")
endif()
# Desktop file
if (NOT WIN32)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol.desktop"
DESTINATION "${CMAKE_INSTALL_DATADIR}/applications/")
# Appdata file
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol.appdata.xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo/")
# PolKit file
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.gsmartcontrol.policy"
DESTINATION "${CMAKE_INSTALL_DATADIR}/polkit-1/actions/")
# Man pages
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
install(FILES "man1/gsmartcontrol.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" RENAME "gsmartcontrol-root.1")
# Scripts (this goes to bin, not sbin, as it doesn't require root privileges before running)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/gsmartcontrol-root.sh" TYPE BIN RENAME "gsmartcontrol-root")
endif()
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
png_name="gsmartcontrol.png"
# needs imagemagick
convert 16/$png_name 22/$png_name 24/$png_name 32/$png_name \
48/$png_name 64/$png_name 128/$png_name 256/$png_name gsmartcontrol.ico
+33
View File
@@ -0,0 +1,33 @@
/******************************************************************************
License: GNU General Public License v3.0 only
Copyright:
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
******************************************************************************/
// This file is for generating documentation only. Do NOT include it.
/// \file
/// \author Alexander Shaduri
/**
\mainpage GSmartControl Index
\section intro_section Introduction
This is GSmartControl internal documentation.
*/
// Group definitions and titles.
/**
\addtogroup applib Application-Specific Components
\addtogroup applib_examples Examples of Application-Specific Components
\addtogroup hz HZ Common System Components
\addtogroup hz_examples Examples for HZ Common System Components
\addtogroup libdebug LibDebug Flexible Debug Logging
\addtogroup libdebug_examples Examples for LibDebug Flexible Debug Logging
\addtogroup rconfig Resource Manager-Based Configuration
\addtogroup rconfig_examples Examples for Resource Manager-Based Configuration
\addtogroup gsc GSmartControl Application
*/
+168
View File
@@ -0,0 +1,168 @@
#!/bin/bash
###############################################################################
# License: Zlib
# Copyright:
# (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Run gsmartcontrol with root, asking for root password first.
# export GSMARTCONTROL_SU to override a su command (e.g. "kdesu -c").
EXEC_BIN="@CMAKE_INSTALL_FULL_SBINDIR@/gsmartcontrol";
program_name="gsmartcontrol"
# Preserve quotes in arguments
final_args_quoted="";
for i in "$@";do
final_args_quoted="$final_args_quoted \"${i//\"/\\\"}\"";
done;
DESKTOP="auto";
# Compatibility with old syntax:
# gsmartcontrol-root [<desktop> [program_options]]
if [ "$1" == "auto" ] || [ "$1" == "kde" ] || [ "$1" == "gnome" ] || [ "$1" == "other" ]; then
DESKTOP="$1";
shift; # remove $1
else
# New syntax:
# gsmartcontrol-root [--desktop=<auto|kde|gnome|other>] [program_options]
for arg in "$@"; do
case $arg in
--desktop=*)
DESKTOP="${arg#*=}";
final_args_quoted="${final_args_quoted/\"$arg\"/}";
;;
*)
# unknown option
;;
esac
done
fi
if [ "$DESKTOP" != "auto" ] && [ "$DESKTOP" != "kde" ] && \
[ "$DESKTOP" != "gnome" ] && [ "$DESKTOP" != "other" ]; then
echo "Usage: $0 [--desktop=<auto|kde|gnome|other>] [<${program_name}_options>]";
exit 1;
fi
# Auto-detect current desktop if auto was specified.
if [ "$DESKTOP" = "auto" ]; then
# KDE_SESSION_UID is present on kde3 and kde4.
# Note that it may be empty (but still set)
if [ "${KDE_SESSION_UID+set}" = "set" ]; then
DESKTOP="kde";
# same with gnome
elif [ "${GNOME_DESKTOP_SESSION_ID+set}" = "set" ]; then
DESKTOP="gnome";
else
DESKTOP="other";
fi
fi
# echo $DESKTOP;
# They're basically the same, only the order is different.
# pkexec is for PolKit.
# sux requires xterm to ask for the password.
# xdg-su is basically like this script, except worse :)
# su-to-root is a debian/ubuntu official method (although gksu is available).
gnome_sus="pkexec su-to-root gnomesu gksu kdesu beesu xdg-su sux";
kde_sus="pkexec su-to-root kdesu gnomesu gksu beesu xdg-su sux";
other_sus="$gnome_sus";
candidates="";
found_su=""
if [ "$DESKTOP" = "gnome" ]; then
candidates="$gnome_sus";
elif [ "$DESKTOP" = "kde" ]; then
candidates="$kde_sus";
elif [ "$DESKTOP" = "other" ]; then
candidates="$other_sus";
fi
if [ "$GSMARTCONTROL_SU" = "" ]; then
for subin in $candidates; do
which "$subin" &>/dev/null
if [ $? -eq 0 ]; then
found_su="$subin";
break;
fi
done
if [ "$found_su" = "" ]; then
xmessage "Error launching ${program_name}: No suitable su mechanism found.
Try installing PolKit, kdesu, gnomesu, gksu, beesu or sux first.";
exit 1;
fi
fi
# gnomesu and gksu (but not kdesu, not sure about others) fail to adopt
# root's PATH. Since the user's PATH may not contain /usr/sbin (with smartctl)
# on some distributions (e.g. mandriva), add it manually. We also add
# /usr/local/sbin, since that's the default location of custom-compiled smartctl.
# Add these directories _before_ existing PATH, so that the user is not
# tricked into running it from some other path (we're running as root with
# the user's env after all).
# Add sbindir as well (freebsd seems to require it).
# Note that beesu won't show a GUI login box if /usr/sbin is before /usr/bin,
# so add it first as well.
EXTRA_PATHS="/usr/bin:/usr/sbin:/usr/local/sbin:@CMAKE_INSTALL_FULL_SBINDIR@";
export PATH="$EXTRA_PATHS:$PATH"
# echo $found_su;
# Examples:
# gnomesu -c 'gsmartcontrol --no-scan'
# kdesu -c 'gsmartcontrol --no-scan'
# beesu -P 'gsmartcontrol --no-scan'
# su-to-root -X -c 'gsmartcontrol --no-scan'
# xterm -e sux -c 'gsmartcontrol --no-scan' # sux asks for password in a terminal
full_cmd="";
if [ "$GSMARTCONTROL_SU" != "" ]; then
full_cmd="$GSMARTCONTROL_SU '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "pkexec" ]; then
if [ "$GDK_SCALE" != "" ]; then
final_args_quoted="$final_args_quoted --gdk-scale='$GDK_SCALE'"
fi
if [ "$GDK_DPI_SCALE" != "" ]; then
final_args_quoted="$final_args_quoted --gdk-dpi-scale='$GDK_DPI_SCALE'"
fi
full_cmd="pkexec --disable-internal-agent $EXEC_BIN $final_args_quoted";
elif [ "$found_su" = "sux" ]; then
full_cmd="xterm -e sux -c '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "gksu" ]; then
full_cmd="$found_su '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "beesu" ]; then
full_cmd="$found_su -P '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "su-to-root" ]; then
full_cmd="$found_su -X -c '$EXEC_BIN $final_args_quoted'";
else # gnomesu, kdesu, xdg-su
full_cmd="$found_su -c '$EXEC_BIN $final_args_quoted'";
fi
# echo $full_cmd
eval "$full_cmd"
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>gsmartcontrol</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0</project_license>
<name>GSmartControl</name>
<summary>Hard Disk and SSD Health Inspection</summary>
<description>
<p>
GSmartControl is a graphical user interface for smartctl, which is a tool for
querying and controlling SMART (Self-Monitoring, Analysis, and Reporting
Technology) data in hard disk and solid-state drives. It allows you to inspect
the drive's SMART data to determine its health, as well as run various tests
on it.
</p>
</description>
<launchable type="desktop-id">gsmartcontrol.desktop</launchable>
<url type="homepage">https://gsmartcontrol.shaduri.dev</url>
<screenshots>
<screenshot type="default">
<caption>Main window</caption>
<image>https://gsmartcontrol.shaduri.dev/screenshots/main_ok.png</image>
</screenshot>
<screenshot>
<caption>Drive identity information</caption>
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_identity.png</image>
</screenshot>
<screenshot>
<caption>Attribute list of a failing drive</caption>
<image>https://gsmartcontrol.shaduri.dev/screenshots/info_failing.png</image>
</screenshot>
</screenshots>
</component>
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

+35
View File
@@ -0,0 +1,35 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
[Desktop Entry]
# desktop file version
Version=1.0
Type=Application
Categories=System;Monitor;
Name=GSmartControl
# short description, usually shown in parentheses after Name
GenericName=Hard Disk and SSD Health Inspection
GenericName[fr]=Inspecteur de santé de disque dur et de SSD
# tooltip
Comment=Monitor and control SMART data on hard disk and solid-state drives
Comment[fr]=Surveille et contrôle les données SMART des disques durs et des SSD
# If it's a name only, it looks for "name.[png|xpm]" file in
# $XDG_DATA_DIRS/icons.
# An absolute file path is also supported.
Icon=gsmartcontrol
# Run with root permissions. This should work with newer GNOME too.
# It _should_ work with kde, but it hangs on mine, so use plain kdesu.
#X-KDE-SubstituteUID=true
#X-KDE-RootOnly=true
# Run with root permissions.
Exec="@CMAKE_INSTALL_FULL_BINDIR@/gsmartcontrol-root"
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1,16 +1,16 @@
.TH GSmartControl "1" "" "gsmartcontrol " "User Commands"
.SH NAME
GSmartControl \- Hard disk drive health inspection tool
GSmartControl \- Hard disk drive and SSD health inspection tool
.SH SYNOPSIS
\fBgsmartcontrol\fP [OPTIONS]
\fBgsmartcontrol\-root\fP [\fI<desktop>\fP [OPTIONS]]
\fBgsmartcontrol\-root\fP [--desktop=\fI<desktop>\fP] [OPTIONS]
.SH DESCRIPTION
\fBGSmartControl\fP is a graphical user interface for smartctl (from
smartmontools), which is a tool for querying and controlling SMART
(Self-Monitoring, Analysis, and Reporting Technology) data on modern hard disk
drives. It allows you to inspect the drive's SMART data to determine its
health, as well as run various tests on it.
and solid-state drives. It allows you to inspect the drive's SMART data to
determine its health, as well as run various tests on it.
.PP
This manual page documents briefly the \fBgsmartcontrol\fP and
\fBgsmartcontrol\-root\fP commands.
@@ -37,7 +37,7 @@ Show logging options
.SS "Application Options:"
.TP
\fB\-l\fP, \fB\-\-no\-locale\fP
Disable locale
Don't use system locale
.TP
\fB\-V\fP, \fB\-\-version\fP
Display version information
@@ -45,14 +45,18 @@ Display version information
\fB\-\-no\-scan\fP
Don't scan devices on startup
.TP
\fB\-\-no\-hide\-tabs\fP
Don't hide non\-identity tabs when SMART is disabled. Useful for debugging.
.TP
\fB\-\-add\-virtual\fP
Load smartctl data from file, creating a virtual drive
Load smartctl data from file, creating a virtual drive. You
can specify this option multiple times.
.TP
\fB\-\-add\-device\fP
Add this device to device list. Useful with \fB\-\-no\-scan\fP to list certain drives only.
Add this device to device list. The format of the device is
\fI<device>::<type>::<extra_args>\fP, where type and extra_args are optional.
This option is useful with \fB\-\-no\-scan\fP to list certain drives only. You
can specify this option multiple times. Example:\fR
.nf
\-\-add\-device /dev/sda \-\-add\-device /dev/twa0::3ware,2 \-\-add\-device '/dev/sdb::::-T permissive'
.fi
.TP
\fB\-\-display\fP=\fIDISPLAY\fP
X display to use
@@ -67,8 +71,8 @@ Disable logging; same as \fB\-\-verbosity\-level\fP 0
Set verbosity level [0\-5]
.PP
.SH COPYRIGHT
Copyright \(co 2008 \- 2009 Alexander Shaduri <ashaduri \'at\' gmail.com>
Copyright \(co 2008 \- 2021 Alexander Shaduri <ashaduri@gmail.com>
.PP
.SH AUTHOR
This manual page was originally written by Giuseppe Iuculano
<giuseppe@iuculano.it>, for the Debian project.
<giuseppe@iuculano.it> for the Debian project.
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
License: BSD Zero Clause License file
Copyright:
(C) 2008 - 2021 GSmartControl developers
-->
<policyconfig>
<action id="org.gsmartcontrol">
<message>Authentication is required to run GSmartControl</message>
<icon_name>gsmartcontrol</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">@CMAKE_INSTALL_FULL_SBINDIR@/gsmartcontrol</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>
+73
View File
@@ -0,0 +1,73 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 - 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Disable all warnings
if (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang
OR ${CMAKE_CXX_COMPILER_ID} STREQUAL GNU
OR ${CMAKE_CXX_COMPILER_ID} STREQUAL AppleClang)
add_compile_options(-w)
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
add_compile_options(/w)
endif()
find_package(PkgConfig REQUIRED) # pkg_check_modules()
# Gtkmm.
# Don't make it REQUIRED, we may want to build only the parsers
pkg_check_modules(Gtkmm REQUIRED IMPORTED_TARGET GLOBAL "gtkmm-3.0>=3.0")
add_library(app_gtkmm_interface INTERFACE)
target_link_libraries(app_gtkmm_interface
INTERFACE
PkgConfig::Gtkmm
)
target_compile_definitions(app_gtkmm_interface
INTERFACE
ENABLE_GLIB=1
ENABLE_GLIBMM=1
# For porting to GTK4
# GTK_DISABLE_DEPRECATED=1
# GDK_DISABLE_DEPRECATED=1
# GTKMM_DISABLE_DEPRECATED=1
# GDKMM_DISABLE_DEPRECATED=1
# GLIBMM_DISABLE_DEPRECATED=1
# GIOMM_DISABLE_DEPRECATED=1
)
# Support pre-C++17 glibmm with throw(...) exception specifications
pkg_check_modules(Glibmm "glibmm-2.4")
if ("${Glibmm_VERSION}" VERSION_LESS "2.50.1")
target_compile_definitions(app_gtkmm_interface INTERFACE "APP_GLIBMM_USES_THROW")
message(STATUS "Enabling old glibmm throw(...) workaround")
endif()
# Gettext libintl
find_package(Intl REQUIRED)
add_library(app_gettext_interface INTERFACE)
if (Intl_INCLUDE_DIRS)
target_include_directories(app_gettext_interface
SYSTEM INTERFACE
${Intl_INCLUDE_DIRS}
)
endif()
if (Intl_LIBRARIES)
target_link_libraries(app_gettext_interface
INTERFACE
${Intl_LIBRARIES}
)
endif()
# Gettext binaries and macros.
# See https://cmake.org/cmake/help/v3.15/module/FindGettext.html
# find_package(Gettext REQUIRED)
add_subdirectory(catch2)
add_subdirectory(nlohmann_json)
add_subdirectory(whereami)
add_subdirectory(tl_expected)
+22
View File
@@ -0,0 +1,22 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
#add_subdirectory(Catch2)
add_library(Catch2 INTERFACE)
# Relative sources are allowed only since cmake 3.13.
target_sources(Catch2 INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/Catch2/single_include/catch2/catch.hpp
)
target_include_directories(Catch2
SYSTEM INTERFACE
"${CMAKE_SOURCE_DIR}/dependencies/catch2/Catch2/single_include"
)
+25
View File
@@ -0,0 +1,25 @@
---
AccessModifierOffset: '-4'
AlignEscapedNewlines: Left
AllowAllConstructorInitializersOnNextLine: 'true'
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
DerivePointerAlignment: 'false'
FixNamespaceComments: 'true'
IncludeBlocks: Regroup
IndentCaseLabels: 'false'
IndentPPDirectives: AfterHash
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
SpaceBeforeCtorInitializerColon: 'false'
SpaceInEmptyParentheses: 'false'
SpacesInParentheses: 'true'
Standard: Cpp11
TabWidth: '4'
UseTab: Never
...
+22
View File
@@ -0,0 +1,22 @@
# This sets the default behaviour, overriding core.autocrlf
* text=auto
# All source files should have unix line-endings in the repository,
# but convert to native line-endings on checkout
*.cpp text
*.h text
*.hpp text
# Windows specific files should retain windows line-endings
*.sln text eol=crlf
# Keep executable scripts with LFs so they can be run after being
# checked out on Windows
*.py text eol=lf
# Keep the single include header with LFs to make sure it is uploaded,
# hashed etc with LF
single_include/**/*.hpp eol=lf
# Also keep the LICENCE file with LFs for the same reason
LICENCE.txt eol=lf
+31
View File
@@ -0,0 +1,31 @@
*.build
*.pbxuser
*.mode1v3
*.ncb
*.suo
Debug
Release
*.user
*.xcuserstate
.DS_Store
xcuserdata
CatchSelfTest.xcscheme
Breakpoints.xcbkptlist
projects/VS2010/TestCatch/_UpgradeReport_Files/
projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters
projects/VisualStudio/TestCatch/UpgradeLog.XML
projects/CMake/.idea
projects/CMake/cmake-build-debug
UpgradeLog.XML
Resources/DWARF
projects/Generated
*.pyc
DerivedData
*.xccheckout
Build
.idea
.vs
cmake-build-*
benchmark-dir
.conan/test_package/build
bazel-*
+37
View File
@@ -0,0 +1,37 @@
<a id="top"></a>
![catch logo](artwork/catch2-logo-small.png)
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=v2.x)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/v2.x/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/6JUH8Eybx4CtvkJS)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.13.10/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!
If you've been using an earlier version of Catch, please see the
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
before moving to Catch2. You might also like to read [this blog post](https://levelofindirection.com/blog/catch2-released.html) for more details.
## What's the Catch?
Catch2 is a multi-paradigm test framework for C++. which also supports
Objective-C (and maybe C).
It is primarily distributed as a single header file, although certain
extensions may require additional headers.
## How to use it
This documentation comprises these three parts:
* [Why do we need yet another C++ Test Framework?](docs/why-catch.md#top)
* [Tutorial](docs/tutorial.md#top) - getting started
* [Reference section](docs/Readme.md#top) - all the details
## More
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
* See [who else is using Catch2](docs/opensource-users.md#top)
+206
View File
@@ -0,0 +1,206 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
Catch
-----
This module defines a function to help use the Catch test framework.
The :command:`catch_discover_tests` discovers tests by asking the compiled test
executable to enumerate its tests. This does not require CMake to be re-run
when tests change. However, it may not work in a cross-compiling environment,
and setting test properties is less convenient.
This command is intended to replace use of :command:`add_test` to register
tests, and will create a separate CTest test for each Catch test case. Note
that this is in some cases less efficient, as common set-up and tear-down logic
cannot be shared by multiple test cases executing in the same instance.
However, it provides more fine-grained pass/fail information to CTest, which is
usually considered as more beneficial. By default, the CTest test name is the
same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
.. command:: catch_discover_tests
Automatically add tests with CTest by querying the compiled test executable
for available tests::
catch_discover_tests(target
[TEST_SPEC arg1...]
[EXTRA_ARGS arg1...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
[PROPERTIES name1 value1...]
[TEST_LIST var]
[REPORTER reporter]
[OUTPUT_DIR dir]
[OUTPUT_PREFIX prefix}
[OUTPUT_SUFFIX suffix]
)
``catch_discover_tests`` sets up a post-build command on the test executable
that generates the list of tests by parsing the output from running the test
with the ``--list-test-names-only`` argument. This ensures that the full
list of tests is obtained. Since test discovery occurs at build time, it is
not necessary to re-run CMake when the list of tests changes.
However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
in order to function in a cross-compiling environment.
Additionally, setting properties on tests is somewhat less convenient, since
the tests are not available at CMake time. Additional test properties may be
assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
more fine-grained test control is needed, custom content may be provided
through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
directory property. The set of discovered tests is made accessible to such a
script via the ``<target>_TESTS`` variable.
The options are:
``target``
Specifies the Catch executable, which must be a known CMake executable
target. CMake will substitute the location of the built executable when
running the test.
``TEST_SPEC arg1...``
Specifies test cases, wildcarded test cases, tags and tag expressions to
pass to the Catch executable with the ``--list-test-names-only`` argument.
``EXTRA_ARGS arg1...``
Any extra arguments to pass on the command line to each test case.
``WORKING_DIRECTORY dir``
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
``TEST_PREFIX prefix``
Specifies a ``prefix`` to be prepended to the name of each discovered test
case. This can be useful when the same test executable is being used in
multiple calls to ``catch_discover_tests()`` but with different
``TEST_SPEC`` or ``EXTRA_ARGS``.
``TEST_SUFFIX suffix``
Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
be specified.
``PROPERTIES name1 value1...``
Specifies additional properties to be set on all tests discovered by this
invocation of ``catch_discover_tests``.
``TEST_LIST var``
Make the list of tests available in the variable ``var``, rather than the
default ``<target>_TESTS``. This can be useful when the same test
executable is being used in multiple calls to ``catch_discover_tests()``.
Note that this variable is only available in CTest.
``REPORTER reporter``
Use the specified reporter when running the test case. The reporter will
be passed to the Catch executable as ``--reporter reporter``.
``OUTPUT_DIR dir``
If specified, the parameter is passed along as
``--out dir/<test_name>`` to Catch executable. The actual file name is the
same as the test name. This should be used instead of
``EXTRA_ARGS --out foo`` to avoid race conditions writing the result output
when using parallel test execution.
``OUTPUT_PREFIX prefix``
May be used in conjunction with ``OUTPUT_DIR``.
If specified, ``prefix`` is added to each output file name, like so
``--out dir/prefix<test_name>``.
``OUTPUT_SUFFIX suffix``
May be used in conjunction with ``OUTPUT_DIR``.
If specified, ``suffix`` is added to each output file name, like so
``--out dir/<test_name>suffix``. This can be used to add a file extension to
the output e.g. ".xml".
#]=======================================================================]
#------------------------------------------------------------------------------
function(catch_discover_tests TARGET)
cmake_parse_arguments(
""
""
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES"
${ARGN}
)
if(NOT _WORKING_DIRECTORY)
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT _TEST_LIST)
set(_TEST_LIST ${TARGET}_TESTS)
endif()
## Generate a unique name based on the extra arguments
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}")
string(SUBSTRING ${args_hash} 0 7 args_hash)
# Define rule to generate test list for aforementioned test executable
set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
get_property(crosscompiling_emulator
TARGET ${TARGET}
PROPERTY CROSSCOMPILING_EMULATOR
)
add_custom_command(
TARGET ${TARGET} POST_BUILD
BYPRODUCTS "${ctest_tests_file}"
COMMAND "${CMAKE_COMMAND}"
-D "TEST_TARGET=${TARGET}"
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
-D "TEST_EXECUTOR=${crosscompiling_emulator}"
-D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
-D "TEST_SPEC=${_TEST_SPEC}"
-D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
-D "TEST_PROPERTIES=${_PROPERTIES}"
-D "TEST_PREFIX=${_TEST_PREFIX}"
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
-D "TEST_LIST=${_TEST_LIST}"
-D "TEST_REPORTER=${_REPORTER}"
-D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}"
-D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}"
-D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}"
-D "CTEST_FILE=${ctest_tests_file}"
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
VERBATIM
)
file(WRITE "${ctest_include_file}"
"if(EXISTS \"${ctest_tests_file}\")\n"
" include(\"${ctest_tests_file}\")\n"
"else()\n"
" add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
"endif()\n"
)
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
# Add discovered tests to directory TEST_INCLUDE_FILES
set_property(DIRECTORY
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
)
else()
# Add discovered tests as directory TEST_INCLUDE_FILE if possible
get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
if (NOT ${test_include_file_set})
set_property(DIRECTORY
PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
)
else()
message(FATAL_ERROR
"Cannot set more than one TEST_INCLUDE_FILE"
)
endif()
endif()
endfunction()
###############################################################################
set(_CATCH_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file"
)
+135
View File
@@ -0,0 +1,135 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
set(prefix "${TEST_PREFIX}")
set(suffix "${TEST_SUFFIX}")
set(spec ${TEST_SPEC})
set(extra_args ${TEST_EXTRA_ARGS})
set(properties ${TEST_PROPERTIES})
set(reporter ${TEST_REPORTER})
set(output_dir ${TEST_OUTPUT_DIR})
set(output_prefix ${TEST_OUTPUT_PREFIX})
set(output_suffix ${TEST_OUTPUT_SUFFIX})
set(script)
set(suite)
set(tests)
function(add_command NAME)
set(_args "")
# use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
math(EXPR _last_arg ${ARGC}-1)
foreach(_n RANGE 1 ${_last_arg})
set(_arg "${ARGV${_n}}")
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else()
set(_args "${_args} ${_arg}")
endif()
endforeach()
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()
# Run test executable to get list of available tests
if(NOT EXISTS "${TEST_EXECUTABLE}")
message(FATAL_ERROR
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
)
endif()
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
OUTPUT_VARIABLE output
RESULT_VARIABLE result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
)
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
if(${result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
)
elseif(${result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${result}\n"
" Output: ${output}\n"
)
endif()
string(REPLACE "\n" ";" output "${output}")
# Run test executable to get list of available reporters
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-reporters
OUTPUT_VARIABLE reporters_output
RESULT_VARIABLE reporters_result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
)
if(${reporters_result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no reporters!\n"
)
elseif(${reporters_result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${reporters_result}\n"
" Output: ${reporters_output}\n"
)
endif()
string(FIND "${reporters_output}" "${reporter}" reporter_is_valid)
if(reporter AND ${reporter_is_valid} EQUAL -1)
message(FATAL_ERROR
"\"${reporter}\" is not a valid reporter!\n"
)
endif()
# Prepare reporter
if(reporter)
set(reporter_arg "--reporter ${reporter}")
endif()
# Prepare output dir
if(output_dir AND NOT IS_ABSOLUTE ${output_dir})
set(output_dir "${TEST_WORKING_DIR}/${output_dir}")
if(NOT EXISTS ${output_dir})
file(MAKE_DIRECTORY ${output_dir})
endif()
endif()
# Parse output
foreach(line ${output})
set(test ${line})
# Escape characters in test case names that would be parsed by Catch2
set(test_name ${test})
foreach(char , [ ])
string(REPLACE ${char} "\\${char}" test_name ${test_name})
endforeach(char)
# ...add output dir
if(output_dir)
string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name})
set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}")
endif()
# ...and add to script
add_command(add_test
"${prefix}${test}${suffix}"
${TEST_EXECUTOR}
"${TEST_EXECUTABLE}"
"${test_name}"
${extra_args}
"${reporter_arg}"
"${output_dir_arg}"
)
add_command(set_tests_properties
"${prefix}${test}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
${properties}
)
list(APPEND tests "${prefix}${test}${suffix}")
endforeach()
# Create a list of all discovered tests, which users may use to e.g. set
# properties on the tests
add_command(set ${TEST_LIST} ${tests})
# Write CTest script
file(WRITE "${CTEST_FILE}" "${script}")
@@ -0,0 +1,252 @@
#==================================================================================================#
# supported macros #
# - TEST_CASE, #
# - TEMPLATE_TEST_CASE #
# - SCENARIO, #
# - TEST_CASE_METHOD, #
# - CATCH_TEST_CASE, #
# - CATCH_TEMPLATE_TEST_CASE #
# - CATCH_SCENARIO, #
# - CATCH_TEST_CASE_METHOD. #
# #
# Usage #
# 1. make sure this module is in the path or add this otherwise: #
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
# 2. make sure that you've enabled testing option for the project by the call: #
# enable_testing() #
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
# project(testing_target) #
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
# enable_testing() #
# #
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
# #
# file(GLOB SOURCE_FILES "*.cpp") #
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
# #
# include(ParseAndAddCatchTests) #
# ParseAndAddCatchTests(${PROJECT_NAME}) #
# #
# The following variables affect the behavior of the script: #
# #
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
# -- enables debug messages #
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
# -- adds fixture class name to the test name #
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
# -- adds cmake target name to the test name #
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
# #
# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way #
# a test should be run. For instance to use test MPI, one can write #
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
# just before calling this ParseAndAddCatchTests function #
# #
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
# command. For example, to include successful tests in the output, one can write #
# set(AdditionalCatchParameters --success) #
# #
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
# file in the target is set, and contains the list of the tests extracted from that target, or #
# from that file. This is useful, for example to add further labels or properties to the tests. #
# #
#==================================================================================================#
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
endif()
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
function(ParseAndAddCatchTests_PrintDebugMessage)
if(PARSE_CATCH_TESTS_VERBOSE)
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
endif()
endfunction()
# This removes the contents between
# - block comments (i.e. /* ... */)
# - full line comments (i.e. // ... )
# contents have been read into '${CppCode}'.
# !keep partial line comments
function(ParseAndAddCatchTests_RemoveComments CppCode)
string(ASCII 2 CMakeBeginBlockComment)
string(ASCII 3 CMakeEndBlockComment)
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
endfunction()
# Worker function
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
return()
endif()
# According to CMake docs EXISTS behavior is well-defined only for full paths.
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
if(NOT EXISTS ${SourceFile})
message(WARNING "Cannot find source file: ${SourceFile}")
return()
endif()
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
# Remove block and fullline comments
ParseAndAddCatchTests_RemoveComments(Contents)
# Find definition of test names
# https://regex101.com/r/JygOND/1
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([ \t\n]*\"[^\"]*\"[ \t\n]*(,[ \t\n]*\"[^\"]*\")?(,[ \t\n]*[^\,\)]*)*\\)[ \t\n]*\{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
set_property(
DIRECTORY
APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
)
endif()
# check CMP0110 policy for new add_test() behavior
if(POLICY CMP0110)
cmake_policy(GET CMP0110 _cmp0110_value) # new add_test() behavior
else()
# just to be thorough explicitly set the variable
set(_cmp0110_value)
endif()
foreach(TestName ${Tests})
# Strip newlines
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
# Get test type and fixture if applicable
string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
# Get string parts of test definition
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
# Strip wrapping quotation marks
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
# Validate that a test name and tags have been provided
list(LENGTH TestStrings TestStringsLength)
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
endif()
# Assign name and tags
list(GET TestStrings 0 Name)
if("${TestType}" STREQUAL "SCENARIO")
set(Name "Scenario: ${Name}")
endif()
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
set(CTestName "${TestFixture}:${Name}")
else()
set(CTestName "${Name}")
endif()
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
set(CTestName "${TestTarget}:${CTestName}")
endif()
# add target to labels to enable running all tests added from this target
set(Labels ${TestTarget})
if(TestStringsLength EQUAL 2)
list(GET TestStrings 1 Tags)
string(TOLOWER "${Tags}" Tags)
# remove target from labels if the test is hidden
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
list(REMOVE_ITEM Labels ${TestTarget})
endif()
string(REPLACE "]" ";" Tags "${Tags}")
string(REPLACE "[" "" Tags "${Tags}")
else()
# unset tags variable from previous loop
unset(Tags)
endif()
list(APPEND Labels ${Tags})
set(HiddenTagFound OFF)
foreach(label ${Labels})
string(REGEX MATCH "^!hide|^\\." result ${label})
if(result)
set(HiddenTagFound ON)
break()
endif(result)
endforeach(label)
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
else()
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
if(Labels)
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
endif()
# Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name})
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary,
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
# And properly introduced in 3.19 with the CMP0110 policy
if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18")
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to NEW, no need for add_test(\"\") workaround")
else()
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to OLD adding \"\" for add_test() workaround")
set(CTestName "\"${CTestName}\"")
endif()
# Handle template test cases
if("${TestTypeAndFixture}" MATCHES ".*TEMPLATE_.*")
set(Name "${Name} - *")
endif()
# Add the test and set its properties
add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
set_tests_properties("${CTestName}" PROPERTIES DISABLED ON)
else()
set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
LABELS "${Labels}")
endif()
set_property(
TARGET ${TestTarget}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
set_property(
SOURCE ${SourceFile}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
endif()
endforeach()
endfunction()
# entry point
function(ParseAndAddCatchTests TestTarget)
message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES)
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
foreach(SourceFile ${SourceFiles})
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
endforeach()
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
endfunction()
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
Catch2 v2.13.10.
https://github.com/catchorg/Catch2
+18
View File
@@ -0,0 +1,18 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
add_library(nlohmann_json INTERFACE)
# Relative sources are allowed only since cmake 3.13.
target_sources(nlohmann_json INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/nlohmann/json.hpp
)
target_include_directories(nlohmann_json
SYSTEM INTERFACE
"${CMAKE_SOURCE_DIR}/dependencies/nlohmann_json"
)
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
JSON for Modern C++
version 3.9.1
https://github.com/nlohmann/json
+20
View File
@@ -0,0 +1,20 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2024 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
add_library(tl_expected INTERFACE)
# Relative sources are allowed only since cmake 3.13.
target_sources(tl_expected INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/expected/include/tl/expected.hpp
)
target_include_directories(tl_expected
SYSTEM INTERFACE
"${CMAKE_SOURCE_DIR}/dependencies/tl_expected/expected/include"
)
+10
View File
@@ -0,0 +1,10 @@
os:
- Visual Studio 2015
- Visual Studio 2017
- Visual Studio 2019
- Visual Studio 2022
build_script:
- cmake -Bbuild -S.
- cmake --build build
- cmake --build build --target RUN_TESTS
+1
View File
@@ -0,0 +1 @@
BasedOnStyle: LLVM
@@ -0,0 +1,131 @@
name: CMake
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
std: [11, 14]
cxx: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11]
exclude:
- cxx: g++-4.8
std: 14
- cxx: g++4.9
std: 14
include:
- cxx: g++-4.8
install: sudo apt install g++-4.8
- cxx: g++-4.9
install: sudo apt install g++-4.9
- cxx: g++-5
install: sudo apt install g++-5
- cxx: g++-6
install: sudo apt install g++-6
- cxx: g++-7
install: sudo apt install g++-7
- cxx: g++-8
std: 11
install: sudo apt install g++-8
- cxx: g++-8
std: 14
install: sudo apt install g++-8
- cxx: g++-8
std: 17
install: sudo apt install g++-8
- cxx: g++-9
std: 14
- cxx: g++-9
std: 17
- cxx: g++-10
std: 14
- cxx: g++-10
std: 17
- cxx: g++-11
std: 14
install: sudo apt install g++-11
- cxx: g++-11
std: 17
install: sudo apt install g++-11
- cxx: g++-11
std: 20
install: sudo apt install g++-11
- cxx: clang++-3.5
install: sudo apt install clang-3.5
- cxx: clang++-3.6
install: sudo apt install clang-3.6
- cxx: clang++-3.7
install: sudo apt install clang-3.7
- cxx: clang++-3.8
install: sudo apt install clang-3.8
- cxx: clang++-3.9
install: sudo apt install clang-3.9
- cxx: clang++-4.0
install: sudo apt install clang-4.0
- cxx: clang++-5.0
install: sudo apt install clang-5.0
- cxx: clang++-6.0
install: sudo apt install clang-6.0
- cxx: clang++-7
install: sudo apt install clang-7
- cxx: clang++-8
install: sudo apt install clang-8
- cxx: clang++-9
install: sudo apt install clang-9
- cxx: clang++-10
install: sudo apt install clang-10
- cxx: clang++-11
install: sudo apt install clang-11
- cxx: clang++-6.0
std: 17
install: sudo apt install clang-6.0
- cxx: clang++-7
std: 17
install: sudo apt install clang-7
- cxx: clang++-8
std: 17
install: sudo apt install clang-8
- cxx: clang++-9
std: 17
install: sudo apt install clang-9
- cxx: clang++-10
std: 17
install: sudo apt install clang-10
- cxx: clang++-11
std: 17
install: sudo apt install clang-11
steps:
- uses: actions/checkout@v3
- name: Setup Toolchain
run: |
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ xenial main'
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ xenial universe'
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ bionic main'
sudo apt-add-repository 'deb http://azure.archive.ubuntu.com/ubuntu/ bionic universe'
${{matrix.install}}
- name: Configure CMake
env:
CXX: ${{matrix.cxx}}
run: cmake -B ${{github.workspace}}/build -DCMAKE_CXX_STANDARD=${{matrix.std}}
- name: Build
run: cmake --build ${{github.workspace}}/build
- name: Test
working-directory: ${{github.workspace}}/build
run: cmake --build ${{github.workspace}}/build --target test
@@ -0,0 +1,3 @@
\#*
.\#*
/build/
+268
View File
@@ -0,0 +1,268 @@
language: cpp
dist: xenial
matrix:
include:
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env: COMPILER=g++-5 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env: COMPILER=g++-6 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env: COMPILER=g++-7 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env: COMPILER=g++-8 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env: COMPILER=g++-4.9 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
env: COMPILER=g++-4.8 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.5
- ubuntu-toolchain-r-test
packages:
- clang++-3.5
- libc++-dev
env: COMPILER=clang++-3.5 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.6
- ubuntu-toolchain-r-test
packages:
- clang++-3.6
- libc++-dev
env: COMPILER=clang++-3.6 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- clang++-3.7
- libc++-dev
env: COMPILER=clang++-3.7 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main"
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
- ubuntu-toolchain-r-test
packages:
- clang++-3.8
- libc++-dev
env: COMPILER=clang++-3.8 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main"
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
- ubuntu-toolchain-r-test
packages:
- clang++-3.9
- libc++-dev
env: COMPILER=clang++-3.9 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-4.0
- ubuntu-toolchain-r-test
packages:
- clang++-4.0
- libc++-dev
env: COMPILER=clang++-4.0 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-5.0
- ubuntu-toolchain-r-test
packages:
- clang++-5.0
- libc++-dev
env: COMPILER=clang++-5.0 CXXSTD=11
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-6.0
- ubuntu-toolchain-r-test
packages:
- clang++-6.0
- libc++-dev
env: COMPILER=clang++-6.0 CXXSTD=11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env: COMPILER=g++-5 CXXSTD=14
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env: COMPILER=g++-6 CXXSTD=14
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env: COMPILER=g++-7 CXXSTD=14
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env: COMPILER=g++-8 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.5
- ubuntu-toolchain-r-test
packages:
- clang++-3.5
- libc++-dev
env: COMPILER=clang++-3.5 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.6
- ubuntu-toolchain-r-test
packages:
- clang++-3.6
- libc++-dev
env: COMPILER=clang++-3.6 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- clang++-3.7
- libc++-dev
env: COMPILER=clang++-3.7 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main"
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
- ubuntu-toolchain-r-test
packages:
- clang++-3.8
- libc++-dev
env: COMPILER=clang++-3.8 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- sourceline: "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main"
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
- ubuntu-toolchain-r-test
packages:
- clang++-3.9
- libc++-dev
env: COMPILER=clang++-3.9 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-4.0
- ubuntu-toolchain-r-test
packages:
- clang++-4.0
- libc++-dev
env: COMPILER=clang++-4.0 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-5.0
- ubuntu-toolchain-r-test
packages:
- clang++-5.0
- libc++-dev
env: COMPILER=clang++-5.0 CXXSTD=14
- compiler: clang
addons:
apt:
sources:
- llvm-toolchain-xenial-6.0
- ubuntu-toolchain-r-test
packages:
- clang++-6.0
- libc++-dev
env: COMPILER=clang++-6.0 CXXSTD=14
before_install:
- sudo apt update
- sudo apt install -y apt-transport-https ca-certificates gnupg software-properties-common
- curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | sudo apt-key add -
- sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ xenial main'
- sudo apt update
install:
- if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi
- if [ "$CXX" = "g++" ]; then export CXX="$COMPILER"; fi
- sudo apt install -y cmake
script:
- /usr/bin/cmake -B build -S . "-DCMAKE_CXX_STANDARD=$CXXSTD"
- /usr/bin/cmake --build build
- /usr/bin/cmake --build build --target test
+117
View File
@@ -0,0 +1,117 @@
cmake_minimum_required(VERSION 3.14)
project(tl-expected
HOMEPAGE_URL https://tl.tartanllama.xyz
DESCRIPTION "C++11/14/17 std::expected with functional-style extensions"
VERSION 1.0.0
LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(FetchContent)
include(CTest)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
option(EXPECTED_BUILD_PACKAGE "Build package files as well" ON)
cmake_dependent_option(EXPECTED_BUILD_TESTS
"Enable tl::expected tests" ON
"BUILD_TESTING" OFF)
cmake_dependent_option(EXPECTED_BUILD_PACKAGE_DEB
"Create a DEB" ON
"EXPECTED_BUILD_PACKAGE" OFF)
add_library(expected INTERFACE)
target_include_directories(expected
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
if (NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
add_library(tl::expected ALIAS expected)
endif()
# Installation help
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
INSTALL_DESTINATION "share/cmake/${PROJECT_NAME}")
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT)
install(TARGETS expected
EXPORT ${PROJECT_NAME}-targets
INCLUDES DESTINATION "${CMAKE_INSTALL_DATADIR}")
install(EXPORT ${PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
NAMESPACE tl::
FILE "${PROJECT_NAME}-targets.cmake")
install(FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}")
install(DIRECTORY "include/" TYPE INCLUDE)
if(EXPECTED_BUILD_TESTS)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CATCH_INSTALL_HELPERS OFF)
set(CATCH_BUILD_TESTING OFF)
set(CATCH_INSTALL_DOCS OFF)
FetchContent_Declare(Catch2 URL
https://github.com/catchorg/Catch2/archive/v2.13.10.zip)
FetchContent_MakeAvailable(Catch2)
file(GLOB test-sources CONFIGURE_DEPENDS tests/*.cpp)
list(FILTER test-sources EXCLUDE REGEX "tests/test.cpp")
add_executable(${PROJECT_NAME}-tests "${test-sources}")
target_compile_options(${PROJECT_NAME}-tests PRIVATE
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra>)
target_link_libraries(${PROJECT_NAME}-tests
PRIVATE
Catch2::Catch2
expected)
add_test(NAME tl::expected::tests COMMAND ${PROJECT_NAME}-tests)
endif()
if (NOT EXPECTED_BUILD_PACKAGE)
return()
endif()
list(APPEND source-generators TBZ2 TGZ TXZ ZIP)
if (CMAKE_HOST_WIN32)
list(APPEND binary-generators "WIX")
endif()
if (EXPECTED_BUILD_PACKAGE_DEB)
list(APPEND binary-generators "DEB")
endif()
if (EXPECTED_BUILD_RPM)
list(APPEND binary-generators "RPM")
endif()
set(CPACK_SOURCE_GENERATOR ${source-generators})
set(CPACK_GENERATOR ${binary-generators})
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Sy Brand")
list(APPEND CPACK_SOURCE_IGNORE_FILES /.git/ /build/ .gitignore .DS_Store)
include(CPack)
+121
View File
@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
+76
View File
@@ -0,0 +1,76 @@
# expected
Single header implementation of `std::expected` with functional-style extensions.
[![Documentation SmartStatus](https://readthedocs.org/projects/tl-docs/badge/?version=latest)](https://tl.tartanllama.xyz/en/latest/?badge=latest)
Clang + GCC: [![Linux Build SmartStatus](https://github.com/TartanLlama/expected/actions/workflows/cmake.yml/badge.svg)](https://github.com/TartanLlama/expected/actions/workflows/cmake.yml)
MSVC: [![Windows Build SmartStatus](https://ci.appveyor.com/api/projects/status/k5x00xa11y3s5wsg?svg=true)](https://ci.appveyor.com/project/TartanLlama/expected)
Available on [Vcpkg](https://github.com/microsoft/vcpkg/tree/master/ports/tl-expected) and [Conan](https://github.com/yipdw/conan-tl-expected).
[`std::expected`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf) is proposed as the preferred way to represent object which will either have an expected value, or an unexpected value giving information about why something failed. Unfortunately, chaining together many computations which may fail can be verbose, as error-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `expected` cleaner.
For example, instead of writing this code:
```cpp
std::expected<image,fail_reason> get_cute_cat (const image& img) {
auto cropped = crop_to_cat(img);
if (!cropped) {
return cropped;
}
auto with_tie = add_bow_tie(*cropped);
if (!with_tie) {
return with_tie;
}
auto with_sparkles = make_eyes_sparkle(*with_tie);
if (!with_sparkles) {
return with_sparkles;
}
return add_rainbow(make_smaller(*with_sparkles));
}
```
You can do this:
```cpp
tl::expected<image,fail_reason> get_cute_cat (const image& img) {
return crop_to_cat(img)
.and_then(add_bow_tie)
.and_then(make_eyes_sparkle)
.map(make_smaller)
.map(add_rainbow);
}
```
The interface is the same as `std::expected` as proposed in [p0323r3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf), but the following member functions are also defined. Explicit types are for clarity.
- `map`: carries out some operation on the stored object if there is one.
* `tl::expected<std::size_t,std::error_code> s = exp_string.map(&std::string::size);`
- `map_error`: carries out some operation on the unexpected object if there is one.
* `my_error_code translate_error (std::error_code);`
* `tl::expected<int,my_error_code> s = exp_int.map_error(translate_error);`
- `and_then`: like `map`, but for operations which return a `tl::expected`.
* `tl::expected<ast, fail_reason> parse (const std::string& s);`
* `tl::expected<ast, fail_reason> exp_ast = exp_string.and_then(parse);`
- `or_else`: calls some function if there is no value stored.
* `exp.or_else([] { throw std::runtime_error{"oh no"}; });`
p0323r3 specifies calling `.error()` on an expected value, or using the `*` or `->` operators on an unexpected value, to be undefined behaviour. In this implementation it causes an assertion failure. The implementation of assertions can be overridden by defining the macro `TL_ASSERT(boolean_condition)` before #including <tl/expected.hpp>; by default, `assert(boolean_condition)` from the `<cassert>` header is used. Note that correct code would not rely on these assertions.
### Compiler support
Tested on:
- Linux
* clang++ 3.5, 3.6, 3.7, 3.8, 3.9, 4, 5, 6, 7, 8, 9, 10, 11
* g++ 4.8, 4.9, 5.5, 6.4, 7.5, 8, 9, 10
- Windows
* MSVC 2015, 2017, 2019, 2022
----------
[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)]("http://creativecommons.org/publicdomain/zero/1.0/")
To the extent possible under law, [Sy Brand](https://twitter.com/TartanLlama) has waived all copyright and related or neighboring rights to the `expected` library. This work is published from: United Kingdom.
@@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/tl-expected-targets.cmake")
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
#include <catch2/catch.hpp>
#include <stdexcept>
#define TL_ASSERT(cond) if (!(cond)) { throw std::runtime_error(std::string("assertion failure")); }
#include <tl/expected.hpp>
TEST_CASE("Assertions", "[assertions]") {
tl::expected<int,int> o1 = 42;
REQUIRE_THROWS_WITH(o1.error(), "assertion failure");
tl::expected<int,int> o2 {tl::unexpect, 0};
REQUIRE_THROWS_WITH(*o2, "assertion failure");
struct foo { int bar; };
tl::expected<struct foo,int> o3 {tl::unexpect, 0};
REQUIRE_THROWS_WITH(o3->bar, "assertion failure");
}
+75
View File
@@ -0,0 +1,75 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
TEST_CASE("Simple assignment", "[assignment.simple]") {
tl::expected<int, int> e1 = 42;
tl::expected<int, int> e2 = 17;
tl::expected<int, int> e3 = 21;
tl::expected<int, int> e4 = tl::make_unexpected(42);
tl::expected<int, int> e5 = tl::make_unexpected(17);
tl::expected<int, int> e6 = tl::make_unexpected(21);
e1 = e2;
REQUIRE(e1);
REQUIRE(*e1 == 17);
REQUIRE(e2);
REQUIRE(*e2 == 17);
e1 = std::move(e2);
REQUIRE(e1);
REQUIRE(*e1 == 17);
REQUIRE(e2);
REQUIRE(*e2 == 17);
e1 = 42;
REQUIRE(e1);
REQUIRE(*e1 == 42);
auto unex = tl::make_unexpected(12);
e1 = unex;
REQUIRE(!e1);
REQUIRE(e1.error() == 12);
e1 = tl::make_unexpected(42);
REQUIRE(!e1);
REQUIRE(e1.error() == 42);
e1 = e3;
REQUIRE(e1);
REQUIRE(*e1 == 21);
e4 = e5;
REQUIRE(!e4);
REQUIRE(e4.error() == 17);
e4 = std::move(e6);
REQUIRE(!e4);
REQUIRE(e4.error() == 21);
e4 = e1;
REQUIRE(e4);
REQUIRE(*e4 == 21);
}
TEST_CASE("Assignment deletion", "[assignment.deletion]") {
struct has_all {
has_all() = default;
has_all(const has_all &) = default;
has_all(has_all &&) noexcept = default;
has_all &operator=(const has_all &) = default;
};
tl::expected<has_all, has_all> e1 = {};
tl::expected<has_all, has_all> e2 = {};
e1 = e2;
struct except_move {
except_move() = default;
except_move(const except_move &) = default;
except_move(except_move &&) noexcept(false){};
except_move &operator=(const except_move &) = default;
};
tl::expected<except_move, except_move> e3 = {};
tl::expected<except_move, except_move> e4 = {};
// e3 = e4; should not compile
}
+191
View File
@@ -0,0 +1,191 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
#include <string>
// Old versions of GCC don't have the correct trait names. Could fix them up if needs be.
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
!defined(__clang__))
// nothing for now
#else
TEST_CASE("Triviality", "[bases.triviality]") {
REQUIRE(std::is_trivially_copy_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_copy_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_move_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_move_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_destructible<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_copy_constructible<tl::expected<void,int>>::value);
REQUIRE(std::is_trivially_move_constructible<tl::expected<void,int>>::value);
REQUIRE(std::is_trivially_destructible<tl::expected<void,int>>::value);
{
struct T {
T(const T&) = default;
T(T&&) = default;
T& operator=(const T&) = default;
T& operator=(T&&) = default;
~T() = default;
};
REQUIRE(std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_move_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_destructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&){}
T(T&&) {}
T& operator=(const T&) { return *this; }
T& operator=(T&&) { return *this; }
~T(){}
};
REQUIRE(!std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_move_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_move_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_destructible<tl::expected<T,int>>::value);
}
}
TEST_CASE("Deletion", "[bases.deletion]") {
REQUIRE(std::is_copy_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_destructible<tl::expected<int,int>>::value);
{
struct T {
T()=default;
};
REQUIRE(std::is_default_constructible<tl::expected<T,int>>::value);
}
{
struct T {
T(int){}
};
REQUIRE(!std::is_default_constructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&) = default;
T(T&&) = default;
T& operator=(const T&) = default;
T& operator=(T&&) = default;
~T() = default;
};
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_destructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=delete;
T(T&&)=delete;
T& operator=(const T&)=delete;
T& operator=(T&&)=delete;
};
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_move_assignable<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=delete;
T(T&&)=default;
T& operator=(const T&)=delete;
T& operator=(T&&)=default;
};
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=default;
T(T&&)=delete;
T& operator=(const T&)=default;
T& operator=(T&&)=delete;
};
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
}
{
tl::expected<int, int> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<int, std::string> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<std::string, int> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<std::string, std::string> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
}
#endif
+6
View File
@@ -0,0 +1,6 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
TEST_CASE("Constexpr", "[constexpr]") {
//TODO
}
+134
View File
@@ -0,0 +1,134 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
#include <type_traits>
#include <vector>
#include <string>
struct takes_init_and_variadic {
std::vector<int> v;
std::tuple<int, int> t;
template <class... Args>
takes_init_and_variadic(std::initializer_list<int> l, Args &&... args)
: v(l), t(std::forward<Args>(args)...) {}
};
TEST_CASE("Constructors", "[constructors]") {
{
tl::expected<int,int> e;
REQUIRE(e);
REQUIRE(e == 0);
}
{
tl::expected<int,int> e = tl::make_unexpected(0);
REQUIRE(!e);
REQUIRE(e.error() == 0);
}
{
tl::expected<int,int> e (tl::unexpect, 0);
REQUIRE(!e);
REQUIRE(e.error() == 0);
}
{
tl::expected<int,int> e (tl::in_place, 42);
REQUIRE(e);
REQUIRE(e == 42);
}
{
tl::expected<std::vector<int>,int> e (tl::in_place, {0,1});
REQUIRE(e);
REQUIRE((*e)[0] == 0);
REQUIRE((*e)[1] == 1);
}
{
tl::expected<std::tuple<int,int>,int> e (tl::in_place, 0, 1);
REQUIRE(e);
REQUIRE(std::get<0>(*e) == 0);
REQUIRE(std::get<1>(*e) == 1);
}
{
tl::expected<takes_init_and_variadic,int> e (tl::in_place, {0,1}, 2, 3);
REQUIRE(e);
REQUIRE(e->v[0] == 0);
REQUIRE(e->v[1] == 1);
REQUIRE(std::get<0>(e->t) == 2);
REQUIRE(std::get<1>(e->t) == 3);
}
{
tl::expected<int, int> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<int, std::string> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<std::string, int> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<std::string, std::string> e;
REQUIRE(std::is_default_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_constructible<decltype(e)>::value);
REQUIRE(std::is_move_constructible<decltype(e)>::value);
REQUIRE(std::is_copy_assignable<decltype(e)>::value);
REQUIRE(std::is_move_assignable<decltype(e)>::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(decltype(e))::value);
REQUIRE(!TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(decltype(e))::value);
# if !defined(TL_EXPECTED_GCC49)
REQUIRE(!std::is_trivially_move_constructible<decltype(e)>::value);
REQUIRE(!std::is_trivially_move_assignable<decltype(e)>::value);
# endif
}
{
tl::expected<void,int> e;
REQUIRE(e);
}
{
tl::expected<void,int> e (tl::unexpect, 42);
REQUIRE(!e);
REQUIRE(e.error() == 42);
}
}
+50
View File
@@ -0,0 +1,50 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
#include <memory>
#include <vector>
#include <tuple>
namespace {
struct takes_init_and_variadic {
std::vector<int> v;
std::tuple<int, int> t;
template <class... Args>
takes_init_and_variadic(std::initializer_list<int> l, Args &&... args)
: v(l), t(std::forward<Args>(args)...) {}
};
}
TEST_CASE("Emplace", "[emplace]") {
{
tl::expected<std::unique_ptr<int>,int> e;
e.emplace(new int{42});
REQUIRE(e);
REQUIRE(**e == 42);
}
{
tl::expected<std::vector<int>,int> e;
e.emplace({0,1});
REQUIRE(e);
REQUIRE((*e)[0] == 0);
REQUIRE((*e)[1] == 1);
}
{
tl::expected<std::tuple<int,int>,int> e;
e.emplace(2,3);
REQUIRE(e);
REQUIRE(std::get<0>(*e) == 2);
REQUIRE(std::get<1>(*e) == 3);
}
{
tl::expected<takes_init_and_variadic,int> e = tl::make_unexpected(0);
e.emplace({0,1}, 2, 3);
REQUIRE(e);
REQUIRE(e->v[0] == 0);
REQUIRE(e->v[1] == 1);
REQUIRE(std::get<0>(e->t) == 2);
REQUIRE(std::get<1>(e->t) == 3);
}
}
+830
View File
@@ -0,0 +1,830 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#undef STATIC_REQUIRE
#define STATIC_REQUIRE(e) \
constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \
(void)TOKENPASTE2(rqure, __LINE__); \
REQUIRE(e);
TEST_CASE("Map extensions", "[extensions.map]") {
auto mul2 = [](int a) { return a * 2; };
auto ret_void = [](int a) { (void)a; };
{
tl::expected<int, int> e = 21;
auto ret = e.map(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.map(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).map(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).map(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = e.map(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e = 21;
auto ret = e.map(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).map(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).map(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
// mapping functions which return references
{
tl::expected<int, int> e(42);
auto ret = e.map([](int& i) -> int& { return i; });
REQUIRE(ret);
REQUIRE(ret == 42);
}
}
TEST_CASE("Map error extensions", "[extensions.map_error]") {
auto mul2 = [](int a) { return a * 2; };
auto ret_void = [](int a) { (void)a; };
{
tl::expected<int, int> e = 21;
auto ret = e.map_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.map_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).map_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).map_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = e.map_error(ret_void);
REQUIRE(ret);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.map_error(ret_void);
REQUIRE(ret);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).map_error(ret_void);
REQUIRE(ret);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).map_error(ret_void);
REQUIRE(ret);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map_error(ret_void);
REQUIRE(!ret);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.map_error(ret_void);
REQUIRE(!ret);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map_error(ret_void);
REQUIRE(!ret);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).map_error(ret_void);
REQUIRE(!ret);
}
}
TEST_CASE("And then extensions", "[extensions.and_then]") {
auto succeed = [](int a) { (void)a; return tl::expected<int, int>(21 * 2); };
auto fail = [](int a) { (void)a; return tl::expected<int, int>(tl::unexpect, 17); };
{
tl::expected<int, int> e = 21;
auto ret = e.and_then(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.and_then(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).and_then(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).and_then(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = e.and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.and_then(succeed);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.and_then(succeed);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).and_then(succeed);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).and_then(succeed);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).and_then(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
}
TEST_CASE("or_else", "[extensions.or_else]") {
using eptr = std::unique_ptr<int>;
auto succeed = [](int a) { (void)a; return tl::expected<int, int>(21 * 2); };
auto succeedptr = [](eptr e) { (void)e; return tl::expected<int,eptr>(21*2);};
auto fail = [](int a) { (void)a; return tl::expected<int,int>(tl::unexpect, 17);};
auto failptr = [](eptr e) { *e = 17;return tl::expected<int,eptr>(tl::unexpect, std::move(e));};
auto failvoid = [](int) {};
auto failvoidptr = [](const eptr&) { /* don't consume */};
auto consumeptr = [](eptr) {};
auto make_u_int = [](int n) { return std::unique_ptr<int>(new int(n));};
{
tl::expected<int, int> e = 21;
auto ret = e.or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, eptr> e = 21;
auto ret = std::move(e).or_else(succeedptr);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = e.or_else(fail);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.or_else(fail);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).or_else(fail);
REQUIRE(ret);
REQUIRE(ret == 21);
}
{
tl::expected<int, eptr> e = 21;
auto ret = std::move(e).or_else(failptr);
REQUIRE(ret);
REQUIRE(ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).or_else(fail);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
auto ret = std::move(e).or_else(succeedptr);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(succeed);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(failvoid);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.or_else(failvoid);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(failvoid);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
auto ret = std::move(e).or_else(failvoidptr);
REQUIRE(!ret);
REQUIRE(*ret.error() == 21);
}
{
tl::expected<int, eptr> e(tl::unexpect, make_u_int(21));
auto ret = std::move(e).or_else(consumeptr);
REQUIRE(!ret);
REQUIRE(ret.error() == nullptr);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(fail);
REQUIRE(!ret);
REQUIRE(ret.error() == 17);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).or_else(failvoid);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
}
TEST_CASE("Transform extensions", "[extensions.tronsfarm]") {
auto mul2 = [](int a) { return a * 2; };
auto ret_void = [](int a) { (void)a; };
{
tl::expected<int, int> e = 21;
auto ret = e.transform(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.transform(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).transform(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).transform(mul2);
REQUIRE(ret);
REQUIRE(*ret == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = e.transform(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e = 21;
auto ret = e.transform(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).transform(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).transform(ret_void);
REQUIRE(ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform(ret_void);
REQUIRE(!ret);
STATIC_REQUIRE(
(std::is_same<decltype(ret), tl::expected<void, int>>::value));
}
// mapping functions which return references
{
tl::expected<int, int> e(42);
auto ret = e.transform([](int& i) -> int& { return i; });
REQUIRE(ret);
REQUIRE(ret == 42);
}
}
TEST_CASE("Transform error extensions", "[extensions.transform_error]") {
auto mul2 = [](int a) { return a * 2; };
auto ret_void = [](int a) { (void)a; };
{
tl::expected<int, int> e = 21;
auto ret = e.transform_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.transform_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).transform_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).transform_error(mul2);
REQUIRE(ret);
REQUIRE(*ret == 21);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform_error(mul2);
REQUIRE(!ret);
REQUIRE(ret.error() == 42);
}
{
tl::expected<int, int> e = 21;
auto ret = e.transform_error(ret_void);
REQUIRE(ret);
}
{
const tl::expected<int, int> e = 21;
auto ret = e.transform_error(ret_void);
REQUIRE(ret);
}
{
tl::expected<int, int> e = 21;
auto ret = std::move(e).transform_error(ret_void);
REQUIRE(ret);
}
{
const tl::expected<int, int> e = 21;
auto ret = std::move(e).transform_error(ret_void);
REQUIRE(ret);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform_error(ret_void);
REQUIRE(!ret);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = e.transform_error(ret_void);
REQUIRE(!ret);
}
{
tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform_error(ret_void);
REQUIRE(!ret);
}
{
const tl::expected<int, int> e(tl::unexpect, 21);
auto ret = std::move(e).transform_error(ret_void);
REQUIRE(!ret);
}
}
struct S {
int x;
};
struct F {
int x;
};
TEST_CASE("14", "[issue.14]") {
auto res = tl::expected<S,F>{tl::unexpect, F{}};
res.map_error([](F f) {
(void)f;
});
}
TEST_CASE("32", "[issue.32]") {
int i = 0;
tl::expected<void, int> a;
a.map([&i]{i = 42;});
REQUIRE(i == 42);
auto x = a.map([]{return 42;});
REQUIRE(*x == 42);
}
+195
View File
@@ -0,0 +1,195 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
#include <string>
#include <memory>
using std::string;
tl::expected<int, string> getInt3(int val) { return val; }
tl::expected<int, string> getInt2(int val) { return val; }
tl::expected<int, string> getInt1() { return getInt2(5).and_then(getInt3); }
TEST_CASE("Issue 1", "[issues.1]") { getInt1(); }
tl::expected<int, int> operation1() { return 42; }
tl::expected<std::string, int> operation2(int const val) { (void)val; return "Bananas"; }
TEST_CASE("Issue 17", "[issues.17]") {
auto const intermediate_result = operation1();
intermediate_result.and_then(operation2);
}
struct a {};
struct b : a {};
auto doit() -> tl::expected<std::unique_ptr<b>, int> {
return tl::make_unexpected(0);
}
TEST_CASE("Issue 23", "[issues.23]") {
tl::expected<std::unique_ptr<a>, int> msg = doit();
REQUIRE(!msg.has_value());
}
TEST_CASE("Issue 26", "[issues.26]") {
tl::expected<a, int> exp = tl::expected<b, int>(tl::unexpect, 0);
REQUIRE(!exp.has_value());
}
struct foo {
foo() = default;
foo(foo &) = delete;
foo(foo &&){};
};
TEST_CASE("Issue 29", "[issues.29]") {
std::vector<foo> v;
v.emplace_back();
tl::expected<std::vector<foo>, int> ov = std::move(v);
REQUIRE(ov->size() == 1);
}
tl::expected<int, std::string> error() {
return tl::make_unexpected(std::string("error1 "));
}
std::string maperror(std::string s) { return s + "maperror "; }
TEST_CASE("Issue 30", "[issues.30]") {
error().map_error(maperror);
}
struct i31{
int i;
};
TEST_CASE("Issue 31", "[issues.31]") {
const tl::expected<i31, int> a = i31{42};
(void)a->i;
tl::expected< void, std::string > result;
tl::expected< void, std::string > result2 = result;
result2 = result;
}
TEST_CASE("Issue 33", "[issues.33]") {
tl::expected<void, int> res {tl::unexpect, 0};
REQUIRE(!res);
res = res.map_error([](int i) { (void)i; return 42; });
REQUIRE(res.error() == 42);
}
tl::expected<void, std::string> voidWork() { return {}; }
tl::expected<int, std::string> work2() { return 42; }
void errorhandling(std::string){}
TEST_CASE("Issue 34", "[issues.34]") {
tl::expected <int, std::string> result = voidWork ()
.and_then (work2);
result.map_error ([&] (std::string result) {errorhandling (result);});
}
struct non_copyable {
non_copyable(non_copyable&&) = default;
non_copyable(non_copyable const&) = delete;
non_copyable() = default;
};
TEST_CASE("Issue 42", "[issues.42]") {
tl::expected<non_copyable,int>{}.map([](non_copyable) {});
}
TEST_CASE("Issue 43", "[issues.43]") {
auto result = tl::expected<void, std::string>{};
result = tl::make_unexpected(std::string{ "foo" });
}
#if !(__GNUC__ <= 5)
#include <memory>
using MaybeDataPtr = tl::expected<int, std::unique_ptr<int>>;
MaybeDataPtr test(int i) noexcept
{
return std::move(i);
}
MaybeDataPtr test2(int i) noexcept
{
return std::move(i);
}
TEST_CASE("Issue 49", "[issues.49]") {
auto m = test(10)
.and_then(test2);
}
#endif
tl::expected<int, std::unique_ptr<std::string>> func()
{
return 1;
}
TEST_CASE("Issue 61", "[issues.61]") {
REQUIRE(func().value() == 1);
}
struct move_tracker {
int moved = 0;
move_tracker() = default;
move_tracker(move_tracker const &other) noexcept {};
move_tracker(move_tracker &&orig) noexcept
: moved(orig.moved + 1) {}
move_tracker &
operator=(move_tracker const &other) noexcept {};
move_tracker &operator=(move_tracker &&orig) noexcept {
moved = orig.moved + 1;
return *this;
}
};
TEST_CASE("Issue 122", "[issues.122]") {
tl::expected<move_tracker, int> res;
res.emplace();
REQUIRE(res.value().moved == 0);
}
#ifdef __cpp_deduction_guides
TEST_CASE("Issue 89", "[issues.89]") {
auto s = tl::unexpected("Some string");
REQUIRE(s.value() == std::string("Some string"));
}
#endif
struct S {
int i = 0;
int j = 0;
S(int i) : i(i) {}
S(int i, int j) : i(i), j(j) {}
};
TEST_CASE("Issue 107", "[issues.107]") {
tl::expected<int, S> ex1(tl::unexpect, 2);
tl::expected<int, S> ex2(tl::unexpect, 2, 2);
REQUIRE(ex1.error().i == 2);
REQUIRE(ex1.error().j == 0);
REQUIRE(ex2.error().i == 2);
REQUIRE(ex2.error().j == 2);
}
TEST_CASE("Issue 129", "[issues.129]") {
tl::expected<std::unique_ptr<int>, int> x1 {std::unique_ptr<int>(new int(4))};
tl::expected<std::unique_ptr<int>, int> y1 {std::unique_ptr<int>(new int(2))};
x1 = std::move(y1);
REQUIRE(**x1 == 2);
}
+2
View File
@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
+6
View File
@@ -0,0 +1,6 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
TEST_CASE("Noexcept", "[noexcept]") {
//TODO
}
+36
View File
@@ -0,0 +1,36 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
struct move_detector {
move_detector() = default;
move_detector(move_detector &&rhs) { rhs.been_moved = true; }
bool been_moved = false;
};
TEST_CASE("Observers", "[observers]") {
tl::expected<int,int> o1 = 42;
tl::expected<int,int> o2 {tl::unexpect, 0};
const tl::expected<int,int> o3 = 42;
REQUIRE(*o1 == 42);
REQUIRE(*o1 == o1.value());
REQUIRE(o2.value_or(42) == 42);
REQUIRE(o2.error() == 0);
REQUIRE(o3.value() == 42);
auto success = std::is_same<decltype(o1.value()), int &>::value;
REQUIRE(success);
success = std::is_same<decltype(o3.value()), const int &>::value;
REQUIRE(success);
success = std::is_same<decltype(std::move(o1).value()), int &&>::value;
REQUIRE(success);
#ifndef TL_EXPECTED_NO_CONSTRR
success = std::is_same<decltype(std::move(o3).value()), const int &&>::value;
REQUIRE(success);
#endif
tl::expected<move_detector,int> o4{tl::in_place};
move_detector o5 = std::move(o4).value();
REQUIRE(o4->been_moved);
REQUIRE(!o5.been_moved);
}
+17
View File
@@ -0,0 +1,17 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
TEST_CASE("Relational operators", "[relops]") {
tl::expected<int, int> o1 = 42;
tl::expected<int, int> o2{tl::unexpect, 0};
const tl::expected<int, int> o3 = 42;
REQUIRE(o1 == o1);
REQUIRE(o1 != o2);
REQUIRE(o1 == o3);
REQUIRE(o3 == o3);
tl::expected<void, int> o6;
REQUIRE(o6 == o6);
}
+107
View File
@@ -0,0 +1,107 @@
#include <catch2/catch.hpp>
#include <tl/expected.hpp>
struct no_throw {
no_throw(std::string i) : i(i) {}
std::string i;
};
struct canthrow_move {
canthrow_move(std::string i) : i(i) {}
canthrow_move(canthrow_move const &) = default;
canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
canthrow_move &operator=(canthrow_move &&) = default;
std::string i;
};
bool should_throw = false;
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
struct willthrow_move {
willthrow_move(std::string i) : i(i) {}
willthrow_move(willthrow_move const &) = default;
willthrow_move(willthrow_move &&other) : i(other.i) {
if (should_throw)
throw 0;
}
willthrow_move &operator=(willthrow_move &&) = default;
std::string i;
};
#endif // TL_EXPECTED_EXCEPTIONS_ENABLED
static_assert(tl::detail::is_swappable<no_throw>::value, "");
template <class T1, class T2> void swap_test() {
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
std::string s2 = "zyxwvutsrqponmlkjihgfedcba";
tl::expected<T1, T2> a{s1};
tl::expected<T1, T2> b{s2};
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
swap(a, b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
swap(a, b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
a = s1;
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b->i == s1);
a = s1;
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b->i == s1);
a = tl::unexpected<T2>(s1);
b = s2;
a.swap(b);
REQUIRE(a->i == s2);
REQUIRE(b.error().i == s1);
a = tl::unexpected<T2>(s1);
b = tl::unexpected<T2>(s2);
a.swap(b);
REQUIRE(a.error().i == s2);
REQUIRE(b.error().i == s1);
}
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
TEST_CASE("swap") {
swap_test<no_throw, no_throw>();
swap_test<no_throw, canthrow_move>();
swap_test<canthrow_move, no_throw>();
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
tl::expected<no_throw, willthrow_move> a{s1};
tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
should_throw = 1;
#ifdef _MSC_VER
//this seems to break catch on GCC and Clang
REQUIRE_THROWS(swap(a, b));
#endif
REQUIRE(a->i == s1);
REQUIRE(b.error().i == s2);
}
#endif // TL_EXPECTED_EXCEPTIONS_ENABLED
+32
View File
@@ -0,0 +1,32 @@
struct no_throw {
no_throw(std::string i) : i(i) {}
std::string i;
};
struct canthrow_move {
canthrow_move(std::string i) : i(i) {}
canthrow_move(canthrow_move const &) = default;
canthrow_move(canthrow_move &&other) noexcept(false) : i(other.i) {}
canthrow_move &operator=(canthrow_move &&) = default;
std::string i;
};
bool should_throw = false;
struct willthrow_move {
willthrow_move(std::string i) : i(i) {}
willthrow_move(willthrow_move const &) = default;
willthrow_move(willthrow_move &&other) : i(other.i) {
if (should_throw)
throw 0;
}
willthrow_move &operator=(willthrow_move &&) = default;
std::string i;
};
int main() {
std::string s1 = "abcdefghijklmnopqrstuvwxyz";
std::string s2 = "zyxwvutsrqponmlkjihgfedcbaxxx";
tl::expected<no_throw, willthrow_move> a{s1};
tl::expected<no_throw, willthrow_move> b{tl::unexpect, s2};
should_throw = 1;
swap(a, b);
}
+2
View File
@@ -0,0 +1,2 @@
Expected 1.1.0
https://github.com/TartanLlama/expected
+18
View File
@@ -0,0 +1,18 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
add_library(whereami STATIC)
target_sources(whereami PRIVATE
whereami/src/whereami.cpp
whereami/src/whereami.h
)
target_include_directories(whereami
SYSTEM PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/whereami/src"
)
+5
View File
@@ -0,0 +1,5 @@
Where Am I?
git master 2022-01-15
https://github.com/gpakosz/whereami
whereami.c renamed to whereami.cpp
+18
View File
@@ -0,0 +1,18 @@
Copyright Gregory Pakosz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+25
View File
@@ -0,0 +1,25 @@
--------------------------------------------------------------------------------
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
1. Bla bla bla
2. Montesqieu et camembert, vive la France, zut alors!
--------------------------------------------------------------------------------
WTFPLv2 is very permissive, see http://www.wtfpl.net/faq/
However, if this WTFPLV2 is REALLY a blocker and is the reason you can't use
this project, contact me and I'll dual license it.
--------------------------------------------------------------------------------
+123
View File
@@ -0,0 +1,123 @@
# Where Am I?
A drop-in two files library to locate the current executable and the current
module on the file system.
Supported platforms:
- Windows
- Linux
- Mac
- iOS
- Android
- QNX Neutrino
- FreeBSD
- NetBSD
- DragonFly BSD
- SunOS
- OpenBSD
Just drop `whereami.h` and `whereami.c` into your build and get started. (see
also [customizing compilation])
[customizing compilation]: #customizing-compilation
--------------------------------------------------------------------------------
## Usage
- `wai_getExecutablePath()` returns the path of the enclosing executable
- `wai_getModulePath()` returns the path of the enclosing module
Example usage:
- first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to retrieve
the length of the path
- allocate the destination buffer with `path = (char*)malloc(length + 1);`
- call `wai_getExecutablePath(path, length, &dirname_length)` again to retrieve
the path
- add a terminal `NUL` character with `path[length] = '\0';`
Here is the output of the example:
$ make -j -C _gnu-make
$ cp ./bin/mac-x86_64/library.dylib /tmp/
$ ./bin/mac-x86_64/executable --load-library=/tmp/library.dylib
executable path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
basename: executable
module path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
basename: executable
library loaded
executable path: /Users/gregory/Projects/whereami/bin/mac-x86_64/executable
dirname: /Users/gregory/Projects/whereami/bin/mac-x86_64
basename: executable
module path: /private/tmp/library.dylib
dirname: /private/tmp
basename: library.dylib
library unloaded
--------------------------------------------------------------------------------
## Customizing compilation
You can customize the library's behavior by defining the following macros:
- `WAI_FUNCSPEC`
- `WAI_PREFIX`
- `WAI_MALLOC`
- `WAI_REALLOC`
- `WAI_FREE`
## Compiling for Windows
There is a Visual Studio 2015 solution in the `_win-vs14/` folder.
## Compiling for Linux or Mac
There is a GNU Make 3.81 `MakeFile` in the `_gnu-make/` folder:
$ make -j -C _gnu-make/
## Compiling for Mac
See above if you want to compile from command line. Otherwise there is an Xcode
project located in the `_mac-xcode/` folder.
## Compiling for iOS
There is an Xcode project located in the `_ios-xcode/` folder.
If you prefer compiling from command line and deploying to a jailbroken device
through SSH, use:
$ make -j -C _gnu-make/ binsubdir=ios CC="$(xcrun --sdk iphoneos --find clang) -isysroot $(xcrun --sdk iphoneos --show-sdk-path) -arch armv7 -arch armv7s -arch arm64" postbuild="codesign -s 'iPhone Developer'"
## Compiling for Android
You will have to install the Android NDK, and point the `$NDK_ROOT` environment
variable to the NDK path: e.g. `export NDK_ROOT=/opt/android-ndk` (without a
trailing `/` character).
Next, the easy way is to make a standalone Android toolchain with the following
command:
$ $NDK_ROOT/build/tools/make_standalone_toolchain.py --arch=arm64 --api 21 --install-dir=/tmp/android-toolchain
Now you can compile the example by running:
$ make -j -C _gnu-make/ platform=android architecture=arm64 CC=/tmp/android-toolchain/bin/aarch64-linux-android-gcc CXX=/tmp/android-toolchain/bin/aarch64-linux-android-g++
Loading page aligned library straight from APKs is supported. To test, use the
following:
$ zip -Z store app bin/android/library.so
$ zipalign -v -f -p 4 ./app.zip ./app.apk
Then copy `bin/android/executable` and `app.apk` to your Android device and
there launch:
$ ./executable --load-library=$PWD/app.apk!/bin/android/library.so
+796
View File
@@ -0,0 +1,796 @@
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
// without any warranty.
// by Gregory Pakosz (@gpakosz)
// https://github.com/gpakosz/whereami
// in case you want to #include "whereami.c" in a larger compilation unit
#if !defined(WHEREAMI_H)
#include <whereami.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC)
#include <stdlib.h>
#endif
#if !defined(WAI_MALLOC)
#define WAI_MALLOC(size) malloc(size)
#endif
#if !defined(WAI_FREE)
#define WAI_FREE(p) free(p)
#endif
#if !defined(WAI_REALLOC)
#define WAI_REALLOC(p, size) realloc(p, size)
#endif
#ifndef WAI_NOINLINE
#if defined(_MSC_VER)
#define WAI_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
#define WAI_NOINLINE __attribute__((noinline))
#else
#error unsupported compiler
#endif
#endif
#if defined(_MSC_VER)
#define WAI_RETURN_ADDRESS() _ReturnAddress()
#elif defined(__GNUC__)
#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0))
#else
#error unsupported compiler
#endif
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <windows.h>
#include <intrin.h>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#include <stdbool.h>
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
{
wchar_t buffer1[MAX_PATH];
wchar_t buffer2[MAX_PATH];
wchar_t* path = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
DWORD size;
int length_, length__;
size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0]));
if (size == 0)
break;
else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0])))
{
DWORD size_ = size;
do
{
wchar_t* path_;
path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2);
if (!path_)
break;
size_ *= 2;
path = path_;
size = GetModuleFileNameW(module, path, size_);
}
while (size == size_);
if (size == size_)
break;
}
else
path = buffer1;
if (!_wfullpath(buffer2, path, MAX_PATH))
break;
length_ = (int)wcslen(buffer2);
length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL);
if (length__ == 0)
length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL);
if (length__ == 0)
break;
if (length__ <= capacity && dirname_length)
{
int i;
for (i = length__ - 1; i >= 0; --i)
{
if (out[i] == '\\')
{
*dirname_length = i;
break;
}
}
}
length = length__;
}
if (path != buffer1)
WAI_FREE(path);
return ok ? length : -1;
}
WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length);
}
WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
HMODULE module;
int length = -1;
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4054)
#endif
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module))
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
{
length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length);
}
return length;
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__linux__)
#include <linux/limits.h>
#else
#include <limits.h>
#endif
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include <stdbool.h>
#if !defined(WAI_PROC_SELF_EXE)
#if defined(__sun)
#define WAI_PROC_SELF_EXE "/proc/self/path/a.out"
#else
#define WAI_PROC_SELF_EXE "/proc/self/exe"
#endif
#endif
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer[PATH_MAX];
char* resolved = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
resolved = realpath(WAI_PROC_SELF_EXE, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
return ok ? length : -1;
}
#if !defined(WAI_PROC_SELF_MAPS_RETRY)
#define WAI_PROC_SELF_MAPS_RETRY 5
#endif
#if !defined(WAI_PROC_SELF_MAPS)
#if defined(__sun)
#define WAI_PROC_SELF_MAPS "/proc/self/map"
#else
#define WAI_PROC_SELF_MAPS "/proc/self/maps"
#endif
#endif
#if defined(__ANDROID__) || defined(ANDROID)
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#endif
#include <stdbool.h>
WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
int length = -1;
FILE* maps = NULL;
for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r)
{
maps = fopen(WAI_PROC_SELF_MAPS, "r");
if (!maps)
break;
for (;;)
{
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
uint64_t low, high;
char perms[5];
uint64_t offset;
uint32_t major, minor;
char path[PATH_MAX];
uint32_t inode;
if (!fgets(buffer, sizeof(buffer), maps))
break;
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
{
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
if (low <= addr && addr <= high)
{
char* resolved;
resolved = realpath(path, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
#if defined(__ANDROID__) || defined(ANDROID)
if (length > 4
&&buffer[length - 1] == 'k'
&&buffer[length - 2] == 'p'
&&buffer[length - 3] == 'a'
&&buffer[length - 4] == '.')
{
int fd = open(path, O_RDONLY);
if (fd == -1)
{
length = -1; // retry
break;
}
char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0);
if (begin == MAP_FAILED)
{
close(fd);
length = -1; // retry
break;
}
char* p = begin + offset - 30; // minimum size of local file header
while (p >= begin) // scan backwards
{
if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found
{
uint16_t length_ = *((uint16_t*)(p + 26));
if (length + 2 + length_ < (int)sizeof(buffer))
{
memcpy(&buffer[length], "!/", 2);
memcpy(&buffer[length + 2], p + 30, length_);
length += 2 + length_;
}
break;
}
--p;
}
munmap(begin, offset);
close(fd);
}
#endif
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
break;
}
}
}
fclose(maps);
maps = NULL;
if (length != -1)
break;
}
return length;
}
#elif defined(__APPLE__)
#define _DARWIN_BETTER_REALPATH
#include <mach-o/dyld.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <stdbool.h>
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer1[PATH_MAX];
char buffer2[PATH_MAX];
char* path = buffer1;
char* resolved = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
uint32_t size = (uint32_t)sizeof(buffer1);
if (_NSGetExecutablePath(path, &size) == -1)
{
path = (char*)WAI_MALLOC(size);
if (!_NSGetExecutablePath(path, &size))
break;
}
resolved = realpath(path, buffer2);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
if (path != buffer1)
WAI_FREE(path);
return ok ? length : -1;
}
WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
char buffer[PATH_MAX];
char* resolved = NULL;
int length = -1;
for(;;)
{
Dl_info info;
if (dladdr(WAI_RETURN_ADDRESS(), &info))
{
resolved = realpath(info.dli_fname, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
break;
}
return length;
}
#elif defined(__QNXNTO__)
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <stdbool.h>
#if !defined(WAI_PROC_SELF_EXE)
#define WAI_PROC_SELF_EXE "/proc/self/exefile"
#endif
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer1[PATH_MAX];
char buffer2[PATH_MAX];
char* resolved = NULL;
FILE* self_exe = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
self_exe = fopen(WAI_PROC_SELF_EXE, "r");
if (!self_exe)
break;
if (!fgets(buffer1, sizeof(buffer1), self_exe))
break;
resolved = realpath(buffer1, buffer2);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
fclose(self_exe);
return ok ? length : -1;
}
WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
char buffer[PATH_MAX];
char* resolved = NULL;
int length = -1;
for(;;)
{
Dl_info info;
if (dladdr(WAI_RETURN_ADDRESS(), &info))
{
resolved = realpath(info.dli_fname, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
break;
}
return length;
}
#elif defined(__DragonFly__) || defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <dlfcn.h>
#include <stdbool.h>
#if defined(__OpenBSD__)
#include <unistd.h>
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer1[4096];
char buffer2[PATH_MAX];
char buffer3[PATH_MAX];
char** argv = (char**)buffer1;
char* resolved = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
size_t size;
if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0)
break;
if (size > sizeof(buffer1))
{
argv = (char**)WAI_MALLOC(size);
if (!argv)
break;
}
if (sysctl(mib, 4, argv, &size, NULL, 0) != 0)
break;
if (strchr(argv[0], '/'))
{
resolved = realpath(argv[0], buffer2);
if (!resolved)
break;
}
else
{
const char* PATH = getenv("PATH");
if (!PATH)
break;
size_t argv0_length = strlen(argv[0]);
const char* begin = PATH;
while (1)
{
const char* separator = strchr(begin, ':');
const char* end = separator ? separator : begin + strlen(begin);
if (end - begin > 0)
{
if (*(end -1) == '/')
--end;
if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2))
{
memcpy(buffer2, begin, end - begin);
buffer2[end - begin] = '/';
memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1);
resolved = realpath(buffer2, buffer3);
if (resolved)
break;
}
}
if (!separator)
break;
begin = ++separator;
}
if (!resolved)
break;
}
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
if (argv != (char**)buffer1)
WAI_FREE(argv);
return ok ? length : -1;
}
#else
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
char buffer1[PATH_MAX];
char buffer2[PATH_MAX];
char* path = buffer1;
char* resolved = NULL;
int length = -1;
bool ok;
for (ok = false; !ok; ok = true)
{
#if defined(__NetBSD__)
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
#else
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
#endif
size_t size = sizeof(buffer1);
if (sysctl(mib, 4, path, &size, NULL, 0) != 0)
break;
resolved = realpath(path, buffer2);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
return ok ? length : -1;
}
#endif
WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
char buffer[PATH_MAX];
char* resolved = NULL;
int length = -1;
for(;;)
{
Dl_info info;
if (dladdr(WAI_RETURN_ADDRESS(), &info))
{
resolved = realpath(info.dli_fname, buffer);
if (!resolved)
break;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);
if (dirname_length)
{
int i;
for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
}
break;
}
return length;
}
#else
#error unsupported platform
#endif
#ifdef __cplusplus
}
#endif
+67
View File
@@ -0,0 +1,67 @@
// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses
// without any warranty.
// by Gregory Pakosz (@gpakosz)
// https://github.com/gpakosz/whereami
#ifndef WHEREAMI_H
#define WHEREAMI_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef WAI_FUNCSPEC
#define WAI_FUNCSPEC
#endif
#ifndef WAI_PREFIX
#define WAI_PREFIX(function) wai_##function
#endif
/**
* Returns the path to the current executable.
*
* Usage:
* - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to
* retrieve the length of the path
* - allocate the destination buffer with `path = (char*)malloc(length + 1);`
* - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the
* path
* - add a terminal NUL character with `path[length] = '\0';`
*
* @param out destination buffer, optional
* @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part
* of the path.
*
* @return the length of the executable path on success (without a terminal NUL
* character), otherwise `-1`
*/
WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
/**
* Returns the path to the current module
*
* Usage:
* - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve
* the length of the path
* - allocate the destination buffer with `path = (char*)malloc(length + 1);`
* - call `wai_getModulePath(path, length, NULL)` again to retrieve the path
* - add a terminal NUL character with `path[length] = '\0';`
*
* @param out destination buffer, optional
* @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part
* of the path.
*
* @return the length of the module path on success (without a terminal NUL
* character), otherwise `-1`
*/
WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length);
#ifdef __cplusplus
}
#endif
#endif // #ifndef WHEREAMI_H
+1
View File
@@ -0,0 +1 @@
gsmartcontrol.shaduri.dev
+12
View File
@@ -0,0 +1,12 @@
remote_theme: clearpathrobotics/jekyll-rtd-theme
title: GSmartControl
description: Hard disk drive and SSD health inspection tool
# Sitemap
url: "https://gsmartcontrol.shaduri.dev" # the base hostname & protocol for your site
plugins:
- jekyll-sitemap
exclude:
- CNAME
+25
View File
@@ -0,0 +1,25 @@
/* Hide sidebar footer with GitHub links */
div.addons-wrap {
display: none !important;
}
/* Hide page breadcrumbs */
div.navigation-top {
display: none !important;
}
/* Hide a line after page breadcrumbs */
div.content > hr {
display: none !important;
}
/* Customize navbar links */
a.caption {
text-transform: none !important;
padding-left: 12px !important;
padding: .5em !important;
color: #fff !important;
font-weight: normal !important;
}
+806
View File
@@ -0,0 +1,806 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> <image id="image0" width="256" height="256" x="0" y="0"
xlink:href="data:image/png;base64,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" />
</svg>

After

Width:  |  Height:  |  Size: 61 KiB

Some files were not shown because too many files have changed in this diff Show More